题意:给出一个n行m列的草地,1表示肥沃,0表示贫瘠,现在要把一些牛放在肥沃的草地上,但是要求所有牛不能相邻,问你有多少种放法。
思路:
DP[i][j]=sum(dp[i-1][k]); i表示当前这一行,状态为j有多少种方案
首先,i行能放牛的状态由前一行i-1决定。所以我们只要知道前一行的状态就知道这一行的方案。因此要初始化第一行的状态dp[1][i]
要使当前这一行能用状态j表示则应瞒足两种条件
1 与当前这一行的地形符合
2 这一行状态与前一行的某一状态不冲突
x&(x<<1)表示x的二进制是否有两个相邻的1相邻
注意,初始化地形状态的时候,应该是0所在的位所构成的数
1 //#pragma comment(linker, "/STACK:167772160")//手动扩栈~~~~hdu 用c++交 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <iostream> 6 #include <queue> 7 #include <stack> 8 #include <cmath> 9 #include <set> 10 #include <algorithm> 11 #include <vector> 12 // #include<malloc.h> 13 using namespace std; 14 #define clc(a,b) memset(a,b,sizeof(a)) 15 #define LL long long 16 const int inf = 0x3f3f3f3f; 17 const double eps = 1e-5; 18 const double pi = acos(-1); 19 const LL MOD = 1e8; 20 const int N=1<<13; 21 // const LL p = 1e9+7; 22 // inline int r(){ 23 // int x=0,f=1;char ch=getchar(); 24 // while(ch>'9'||ch<'0'){if(ch=='-') f=-1;ch=getchar();} 25 // while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 26 // return x*f; 27 // } 28 29 int dp[15][N]; 30 int G[N]; 31 int line[N]; 32 bool judge1(int x){ 33 return (x&(x<<1)); 34 } 35 36 bool judge2(int x,int y){ 37 return G[x]&line[y]; 38 } 39 int main(){ 40 int m,n; 41 while(~scanf("%d%d",&n,&m)){ 42 // clc(G,0); 43 // clc(dp,0); 44 // clc(line,0); 45 for(int i=1;i<=n;i++){ 46 for(int j=1;j<=m;j++){ 47 int x; 48 scanf("%d",&x); 49 if(x==0){ 50 G[i]+=(1<<(m-j)); 51 } 52 } 53 } 54 55 int k=0; 56 for(int i=0;i<(1<<m);i++){ 57 if(!judge1(i)){ 58 line[k++]=i; 59 } 60 } 61 for(int i=0;i<k;i++){ 62 if(!judge2(1,i)) 63 dp[1][i]=1; 64 } 65 66 for(int i=2;i<=n;i++){ 67 for(int j=0;j<k;j++){ 68 if(judge2(i,j)) 69 continue; 70 for(int f=0;f<k;f++){ 71 if(judge2(i-1,f)) 72 continue; 73 if(!(line[j]&line[f])) 74 dp[i][j]+=dp[i-1][f]; 75 } 76 } 77 } 78 79 int ans=0; 80 for(int i=0;i<k;i++){ 81 ans+=dp[n][i]; 82 ans%=MOD; 83 } 84 printf("%d ",ans); 85 } 86 return 0; 87 }