状态压缩dp【入门】

【1】POJ3254 Corn Fields
题目大意:
一个矩阵里有很多格子,每个格子有两种状态,可以放牧和不可以放牧,可以放牧用1表示,否则用0表示,在这块牧场放牛,要求两个相邻的方格不能同时放牛(不包括斜着的),即牛与牛不能相邻。问有多少种放牛方案(一头牛都不放也是一种方案)
输入
1<=n<=12,1<=m<=12
输出
一个mod100000000的整数
样例输入
2 3
1 1 1
0 1 0
样例输出
9
分析
从题意我们可以知道牛与牛之间不能相邻,我们可以很容易的想到可以一行一行的递推,因为每只牛能不能放只与上一行和当前这一行有关。
所以dp中有一个维度是用来表示第几行的,还有一个维度就是用来表示哪一行的状态的。
假设有m列,则状态最多只有(1<<m-1)种,这是显然的。因为他每一列只有放和不放这两种决策。
那么怎么表示状态是个关键问题,这就要用到状态压缩了,用二进制来表示某个状态,比如
0101代表的就是1、3列不放牛,2、4列放牛。这样不仅省空间省代码还省时间。
要用位运算是必须的。
参考分析
重点理解二进制的用处

#include <cstdio>
#include <cstring>
using namespace std;
const int N=1e4;
const int mod=1e9;
int corn[15],state[N];
int dp[15][N];
void init(int n,int &num)
{
    int all=(1<<n);//不考虑题目,n个二进制位所能表示的最大数+1
    for(int i=0;i<all;i++)
    {
        if(!(i&(i<<1)))//记下所有二进制位为0,1间隔的数
            state[++num]=i;
    }
}
int main()
{
    int m,n;
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        int c,num=0;//暂时满足条件的状态数
        memset(corn,0,sizeof(corn));//每一行的最大状态表示数
        memset(state,0,sizeof(state));//所有满足题目要求的状态
        memset(dp,0,sizeof(dp));
        init(n,num);//cout<<num<<endl;
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=n;j++)
            {
                scanf("%d",&c);
                if(c==0)//取反,和题意相反,便于后续处理
                    corn[i]+=(1<<(n-j));
            }
        }
        for(int i=1;i<=num;i++)
        {
            if(!(state[i]&corn[1]))
                dp[1][i]=1;//先确定第一行,初值
        }
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=num;j++)
            {
                if(state[j]&corn[i])
                    continue;
                for(int k=1;k<=num;k++)
                {
                    if(state[k]&corn[i-1])
                        continue;
                    if(state[k]&state[j])
                        continue;
                    dp[i][j]=(dp[i][j]+dp[i-1][k])%mod;
                }
            }
        }
        int ans=0;
        for(int i=1;i<=num;i++)
            ans=(ans+dp[m][i])%mod;
        printf("%d\n",ans);
    }
    return 0;
}

【2】POJ3311 Hie With The Pie
【3】POJ1185 炮兵阵地

发布了95 篇原创文章 · 获赞 8 · 访问量 1328
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览