状压DPCorn Fields牧场的安排
Posted 行码棋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了状压DPCorn Fields牧场的安排相关的知识,希望对你有一定的参考价值。
- 博客主页: https://blog.csdn.net/qq_50285142
- 欢迎点赞👍收藏✨关注❤留言 📝 如有错误,敬请指正
- 🎈点击领取大量学习资源🎈
题意:
n
行m
列牧场,每块都是一块土地,可以种草,要求两块草地不能相邻,且有的地不能种草,有多少种情况
状压DP:
一行的状态可以用一个数来表示,这个数的二进制形式就表示了一行的状态,二进制1
表示有草,0
代表无草
状态表示:
f
[
i
]
[
j
]
f[i][j]
f[i][j]表示前i
行来说,第i
行状态为j
的总情况数
状态转移:
f
[
i
]
[
j
]
=
∑
f
[
i
−
1
]
[
k
]
f[i][j] = \\sum f[i-1][k]
f[i][j]=∑f[i−1][k],k
代表第i-1
行满足的状态
即当前行某个状态的情况等于前一行所有状态的情况和
check()
用于检测一个状态是否有相邻的1
- 初始化:只有当没有1相邻且可以种草(肥沃地方种草,不肥沃地方不能种草)才能初始化为1
- 转移:前一行和当前行都需要
- 没有相邻1
- 可以种草(肥沃地方种草,不肥沃地方不能种草)
- 且两行之间的1也不能相邻 ,即 ! ( j & k ) !(j \\& k) !(j&k)
#include<iostream>
typedef long long ll;
const int N = 13,mod = 1e9;
int f[N][1<<N],st[N];
int n,m;
bool check(int x)
for(int i=0;i<m;i++)
if((x>>i)&1 && (x>>i+1)&1)
return false;
return true;
int main()
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
int x;
scanf("%d",&x);
st[i] <<= 1;
st[i] += x;
for(int i=0;i<1<<m;i++)
if(check(i)&&((i|st[1])==st[1]))
f[1][i] = 1;
for(int i=2;i<=n;i++)
for(int j=0;j<1<<m;j++)
for(int k=0;k<1<<m;k++)
if(((j|st[i])==st[i])&&((k|st[i-1])==st[i-1])&&(!(j&k))&&check(j)&&check(k))
f[i][j] = (f[i][j] + f[i-1][k] ) % mod;
ll res = 0;
for(int i=0;i<1<<m;i++)
res = (res + f[n][i]) % mod;
printf("%lld\\n",res);
return 0;
往期优质文章推荐
领取大量学习资源
以上是关于状压DPCorn Fields牧场的安排的主要内容,如果未能解决你的问题,请参考以下文章
bzoj1725 [Usaco2006 Nov]Corn Fields牧场的安排(状压dp)
BZOJ1725[Usaco2006 Nov]Corn Fields牧场的安排 状压DP
bzoj1725/Usaco2006 NovCorn Fields牧场的安排——状压dp
bzoj1725[Usaco2006 Nov]Corn Fields牧场的安排*