Node:状压DP-1(棋子问题)

来源:互联网 发布:想学淘宝美工设计 编辑:程序博客网 时间:2024/06/07 03:14
#include <iostream>#include <stdio.h>#include <algorithm>#include <string.h>#include <stack>#include <queue>#define flush(arr,i) memset(arr,i,sizeof(arr))using namespace std;const int maxn = 310;int n, dp[10][maxn];/*在一个棋盘上放棋子,上下左右都没有棋子,一共有多少种方案状态压缩*//*补充把一个整数用二进制形式表示*/void display(int n){    if(!n)  return;    display(n >> 1);    printf("%d", n & 1);}int main(){    //freopen("data.txt","r",stdin);    //用1表示放棋子,0表示不妨,对于一行的状态,用一个数字的二进制位表示,0-2^n    //1.判断一个数不存在相邻的两个1 --> ((n >> 1) & n ) != 0    //2.判断一个数(状态)与他前一个数(状态)是否冲突 -> j & k == 0;    //3.转移方程:dp[i][j] -> 表示第i行状态为j时的方案数,我们求的是 dp[n][0....]    //            dp[i][j] = dp[i - 1][...k...]  j & k == 0    while(scanf("%d", &n))    {        int len = (1 << n);        flush(dp, 0);        dp[0][0] = 1;        //枚举行,代表当前计算到了第i行,第0行用来初始化        for(int i = 1; i <= n; i++)        {            //表示第i行我尝试的状态            for(int j = 0; j < len; j++)            {                //第i行状态合法                if(((j >> 1) & j) == 0)                {                    for(int k = 0; k < len; k++)                    //相邻两行之间状态不冲突,可以安放                        if(!(j & k))                            dp[i][j] += dp[i - 1][k];                }            }        }        int ans = 0;        for(int i = 0; i < len; i++)            ans += dp[n][i];        printf("%d\n", ans);    }    return 0;}

0 0
原创粉丝点击