第一个题题目链接: POJ - 3254
第二个题题目链接:POJ - 1185
第一个题的题目大意:给你一个n*m的01矩阵,然后让你安排奶牛,只有为1的地方能安置奶牛,0的地方不能安置奶牛。当在一个为1的地方安置奶牛的时候,这个奶牛的四周都不能防止奶牛,会起冲突。然后问你一共有多少种安置方案。
具体思路:我们把每一行按照二进制压缩,然后每一次枚举合法的状态,看是否能安置上奶牛,然后枚举当前一行的时候,判断是否冲突就好了。然后最终计算答案的时候累加最后一行为某一个合法状态时的方案数。
AC代码:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 //dp[i][j]代表当前第i行为j时候的合法数。
2 #include<iostream>
3 #include<stdio.h>
4 #include<cmath>
5 #include<string>
6 #include<cstring>
7 #include<algorithm>
8 using namespace std;
9 # define ll long long
10 # define inf 0x3f3f3f3f
11 const int maxn = 5e3+100;
12 const int mod = 1e9;
13 int dp[20][maxn];
14 int a[20][20];
15 int n,m;
16 bool check(int t1,int t2)
17 {
18 if((((t2<<1)&t2)==0)&&(((t2>>1)&t2)==0))
19 {
20 for(int j=0; j<m; j++){
21 if(((t2&(1<<j))&&a[t1][j])||(!(t2&(1<<j))))
22 continue;
23 else
24 return false;
25 }
26 return true;
27 }
28 else
29 return false;
30 }
31 int main()
32 {
33 scanf("%d %d",&n,&m);
34 for(int i=0; i<n; i++)
35 {
36 for(int j=0; j<m; j++)
37 {
38 scanf("%d",&a[i][j]);
39 }
40 }
41 int maxstate=(1<<m)-1;
42 for(int i=0; i<n; i++)
43 {
44 if(i==0)
45 {
46 for(int j=0; j<=maxstate; j++)
47 {
48 if(check(i,j))
49 dp[i][j]++;
50 }
51 }
52 else
53 {
54 for(int j=0; j<=maxstate; j++)
55 {
56 for(int k=0; k<=maxstate; k++)
57 {
58 if(check(i,k)&&((j&k)==0))
59 {
60 dp[i][k]+=dp[i-1][j];
61 }
62 }
63 }
64 }
65 }
66 // for(int i=0;i<=maxstate;i++){
67 // cout<<i<<" "<<dp[0][i]<<endl;
68 // }
69 ll sum=0;
70 for(int i=0; i<=maxstate; i++)
71 {
72 sum=(sum+dp[n-1][i])%mod;
73 }
74 printf("%lld\n",sum);
75 return 0;
76 }
第二个题题目大意:中文,和上一个题不同的是这个题求的是最大的合法状态。
具体思路:这个题的难度比上一个题的难度增加了一点,上一个题dp[i][j]表示第i行选j这个状态时的合法数。但是这个题需要判断和上两行的关系。所以我们开一个三维数组。
dp[i][j][k]代表第i行选择j状态,第i-1行选k这个状态时的合法数。然后求一个最大值就好了。
具体判断的时候,如果当前的这一行和sto[i],a[i]&sto[j]==sto[j]的时候,就可以了。
注意需要先预处理出合法的状态,否则会爆内存,因为是个三维空间。
AC代码:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<iostream>
2 #include<stdio.h>
3 #include<cmath>
4 #include<string>
5 #include<algorithm>
6 #include<vector>
7 #include<vector>
8 using namespace std;
9 # define ll long long
10 # define inf 0x3f3f3f3f
11 const int maxn = 2e2+100;
12 const int mod = 1e9;
13 int dp[100+10][maxn][maxn];
14 int a[200];
15 char str[100+100][20];
16 int sto[maxn],num[maxn];
17 int n,m;
18 bool check(int t)
19 {
20 if(((t<<1)&t)||((t>>1)&t)||((t<<2)&t)||((t>>2)&t))
21 return false ;
22 return true;
23 }
24 int cal(int t)
25 {
26 int ans=0;
27 while(t)
28 {
29 ans+=(t&1);
30 t>>=1;
31 }
32 return ans;
33 }
34 int main()
35 {
36 scanf("%d %d",&n,&m);
37 for(int i=0; i<n; i++)
38 {
39 scanf("%s",str[i]);
40 for(int j=0; j<m; j++)
41 {
42 a[i]<<=1;
43 a[i]|=(str[i][j]=='P'?1:0);
44 }
45 }
46 int cnt=0;
47 int maxstate=(1<<m)-1;
48 for(int i=0; i<=maxstate; i++)
49 {
50 if(check(i))
51 {
52 sto[++cnt]=i;
53 num[cnt]=cal(i);
54 }
55 }
56 int maxx=0;
57 for(int i=0; i<n; i++)
58 {
59 if(i==0)
60 {
61 for(int j=1; j<=cnt; j++)
62 {
63 if((a[i]&sto[j])!=sto[j])continue;
64 dp[i][j][0]=max(dp[i][j][0],num[j]);
65 maxx=max(maxx,dp[i][j][0]);
66 }
67 }
68 else if(i==1)
69 {
70 for(int j=1; j<=cnt; j++)
71 {
72 if((sto[j]&a[i])!=sto[j])continue;
73 for(int k=1; k<=cnt; k++)
74 {
75 if((sto[k]&a[i-1])!=sto[k])continue;
76 if((sto[j]&sto[k])!=0)continue;
77 dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][0]+num[j]);
78 maxx=max(maxx,dp[i][j][k]);
79 }
80 }
81 }
82 else
83 {
84 for(int j=1; j<=cnt; j++)
85 {
86 if((sto[j]&a[i])!=sto[j])
87 continue;
88 for(int k=1; k<=cnt; k++)
89 {
90 if((sto[k]&a[i-1])!=sto[k]||(sto[k]&sto[j])!=0)
91 continue;
92 for(int L=1; L<=cnt; L++)
93 {
94 if((sto[L]&a[i-2])!=sto[L])
95 continue;
96 if((sto[j]&sto[L])!=0||(sto[k]&sto[L])!=0)
97 continue;
98 dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][L]+num[j]);
99 maxx=max(maxx,dp[i][j][k]);
100 }
101 }
102 }
103 }
104 }
105 printf("%d\n",maxx);
106 }