棋盘放车问题
问题描述:
在n*n(n≤20)的方格棋盘上放置n个车,求使它们不能互相攻击的方案总数。
问题分析:车子的攻击是直线的上下和左右的。那么我们可以认为是一行一行扫描过来。有dp[i][j]。j表示排列状况
但是根据24点游戏的经验。我们完全可以直接根据排列状况来划分状态。(状态本身就是答案。)
0001 是由 0000得来的。
0011 是由 0010 + 0001得来的。
状态压缩的真正厉害之处不是以物体为刷层。而是以序列来刷层。并且一个循环过去。是从小到大有方向性的刷层。
(也许我可以用2种方法来写24点游戏)。一般来说还是刷层的方法比较好。。去处法DP。
#include<stdio.h> #include<string.h> int dp[30000]; // 8个棋盘 130个 n范围是9个棋盘 int main() { int n,i,j; while(scanf("%d",&n)!=EOF) { memset(dp,0,sizeof(dp)); dp[0] = 1; //还没填 对于不摆当然是1啦。 for(i=1; i<= (1<<n)-1;i++) //n个1,这一层是状态的扫描。 { for(j=i;j>0;j -= (j&-j)) { dp[i] += dp[i-(j&-j)]; //这个dp 是由当前的数的位置(i-(j&-j))的不同而获得的值 } } printf("%d\n",dp[(1<<n)-1]); } return 0; }