题目大意:在一个N*N的棋盘上放置M个国王,已知国王会攻击与它相邻的8个格子,要求放置的额国王不能相互攻击,求放置的方式有多少种。
分析:用dp[row][state][nOne],表示本行状态state时候的放置国王nOne时候情况有多少种,状态转移也比较简单了.....
代码如下:
===================================================================================================================================
#include<stdio.h> #include<algorithm> #include<string.h> using namespace std; const int MAXN = 1<<10; bool G[MAXN][MAXN]; int bit[MAXN], cnt, N, M; int one[MAXN]; long long dp[12][MAXN][107]; void DFS(int k, int state, int nOne) { if(k >= N) { one[cnt] = nOne; bit[cnt++] = state; return ; } DFS(k+1, state, nOne); DFS(k+2, state|(1<<k), nOne+1); } int main() { scanf("%d%d", &N, &M); DFS(0, 0, 0); for(int i=0; i<cnt; i++) for(int j=i; j<cnt; j++) { if((bit[i]&bit[j])+(bit[i]&(bit[j]<<1))+(bit[i]&(bit[j]>>1))==0) G[bit[i]][bit[j]] = G[bit[j]][bit[i]] = true; } dp[0][0][0] = 1; for(int i=1; i<=N; i++) for(int j=0; j<cnt; j++) for(int k=0; k<cnt; k++) { if(G[bit[j]][bit[k]]) { for(int t=one[j]; t<=M; t++) { dp[i][j][t] += dp[i-1][k][t-one[j]]; } } } long long ans=0; for(int i=0; i<cnt; i++) ans += dp[N][i][M]; printf("%lld ", ans); return 0; }