题意:一个row*col的矩阵,每个格子是0或者1,1表示土壤肥沃可以种植草地,0则不可以。在种草地的格子可以放牛,但边相邻的两个格子不允许同时放牛,问总共有多少种放牛的方法?(不放牛也算一种情况)
http://poj.org/problem?id=3254
/*
折腾了 半个下午 和一个晚上 ,终于 把这道 状态dp 的题给 A 了,兴奋一下。。。。
前后想了 三个状态方程,前两个 被 k 掉了
我的一个错的 状态方程是
dp[r] = (第 r 行 合适的状态 个数) * dp[r - 1];
dp[r] 表示 从 第 0行 到 第 r 行的最大值
这个 最后 验证是错的 ,忽略了 r-1 行 和 r 行 不 匹配的情况
正确的 状态转移方程式 :(和 错的 就差那么一点)
dp[r][i] = 求和 dp[r - 1][j] ; 表示 第 r 行为 i 状态时 的最大值 它 == r-1 行所有合适的 状态 j 的 和 ;
*/
折腾了 半个下午 和一个晚上 ,终于 把这道 状态dp 的题给 A 了,兴奋一下。。。。
前后想了 三个状态方程,前两个 被 k 掉了
我的一个错的 状态方程是
dp[r] = (第 r 行 合适的状态 个数) * dp[r - 1];
dp[r] 表示 从 第 0行 到 第 r 行的最大值
这个 最后 验证是错的 ,忽略了 r-1 行 和 r 行 不 匹配的情况
正确的 状态转移方程式 :(和 错的 就差那么一点)
dp[r][i] = 求和 dp[r - 1][j] ; 表示 第 r 行为 i 状态时 的最大值 它 == r-1 行所有合适的 状态 j 的 和 ;
*/
1 #include<stdio.h>
2 #include<iostream>
3 #include<algorithm>
4 #include<cstring>
5 #include<cmath>
6 #include<queue>
7 #include<set>
8 #include<map>
9 #define Min(a,b) a>b?b:a
10 #define Max(a,b) a>b?a:b
11 #define CL(a,num) memset(a,num,sizeof(a));
12 #define inf 9999999
13 #define maxn 400
14 #define mod 100000000
15 #define eps 1e-6
16 #define ll long long
17 using namespace std;
18 ll dp[15][400];
19 int stat[400],cnt ,mat[15];
20 bool ok(int x)
21 {
22 if(x & (x<<1)) return false ;
23
24 return true ;
25 }
26 void find(int x)
27 {
28 for(int i = 0 ; i < (1 << x);++i)
29 {
30 if(ok(i))
31 {
32 stat[cnt++] = i;
33 }
34 }
35 }
36 int main()
37 {
38 int n,m,i,j,a;
39 while(scanf("%d%d",&n,&m)!=EOF)
40 {
41 cnt = 0 ;
42 CL(mat, 0);
43 for( i = 0 ; i < n ; ++i)
44 {
45 for( j = 0;j < m ;++j)
46 {
47 scanf("%d",&a);
48 if(a == 0) mat[i]|= (1 << j);
49 }
50 }
51
52 find(m);
53
54 CL(dp,0);
55 for( i = 0 ; i < cnt; ++i)//第 0 行 特殊 处理
56 {
57 if(!(stat[i]&mat[0]))
58 {
59
60 dp[0][i]++;
61 }
62 }
63
64
65
66 int r,f;
67 for( r = 1; r < n ; ++r)
68 {
69
70 for(i = 0; i < cnt; ++i)
71 {
72
73 if(stat[i]&mat[r])continue ;
74
75 for(j = 0 ; j < cnt; ++j)
76 {
77 if(stat[j]&mat[r - 1])continue ;
78 if((stat[i]&stat[j]))continue ;
79 dp[r][i] += dp[r - 1][j] ;
80
81 }
82
83
84
85 }
86 }
87
88 ll ans = 0;
89 for( i = 0 ; i < cnt ; ++i)
90 {
91 if(stat[i]&mat[n - 1])continue ;
92 ans += dp[n - 1][i];
93 ans %= mod;
94 }
95 printf("%lld\n",ans%mod);
96
97
98 }
99 }
2 #include<iostream>
3 #include<algorithm>
4 #include<cstring>
5 #include<cmath>
6 #include<queue>
7 #include<set>
8 #include<map>
9 #define Min(a,b) a>b?b:a
10 #define Max(a,b) a>b?a:b
11 #define CL(a,num) memset(a,num,sizeof(a));
12 #define inf 9999999
13 #define maxn 400
14 #define mod 100000000
15 #define eps 1e-6
16 #define ll long long
17 using namespace std;
18 ll dp[15][400];
19 int stat[400],cnt ,mat[15];
20 bool ok(int x)
21 {
22 if(x & (x<<1)) return false ;
23
24 return true ;
25 }
26 void find(int x)
27 {
28 for(int i = 0 ; i < (1 << x);++i)
29 {
30 if(ok(i))
31 {
32 stat[cnt++] = i;
33 }
34 }
35 }
36 int main()
37 {
38 int n,m,i,j,a;
39 while(scanf("%d%d",&n,&m)!=EOF)
40 {
41 cnt = 0 ;
42 CL(mat, 0);
43 for( i = 0 ; i < n ; ++i)
44 {
45 for( j = 0;j < m ;++j)
46 {
47 scanf("%d",&a);
48 if(a == 0) mat[i]|= (1 << j);
49 }
50 }
51
52 find(m);
53
54 CL(dp,0);
55 for( i = 0 ; i < cnt; ++i)//第 0 行 特殊 处理
56 {
57 if(!(stat[i]&mat[0]))
58 {
59
60 dp[0][i]++;
61 }
62 }
63
64
65
66 int r,f;
67 for( r = 1; r < n ; ++r)
68 {
69
70 for(i = 0; i < cnt; ++i)
71 {
72
73 if(stat[i]&mat[r])continue ;
74
75 for(j = 0 ; j < cnt; ++j)
76 {
77 if(stat[j]&mat[r - 1])continue ;
78 if((stat[i]&stat[j]))continue ;
79 dp[r][i] += dp[r - 1][j] ;
80
81 }
82
83
84
85 }
86 }
87
88 ll ans = 0;
89 for( i = 0 ; i < cnt ; ++i)
90 {
91 if(stat[i]&mat[n - 1])continue ;
92 ans += dp[n - 1][i];
93 ans %= mod;
94 }
95 printf("%lld\n",ans%mod);
96
97
98 }
99 }