HDU 3811 DP状态压缩
算法:
dp[state][n]表示该状态前N位不是完美排列的个数。
步骤:
1.初始化第 0 位值
2.第i位从第i-1位推出,每一位,枚举(1<<N)种状态。
3.答案就是N!- dp[(1<<N)-1][N-1]
View Code
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<iostream> #include<vector> #include<string> #include<math.h> #include<map> #include<set> #include<algorithm> using namespace std; int dp[1<<18][20]; //dp[state][n]表示该状态前N位为非优美队列的桶数 int use[20][20]; int T, N, M; long long ans[21]; int fuck; void solve( ) { //给dp赋值,第1位 for( int i = 0; i < N; i++) { if( use[0][i] == 0 ) //如果第1位不是完美排列,则以该数字开头的排列值为1 dp[1<<i][0] = 1; } //n为从0到n推出 for( int i = 0; i < N; i++) { for( int j = 1; j < (1<<N); j++) { if( dp[j][i] != 0 ) { for( int k = 0; k < N; k++) { if( !(j & (1<<k) ) && use[i+1][k] == 0 ) //该为不是完美位,该数K只出现了一次 dp[j+(1<<k)][i+1] += dp[j][i]; //状态转移方程 } } } } printf("Case %d: %I64\n",fuck++,ans[N] - dp[(1<<N)-1][N-1]); } int main( ) { scanf("%d",&T); ans[0] = 1; fuck = 1; int a,b; for( int i = 1; i <= 18; i++) ans[i] = ans[i-1] * i; while(T--) { scanf("%d%d",&N,&M); memset(use,0,sizeof(use)); memset(dp,0,sizeof(dp)); for( int i = 1; i <= M; i++) { scanf("%d%d",&a,&b); a--,b--; use[a][b] = 1; } solve( ); } return 0; }
posted on 2012-08-06 14:51 more think, more gains 阅读(155) 评论(0) 编辑 收藏 举报