很经典的一道状态压缩DP~
刚开始写这道题目的时候分析了下,很明显的二进制压缩,每行有1024中情况,但是每两个阵地之间至少要相隔2,最后一算只有60种形态。
感觉不是很麻烦就写了,写着发现不对劲,由于一行需要由前面两行的状态决定,而我开的是二维数组,怎么也不能完全的把信息转换过来。。
一直很纠结于怎样传递信息,最后很无奈的上网搜了下代码,发现用三维的数组就可以了。。
DP[i][j][k]表示第i行当前为第j种状态,i-1行为第k种状态,那么状态转移方程就很容易搞定了。。
DP[i][j][k]=max(DP[i][j][k],DP[i-1][k][h]),其中(st[j]&st[k])==0,(st[j]&st[h])==0,(st[k]&st[h])==0.
st[j]表示第j种状态。
贴下代码:(很龊的)
1 # include<stdio.h>
2 # include<string.h>
3 int n,m;
4 int s[11]={1,2,4,8,16,32,64,128,256,512,1024};
5 char map[105][12];
6 int DP[102][65][65];
7 int st[65];
8 int judge(int i)//判断状态i是否符合要求
9 {
10 int end,cur,ans;
11 end=-3;
12 cur=-1;
13 while(i)
14 {
15 cur++;
16 ans=i%2;
17 if(ans==1)
18 {
19 if(cur-end<3)
20 return 0;
21 end=cur;
22 }
23 i/=2;
24 }
25 return 1;
26 }
27 int cmp(int i)//求i的二进制中有多少个1
28 {
29 int count=0;
30 while(i)
31 {
32 if(i%2) count++;
33 i/=2;
34 }
35 return count;
36 }
37 int max(int a,int b)
38 {
39 return a>b?a:b;
40 }
41 int main()
42 {
43 int i,j,k,h,i1,ans,temp;
44 k=0;
45 for(i=0;i<1024;i++)
46 {
47 if(judge(i)) st[k++]=i;
48 }
49 while(scanf("%d%d",&n,&m)!=EOF)
50 {
51 for(i=0;i<n;i++)
52 scanf("%s",map[i]);
53 memset(DP,0,sizeof(DP));
54 ans=0;
55 temp=0;
56 for(i=0;i<m;i++)
57 if(map[0][i]=='H') temp+=s[i];
58 for(i=0;i<k;i++)
59 {
60 if(st[i]>=s[m]) break;
61 /*for(j=0;j<m;j++)
62 if((st[i]&s[j]) && map[0][j]=='H') break;
63 if(j<m) continue;*/
64 if(st[i]&temp) continue;
65 for(j=0;j<k;j++)
66 {
67 if(st[j]>=s[m]) break;
68 DP[0][i][j]=cmp(st[i]);
69 }
70 ans=max(ans,DP[0][i][0]);
71 }
72 for(i=1;i<n;i++)
73 {
74 for(j=0;j<k;j++)
75 {
76 if(st[j]>=s[m]) break;
77 temp=0;
78 for(h=0;h<m;h++)
79 if((st[j]&s[h]) && map[i][h]=='H') break;
80 else if(st[j]&s[h]) temp++;
81 if(h<m) continue;
82 for(h=0;h<k;h++)
83 {
84 if(st[h]>=s[m]) break;
85 if(st[j]&st[h]) continue;
86 if(i==1) DP[1][j][h]=max(DP[1][j][h],DP[0][h][0]);
87 else
88 {
89 for(i1=0;i1<k;i1++)
90 {
91 if(st[i1]>=s[m]) break;
92 if(!(st[j]&st[i1]) && !(st[h]&st[i1])) DP[i][j][h]=max(DP[i][j][h],DP[i-1][h][i1]);
93 }
94 }
95 DP[i][j][h]+=temp;
96 ans=max(DP[i][j][h],ans);
97 }
98 }
99 }
100 printf("%d\n",ans);
101 }
102 return 0;
103 }