POJ 3254 poj3254 Corn Fields

题意:给出一个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\n",ans);
85     }
86     return 0;
87 }

 

转载于:https://www.cnblogs.com/ITUPC/p/5527951.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值