【POJ 3254】Corn Fields(状压dp)
Corn Fields
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 11814 Accepted: 6179
Description
Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yummy corn for the cows on a number of squares. Regrettably, some of the squares are infertile and can’t be planted. Canny FJ knows that the cows dislike eating close to each other, so when choosing which squares to plant, he avoids choosing squares that are adjacent; no two chosen squares share an edge. He has not yet made the final choice as to which squares to plant.
Being a very open-minded man, Farmer John wants to consider all possible options for how to choose the squares for planting. He is so open-minded that he considers choosing no squares as a valid option! Please help Farmer John determine the number of ways he can choose the squares to plant.
Input
Line 1: Two space-separated integers: M and N
Lines 2..M+1: Line i+1 describes row i of the pasture with N space-separated integers indicating whether a square is fertile (1 for fertile, 0 for infertile)
Output
Line 1: One integer: the number of ways that FJ can choose the squares modulo 100,000,000.
Sample Input
2 3
1 1 1
0 1 0
Sample Output
9
Hint
Number the squares as follows:
1 2 3
4
There are four ways to plant only on one squares (1, 2, 3, or 4), three ways to plant on two squares (13, 14, or 34), 1 way to plant on three squares (134), and one way to plant on no squares. 4+3+1+1=9.
Source
USACO 2006 November Gold
[题意][给出一个n行m列的草地,1表示肥沃,0表示贫瘠,现在要把一些牛放在肥沃的草地上,但是要求所有牛不能相邻,问你有多少种放法。]
**【题解】【状压dp】
【状压DP】
【有这样的一些题目,它们具有DP问题的特性,但是状态中所包含的信息过多,如果要用数组来保存状态的话需要四维以上的数组。于是,我们就需要通过状态压缩来保存状态,而使用状态压缩来保存状态的DP就叫做状态压缩DP。 】**
状压dp一般都与位运算和用,见:
【http://blog.csdn.net/reverie_mjp/article/details/51336707】
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mod 100000000
using namespace std;
int f[15][8192],d[8192],mp[8192];
int n,m,tot,ans;
inline bool check1(int x)
{
return (x&(x<<1));
}
inline bool check2(int i,int x)
{
return (mp[i]&d[x]);
}
int main()
{
int i,j,k,x;
memset(f,0,sizeof(f));
memset(d,0,sizeof(d));
memset(mp,0,sizeof(mp));
scanf("%d%d",&n,&m);
for(i=1;i<=n;++i)
for(j=1;j<=m;++j)
{ scanf("%d",&x); if(!x) mp[i]+=(1<<(j-1)); }//按二进制存储整个网格
for(i=0;i<(1<<m);++i)
if(!check1(i)) d[tot++]=i;//枚举查找满足不相邻的排列方式(就一行来言)
for(i=0;i<tot;++i)
if(!check2(1,i)) f[1][i]=1;//预处理第一行按第i种排列方式能否符合牛都在肥沃土地的要求
for(i=2;i<=n;++i)
for(j=0;j<tot;++j)
{
if(check2(i,j)) continue;
for(k=0;k<tot;++k)
{
if(check2(i-1,k)) continue;
if(!(d[j]&d[k])) f[i][j]+=f[i-1][k];//如果上下两行之间也满足要求,把这种情况加进去
}
}
for(i=0;i<tot;++i)
ans+=f[n][i],ans%=mod;
printf("%d\n",ans);
return 0;
}

浙公网安备 33010602011771号