/* FILE: FrameStewartConjecture.cpp last change: 16-Sep-2013 author: Romeo Rizzi * a solver for problem FrameStewartConjecture based on recursion with memoization. * This problem appears more suitable to recursion with memoization versus dynamic programming as it might be difficult to anticipate which problems we do not actually need to solve and these might be quite a few. */ //#define NDEBUG // NDEBUG definita nella versione che consegno #include #ifndef NDEBUG # include // uso di cin e cout non consentito in versione finale #endif #include using namespace std; const int MAX_N = 10000; int n; const int MAX_K = 30; int k; const int UNKNOWN = -1; long int FS[MAX_N+1][MAX_K+1]; // FS[i][j] = the minimum number of moves in order to transport the tower according to a strategy obeying the Frame-Stewart conditions. long int min (long int a, long int b) { return (a= 0 ); assert( k >= 3 ); assert( n <= MAX_N ); assert( k <= MAX_K ); if( FS[n][k] != UNKNOWN) return FS[n][k]; if( n == 0 ) return FS[0][k] = 0; assert( n > 0 ); if( k == 3 ) return FS[n][3] = 1 + 2*recFS(n-1, 3); // the classical Hanoi if( n < k ) return FS[n][k] = 1 + 2*(n-1); assert( n >= k ); assert( k > 3 ); int tip_size = n-1; int best_tip_size; do {//ricerchiamo la miglior tip_size per una scomposizione alla Frame-Stewart FS[n][k] = 2*recFS(tip_size, k) + recFS(n-tip_size, k-1); best_tip_size = tip_size--; } while( FS[n][k] > 2*recFS(tip_size, k) + recFS(n-tip_size, k-1) ); // NOTA: abbiamo evitato di provare tutte le possibili tip_sizes avvalendoci di considerazioni di monotonia (non appena si incomincia a peggiorare non c'e' da aspettarsi alcun recupero). Questo puo' ridurre notevolmente i problemi generati anche se a priori e' difficile dire quali problemi serviranno. (Ed al tempo stesso era difficile anticipare su quali problemi si possa avere overflow). // cout << "n = " << n << ", k = " << k << ", FS[n][k] = " << FS[n][k] << ", best_tip_size = " << best_tip_size << endl; assert( FS[n-1][k] < FS[n][k] ); // overflow check return FS[n][k]; } int main() { ifstream fin("input.txt"); assert( fin ); fin >> n >> k; fin.close(); for(int nn = 0; nn <= n; nn++) for(int kk = 0; kk <= k; kk++) FS[nn][kk] = UNKNOWN; ofstream fout("output.txt"); fout << recFS(n, k) << endl; fout.close(); return 0; }