poj 3254

19 篇文章 1 订阅

题目:

题意:
有n*m大的一个地方,1表示土地肥沃可以种植物,0表示不能种植物,问:在不许有两个植物相邻的情况下,有多少种放置的方法。
分析:直接dp因为状态较多,数组很难直接表示出来,我们采用二进制状态压缩的方法来解决问题。

分析:
第一道 状压dp 题哦!

所以先做好准备工作:–位运算 tata~ 我自己整理了一丢丢
& 与 同为1为1 or 为0

| 或 同0为0 or 为1

^ 异或 不同为1 相同为0

~ 取反 去相反的

左移 << 右边空出的位上补0,左边的位将从字头挤掉,其值相当于乘2。

右移 同理

那么来说这道题,

我们用dp【i】【j】表示第i行的j的状态。
那么如果满足条件的话,dp【i】【j】+=sum(dp【i】【j】)

所以,我们还需要 判断 。
判断有两个条件:
第一是:
在能放的地方放。

那么我们将 土地的情况和我当前的枚举情况 进行一下 & 的运算 如果等于我的枚举情况,就可以放。
举个例子:
1 1 1 那么 其中一种可以放置的情况 就是 11 0
1 1 1
&1 1 0
1 1 0
再举个返利:
1 0 0 不能放置的 011
1 0 0
&0 1 1
0 0 0 不合法呀~

第二是:

相邻的地方不能 放置啊 这个就很好说了 如果你把当前状态左移一位,在和原来比较的 就是相邻位置 的情况啦 同样是 & 运算。 如果不是0 就不可以放。

至此,这道题最关键的地方就讲完了。

另外还有一步把输进的 转化为 10 进制。。。

下面看代码就好了【【【其实还没写,,现在去写、、、、

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
//by mars_ch
int n,m,ans;
int state[13];
int dp[13][1<<13];   //dp[i][j]表示第i行的j状态,要枚举状态 
bool judge(int x,int y)
{
    if((state[x] & y)!=y) return 0;    //这是不能放置的,为什么看上边的解释啦
    if((y&(y<<1))!= 0) return 0;       //  相邻的是不可以的
    else return 1; 
 } 
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        state[i]=0;
        for(int j=1;j<=m;j++)
        {
            int k;
            scanf("%d",&k);
            state[i]=(state[i]<<1)+k;       // 把每一行都转成十进制数   eg 111 -> 7 
        }
    }
    memset(dp,0,sizeof(dp));
    dp[0][0]=1;
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=(1<<m);j++)
        {
            if(judge(i,j) == 0) continue;
            for(int k=0;k<=(1<<m);k++)
            {
                if(((j & k)!=0))continue;
                dp[i][j]+=dp[i-1][k];     //第i-1行  不能和第i行  相邻的。 
                dp[i][j]%=100000000;          
            }
        }
    }
    for(int i=0;i<=(1<<m);i++)
    {
        ans+=dp[n][i];
        ans%=100000000;
    }
    printf("%d\n",ans);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值