这个题和poj1185很像,都是两个放东西的地方不能相邻,而且状态还要受到原来地形的影响。
为什么叫状态dp呢,因为每个地方只有放和不放,所以可以用0和1表示这两种状态,然后进行状态转移。
同样,第k行的状态要受到第k-1行的约束,所以状态方程中要体现出第k-1行转移到第k行。设dp[k][i]为第k行的第i个状态对应的方案数。
那么dp[k][i]=sum(dp[k-1][j]) 约束条件 ((sta[i]&sta[j])==0);
最后ans=sum(dp[M][i])(i=1,2,..sum);
别忘了取模,白白WA了一次。。。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define mod 100000000
#define MAX 1<<12
int N,M;
__int64 ans;
int dp[15][MAX];
int sta[MAX],sum,presta[MAX],prenum;
int map[15][15];
void dfs(int i,int j,int p)
{
if(j>=N) {sta[++sum]=p;return ;}
if(map[i][j]==1) dfs(i,j+2,p|(1<<j));
dfs(i,j+1,p);
}
void DP()
{
int i,j,k;
ans=0;
prenum=1;
presta[1]=0;
//for(i=0;i<MAX;i++)
dp[0][1]=1;
for(k=1;k<=M;k++)
{
sum=0; //第k行对应的状态数。(即 有几个状态)
dfs(k,0,0); //求第k行对应的状态
for(i=1;i<=sum;i++)
{
for(j=1;j<=prenum;j++)
{
if((sta[i]&presta[j])==0)
{
dp[k][i]+=dp[k-1][j];
dp[k][i]%=mod;
}
}
}
for(i=1;i<=sum;i++) //把当前行给上一行
{
presta[i]=sta[i];
}
prenum=sum;
}
for(i=1;i<=prenum;i++)
{
ans+=dp[M][i];
ans%=mod;
}
}
int main()
{
int i,j;
scanf("%d%d",&M,&N);
for(i=1;i<=M;i++)
{
for(j=0;j<N;j++)
{
scanf("%d",&map[i][j]);
}
}
DP();
printf("%I64d\n",ans);
return 0;
}