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

#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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值