题意:
有一片
n∗m
的土地
(n≤12,m≤12)
,有些格子可以放牛,但要求放牛的格子不能相邻,求有多少种放牛方案。
题解:
首先
O(n∗(2m)∗(2m))
次方的DP很好想,但是要超时,考虑优化:
1.无用状态很多,先把所有有用状态预处理。判断有用状态:
status1&(status1<<1)==0
2.转移时把map压进int , O(1) 判断对于当前行状态是否合法。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<map>
#include<set>
using namespace std;
inline int read(){
char ch=getchar();int i=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();}
return i*f;
}
const int mod=1e8;
int n,m,mp[15],now;
int dp[2][(1<<12)+50];
int status[(1<<12)+50],tot;
inline bool valid(int sta){
return (sta&(sta<<1))==0;
}
int main(){
n=read(),m=read();
for(int i=1;i<=n;i++)
for(int j=0;j<m;j++)
mp[i]|=((read()^1)<<j);
int lim=(1<<m)-1;
for(int i=0;i<=lim;i++)
if(valid(i))status[++tot]=i;
dp[now][1]=1;
for(int i=1;i<=n;i++){
now^=1;
for(int j=1;j<=tot;j++){
dp[now][j]=0;
if(status[j]&mp[i])continue;
for(int k=1;k<=tot;k++){
if(status[j]&status[k])continue;
(dp[now][j]+=dp[now^1][k])%=mod;
}
}
}
int ans=0;
for(int i=1;i<=tot;i++)(ans+=dp[now][i])%=mod;
cout<<ans<<endl;
return 0;
}