poj 3254
来源:互联网 发布:公需课挂机软件 编辑:程序博客网 时间:2024/06/06 19:34
题目:
戳
题意:
有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_chint 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;}
- POJ 3254
- poj 3254
- POJ 3254
- poj 3254
- poj 3254
- poj 3254
- poj 3254
- poj 3254
- poj-3254
- poj 3254
- poj 3254
- poj 3254
- poj 3254
- POJ 3254
- poj 3254
- poj 3254
- POJ 3254
- [状态压缩DP] Poj 3254, Poj 1185
- ssm框架学习---mybatis和spring的整合
- Nginx的模块开发指南
- void void* 空指针类型
- CodeIgniter是一套给PHP网站开发者使用的应用程序开发框架和工具包
- 为什么使用 CodeIgniter?
- poj 3254
- hdu 3416 spfa+sap
- 不敢死队问题
- 生产者和消费者模式(阻塞)
- 2016 百度之星 D题
- 硬币问题(DP)
- 【Android动画九章】-属性动画ObjectAnimator
- [C++]Random库--正态分布
- 基础真的很重要