poj1321 http://poj.org/problem?id=1321
我们可以把棋盘的每一行看做是一个状态,如果某一列放置了棋子,那么就标记为1,否则就标记为0.然后把它看成是一个二进制数,然后转为10进制数,就可以当做数组下标然后进行状态转移了
设dp[i][s] 为处理到第i行时,状态为s的方法数
那么我们枚举第i-1行的所有状态s
dp[i][s] += dp[i-1][s]; //表示第i行不放置棋子的方法数
dp[i][s|(1<<j)] += dp[i-1][s] //表示第i行第j列放置棋子的方法数 (前提是 chess[i][j]==‘#‘ && 状态s第j列没有放过棋子)
1 #include <stdio.h> 2 #include <string.h> 3 char chess[9][9];int dp[11][1<<8]; 4 int n,k; 5 int main() 6 { 7 int i,j,s,ss; 8 while(scanf("%d%d",&n,&k)!=EOF) 9 { 10 int ans = 0; 11 if(n==-1) return 0; 12 memset(dp,0,sizeof(dp)); 13 for(i=1; i<=n; ++i) 14 { 15 scanf("%s",chess[i]); 16 } 17 dp[0][0] = 1; 18 for(i=1; i<=n; ++i) 19 for(s=0; s<(1<<n); ++s) 20 { 21 22 for(j=0; j<n; ++j) 23 if(chess[i][j]==‘#‘&&((1<<j)&s)==0) 24 dp[i][s|1<<j] += dp[i-1][s];//表示第i行第j列放置棋子的方法数 25 dp[i][s] += dp[i-1][s]; //表示第i行不放置棋子的方法数 26 } 27 ///for(j=1; j<=n; ++j) 28 for(s=0; s<(1<<n); ++s) 29 { 30 i = s; 31 int cnt = 0 ; 32 for(;i;i-= i&-i)//统计状态s有多少个1,表示放了多少个棋子 33 cnt ++; 34 if(cnt==k) 35 ans+= dp[n][s]; 36 } 37 printf("%d\n",ans); 38 } 39 return 0; 40 }
时间: 2024-09-29 16:59:17