poj 1037 DP

来源:互联网 发布:西安办公软件培训中心 编辑:程序博客网 时间:2024/06/01 18:49

大致就是一位一位的遍历,比方说第一位,看1在最前有temp种情况,然后temp和C比较,如果比C大,第一位为1,否则C=C-temp,看2在第一位有多少种情况,然后和C比较,依次类推

long long DFS( int statu, int a, int b )  

statu == 0 表示之前是递减,然后有a个大数,b个小数的个数

statu == 1 表示之前是递增,然后有a个大数,b个小数的个数

注意n==1的情况,小心PE

AC代码如下:

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;long long dp[2][22][22];int N;long long DFS( int statu, int a, int b ){if( a == 0 && b == 1 ){if( statu == 0 ){return 0;}return 1;}if( b == 0 && a == 1 ){if( statu == 1 && a == 1){return 0;}return 1;}if( dp[statu][a][b] != -1 ){return dp[statu][a][b];}long long ans = 0;if( statu == 0 ){for( int i = 1; i <= a; i++ ){ans += DFS( 1, a - i, b + i - 1 );}}else{for( int i = 1; i <= b; i++ ){ans += DFS( 0, a + b - i, i - 1 );}}return dp[statu][a][b] = ans;}int main(){int T;long long C;bool mark[30];memset( dp, -1, sizeof( dp ) );cin >> T;while( T-- ){cin >> N >> C;memset( mark, false, sizeof( mark ) );int flag = 0;int pre;int xx;if( N == 1 ){cout << 1 << endl;continue;}for( int i = 1; i <= N; i++ ){int pos = 1;for( int j = 1; j <= N; j++ ){if( !mark[j] ){if( i > 2 ){if( xx ){if( j > pre ){pos++;continue;}}else{if( j < pre ){pos++;continue;}}}long long temp;if( !flag ){temp = DFS( 0, N - i + 1 - pos, pos - 1 ) + DFS( 1, N - i + 1 - pos, pos - 1 );}else{if( j > pre ){temp = DFS( 1, N - i + 1 - pos, pos - 1 );}else{temp = DFS( 0, N - i + 1 - pos, pos - 1 );}}if( temp >= C ){if( flag ){cout << " ";}else{flag = 1;}cout << j;if( i >= 2 ){if( j > pre ){xx = 1;}else{xx = 0;}}pre = j;mark[j] = true;break;}else{C -= temp;}pos++;}}}for( int i = 1; i <= N; i++ ){if( !mark[i] ){cout << " " << i;}}cout << endl;}return 0;}


0 0