浏览器标题切换
浏览器标题切换end

寒假Day54:POJ3254-Corn Fields-状压dp入门题

题意:

给出n、m,接下去给出n行m列的状态(只有0或1),

只能在1的位置种植,并且如果这块地方种植了,那么其上下左右,也就是相邻部分不可种植,

问:总共有多少种种草方案。

 

思路:状压dp入门

 

状压dp求解什么样的问题?

数据范围比较小;简单算法无法解决。

 

一般动态规划无法解决,因为一般的dp转移方程只能从一边过来,

这一题需要上下左右都要考虑到。

 

本质:利用位运算记录状态,从而实现dp

本题的状态划分:每一行作为一个状态,

从而达到:第i行的状态从 i - 1 行转移,并且只从它转移。

也就是说,第 i 行的状态只取决于第 i - 1 行。

 

如何判断上一行状态和现在这一行状态是否冲突?

利用与运算,1&1=1,1&0=0,0&1=0,0&0=0,

如果种植起冲突的话,与运算结果为1,所以为0的时候可以种植啦。

 

如何判断当前位置/当前状态可行?

上下判断:是0表示可以种植并;左右判断:左右为0

将该行所代表的二进制数101010这样的形式左移或者右移,再和上面的步骤一样,利用与运算进行判断即可。

    for(int i=0; i<(1<<m); i++) //总状态数
    {
        int z=(i&(i<<1))==0;//左移判断该状态是否满足
        int y=((i&(i>>1))==0);//右移...
        book[i]=(z&&y);
        //or book[i]=((i&(i<<1))==0)&&((i&(i>>1))==0);
    }

 

 

表示每一行的状态:

因为只有0、1,所以可以考虑从二进制入手;

把每一行看作是一个二进制数,则这个数就代表这一行的状态。

 

dp[i][j]:代表第 i 行的状态是 j。

 

注意:由于符号优先级问题,不确定优先级的请一律加上括号

 

AC代码:(代码里有具体解析)

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<vector>
using namespace std;

const int N=15;
const int mod=100000000;
int n,m,a[N][N],dp[N][1<<N];
int h[N];//每一行空地的状态
int book[1<<N];//标记每个状态是否满足要求

int main()
{
    cin>>n>>m;
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            cin>>a[i][j];
            h[i]=(h[i]<<1)+a[i][j];//处理每一行状态,变成二进制状态,0也要处理
        }
    }
    //左右判断
    for(int i=0; i<(1<<m); i++) //总状态数
    {
        int z=(i&(i<<1))==0;//左移判断该状态是否满足
        int y=((i&(i>>1))==0);//右移...
        book[i]=(z&&y);
        //or book[i]=((i&(i<<1))==0)&&((i&(i>>1))==0);
    }
    dp[0][0]=1;
    for(int i=1; i<=n; i++)
    {
        for(int j=0; j<(1<<m); j++)//枚举第i行的每一个状态(列)
        {
            if(book[j]&&(j&h[i])==j)//状态可行and该位置是0可以种植
            {
                for(int k=0; k<(1<<m); k++)//不是j,枚举上一行的状态
                {
                    if((k&j)==0)//不冲突
                        dp[i][j]=(dp[i][j]+dp[i-1][k])%mod;
                }
            }
        }
    }
    int ans=0;
    for(int i=0; i<(1<<m); i++)
        ans=(ans+dp[n][i])%mod;//答案加起来
    cout<<ans<<endl;
    return 0;
}

 

  

 

posted @ 2020-03-17 23:12  抓水母的派大星  阅读(130)  评论(0编辑  收藏  举报