博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[Usaco2006 Nov]Corn Fields牧场的安排 壮压DP
阅读量:6449 次
发布时间:2019-06-23

本文共 1504 字,大约阅读时间需要 5 分钟。

看到第一眼就发觉是壮压DP

然后就三进制枚举子集吧。

这题真是壮压入门好题。。。

对于dp[i][j] 表示第i行,j状态下前i行的分配方案数。

那么dp[i][j]肯定是从i-1行转过来的

那么由于不能挨着放,那么我们肯定是枚举i - 1行状态时不能包含j的任何一位。

那么只要令k = ((1 << n) - 1) ^ j,k中肯定就不包含j的位了

是这样枚举k的子集

int sub = k;

do

{

    sub = k& (sub - 1);

}while(sub != k);

然后对每个子集,判断合法性,然后相加即可。

 

#include 
#include
#include
#include
#include
#define MAXN 1005#define INF 1000000000using namespace std;int dp[13][1 << 13];int n, m;int st[13];int mod = 100000000;bool ok(int s, int pos){ if((s | st[pos]) > st[pos]) return false; for(int i = 0; i < n; i++) if(s & (1 << i)) { if(s & (1 << (i + 1))) return false; } return true;}int main(){ int x; scanf("%d%d", &m, &n); for(int i = 1; i <= m; i++) { for(int j = 0; j < n; j++) { scanf("%d", &x); if(x) st[i] |= (1 << j); } } dp[0][0] = 1; for(int i = 1; i <= m; i++) { for(int k = 0; k < (1 << n); k++) { int s = ((1 << n) - 1) ^ k; if(ok(k, i)) { //printf("%d %d\n", k, s); dp[i][k] += dp[i - 1][0]; for(int j = s; j; j = s & (j - 1)) { if(ok(j, i - 1)) dp[i][k] = (dp[i][k] + dp[i - 1][j]) % mod; } } } } int ans = 0; for(int i = 0; i < (1 << n); i++) ans = (ans + dp[m][i]) % mod; printf("%d\n", ans); return 0;}

 

 

转载地址:http://halwo.baihongyu.com/

你可能感兴趣的文章
18年selenium3+python3+unittest自动化测试教程(下)
查看>>
Redis集群中删除/修改节点(master、slave)(实验)
查看>>
memcache数据库和redis数据库的区别(理论)
查看>>
我的友情链接
查看>>
MyBatis+Spring结合
查看>>
shell实例-判断apache是否正常启动
查看>>
SharedPreferences存储复杂对象解决方案
查看>>
Office 365之SkyDrive Pro
查看>>
脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么?
查看>>
无缝滚动实现原理分析【公告栏】
查看>>
Java Web 高性能开发
查看>>
redis-cli 命令总结
查看>>
CentOS 4.4双网卡绑定,实现负载均衡
查看>>
GitHub页面使用方法
查看>>
Python爬虫综述(笔记)
查看>>
Scala之柯里化和隐式转换
查看>>
wmic命令
查看>>
Merge and BottomUpSort
查看>>
reids 安装记录
查看>>
获取androdmanifest里面的meta-data
查看>>