#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;
}
Node:状压DP-1(棋子问题)
最新推荐文章于 2021-01-16 14:56:28 发布