花了一个晚上看别人的代码然后才明白题的思路啊!!!然后写的时候一个劲的WA,然后才发现竟然什么也不中也是一种方案,自己给自己写的数据自己算出来的结果都是错的啊!!!!
题意:给出一个n*m的方格,每个方格可以种草也可以不中,但是种草的方格是不能相邻的,让求最多有多少种方案满足题意!!
解题思路:状态dp,采用二进制的数据表示每个方格种还是不种,然后化为十进制记录不同的状态,dp[n][m]代表第n行的第m中状态一个出现的方案个数,对于m的状态,要判断是否可以存在,并且是否有两个草地相邻,是否和第n-1行的的某种状态的草地相邻,如果相邻的话就舍弃!
然后就是求最后状态的所有之和了,千万不要写出来题了就很高兴而忘记模100000000了!今天中午木睡觉,现在太困了,睡觉去啦!
#include<iostream>
#include<cstdio>
#include<string>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<climits>
using namespace std;
#define rep(i,n) for(i=0; i<(n); i++)
#define reph(i,n,m) for(i=(n); i<=(m); i++)//正循环的
#define repd(i,n,m) for(i=(n); i>=(m); i--) //负循环的
#define fab(a) (a)>0?(a):0-(a)
#define ll long long
#define arc(a) (a)*(a)
#define inf 100000000 //最大值的
#define exp 0.0000001 //浮点型的
#define N 15 //记录开的数组
int dp[N][1<<N];//i行的第j状态时的方法数
int f[N],n,m;
bool panduan(int a,int b)//a为i所表示的,b为j所表示的
{
if((f[a] & b)!=b)//说明这种状态是不存在的
return false;
int x=3;
int i;
reph(i,1,m-1)
{
if((b & x)==x)//说明有连着的状态存在
return false;
x=x<<1;
}
return true;
}
int main()
{
int i,j,s;
while(scanf("%d%d",&n,&m)!=EOF)
{
reph(i,1,n)
{
f[i]=0;
reph(j,1,m)
{
scanf("%d",&s);//对于移位操作要加括号,优先级实在是分不清啊!!!1
f[i]=(f[i]<<1)+s;//记录的是输入的状态的
}
}
int r=1<<m;
memset(dp,0,sizeof(dp));
// reph(i,0,r-1)
dp[0][0]=1;//这样的赋值使得第一行的可以用的状态就是一次啦
reph(i,1,n)
{
reph(j,0,r-1)
{
if(panduan(i,j))
{
int k;
reph(k,0,r-1)
if((k & j)==0)//是没有可以挨着的
dp[i][j]=(dp[i][j]+dp[i-1][k])%inf;
}
// printf("%d ",dp[i][j]);
}
}
int ans=0;
reph(i,0,r-1)
ans=(ans+dp[n][i])%inf;
printf("%d\n",ans);
}
return 0;
}