Programación dinámica-4-Hanoi-Tower

descripción

"La Torre de Hanoi" es un juego antiguo muy conocido. Ahora cambiemos ligeramente la pregunta: si hay 4 pilares en total en lugar de 3, ¿cuántas veces necesitas mover las placas al menos para mover todas las placas del primer pilar al cuarto pilar?

Para mayor comodidad de programación, solo necesita generar el valor de mod de resultado 10000 .

formato

Formato de entrada

Un entero positivo n. (0 <n <= 50000)

Formato de salida

Un número entero positivo, que representa el número mínimo de movimientos mod 10000 necesarios para mover n placas del primer pilar al cuarto pilar.

Ejemplo 1

Entrada de muestra 1

2

Salida de muestra 1

3

Resolución de problemas

  1. Cuando se colocan tres pilares, el número mínimo de movimiento de n placas es dp_3 [n]. En primer lugar, dp_3 [n] = 2 * dp_3 [n-1] + 1 se puede obtener rápidamente mediante la fórmula recursiva.
  2. Cuando hay 4 columnas, el número mínimo de movimiento de n placas es dp_4 [n], puede mover k placas en las n placas a una de las columnas primero, el número de movimientos es dp_4 [k], y luego hay nk placas a la izquierda Mueva dp_3 [n-k] veces para llegar a otra columna, luego mueva las k placas restantes a la columna de n-k placas, mueva dp_4 [k] veces, entonces dp_4 [n] = min (2 * dp_4 [k] + dp_3 [nk]), 1 <= k <i.
  3. Dado que el problema n puede ser de hasta 50000, obviamente la recursividad directa no es suficiente, así que enumere los primeros 20 elementos de dp_4 [] y encuentre la ley para resolverlo.

Código

Enumere los primeros 20 elementos y encuentre el patrón:

	int n;
    cin >> n;
    memset(dp_4, 0x3f, sizeof(dp_4));
    dp_3[1] = 1;
    dp_4[1] = 1;
    for (int i = 2; i <= n; i++) dp_3[i] = 2 * dp_3[i - 1] % p + 1;
    for (int i = 2; i <= n; i++) {
    
    
        for (int j = 1; j < i; j++) {
    
    
            dp_4[i] = min(dp_4[i], 2 * dp_4[j] + dp_3[i - j]);
        }
    }
    for (int i = 1; i <= n; i++) cout << dp_4[i] << " ";
    cout << endl;

resultado de la operación:

20
1 3 5 9 13 17 25 33 41 49 65 81 97 113 129 161 193 225 257 289

Es muy sencillo encontrar la regla, volver a listar la nueva recurrencia

#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
const int p = 1e4;
const int maxn = 5e4 + 2;
// int dp_3[maxn];
// int dp_4[maxn];
int dp[maxn];

int main() {
    
    
    int n;
    cin >> n;
    // memset(dp_4, 0x3f, sizeof(dp_4));
    // dp_3[1] = 1;
    // dp_4[1] = 1;
    // for (int i = 2; i <= n; i++) dp_3[i] = 2 * dp_3[i - 1] % p + 1;
    // for (int i = 2; i <= n; i++) {
    
    
    //     for (int j = 1; j < i; j++) {
    
    
    //         dp_4[i] = min(dp_4[i], 2 * dp_4[j] + dp_3[i - j]);
    //     }
    // }
    // for (int i = 1; i <= n; i++) cout << dp_4[i] << " ";
    // cout << endl;

    dp[1] = 1;
    int add = 2;  //每次增加的权值
    int cnt = 2;  //增加的次数
    for (int i = 2, j = 0; i <= n; i++) {
    
    
        dp[i] = (dp[i - 1] + add) % p;
        if (++j == cnt) {
    
    
            cnt++;
            j = 0;
            add = (add << 1) % p;
        }
    }
    // for (int i = 1; i <= n; i++) cout << dp_4[i] << " " << dp[i] << endl;
    // cout << cnt << endl;
    cout << dp[n] << endl;

    system("pause");
    return 0;
}

Supongo que te gusta

Origin blog.csdn.net/qq_45349225/article/details/109407200
Recomendado
Clasificación