网址链接:http://poj.org/problem?id=3254
题目大意:一个m行n列的矩阵,m和n都是小于12的,现在在这块土地上面种玉米
解题思路:
这个题目算是比较明显的状态压缩DP。而且这个题目有个好处就是状态数是比较小的。假如有1行全部是肥沃的土地,那么其最多也就只有400种左右可以种植的方案,因为不能相邻。
int
{
}
通过这个函数可以计算出每一行能允许的所有状态。
首先,我们可以计算出来第0行的所有种植方法
然后枚举接下来的每一行,并且枚举该行可能取的状态,要求是状态必须与草地相融合
枚举上一行的所有状态,要求是该行的状态必须与上一行的状态相融合,这样才能转化过来。
for(i=1;i枚举第i行
最后计算最后一行的所有的状态和即可。
源代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<algorithm>
#define mmod 100000000
using namespace std;
int m,n;
int cnt; //表示合法状态的总数
int state[520]; //表示合法的状态
int row[13]; //表示每一行的状态
int dp[13][520]; //表示第i行状态为j时可以放牛的方法数
int init()
{
int i;
cnt=0;
for(i=0;i<(1<<n);i++)
{
if((i&(i<<1))==0)
state[cnt++]=i; //表示状态i是合法的
}
return 0;
}
int main()
{
int i,j,x,k;
//freopen("in.txt","r",stdin);
while(scanf("%d%d",&m,&n)==2)
{
memset(row,0,sizeof(row));
init(); //对每行最多能选择的状态进行初始化
for(i=0;i
{
for(j=0;j
{
scanf("%d",&x);
row[i]+=(x<<j); //求取每一行草地的状态
}
}
memset(dp,0,sizeof(dp));
for(i=0;i
{
if((state[i]&row[0])==state[i])
{
dp[0][i]=1; //表示第0行可以选择第i个状态
}
}
for(i=1;i
{
for(j=0;j
{
if((row[i]&state[j])==state[j]) //草地与状态不冲突
{
for(k=0;k
{
if((state[j]&state[k])==0 && dp[i-1][k]!=0)
{
dp[i][j]=(dp[i][j]+dp[i-1][k])%mmod;
}
}
}
}
}
int ans=0;
for(j=0;j
{
if(dp[m-1][j]!=0)
ans=(ans+dp[m-1][j])%mmod;
}
printf("%d\n",ans%mmod);
}
return 0;
}