poj 1185(状压dp)

题目链接:http://poj.org/problem?id=1185

思路:状态压缩经典题目,dp[i][j][k]表示第i行状态为j,(i-1)行状态为k时最多可以放置的士兵个数,于是我们可以得到递推方程:dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][l]+num[j]);(其中num[j]为该状态下可以放置的士兵的个数。至于具体怎么分析,这位大牛讲的很清楚:http://www.cnblogs.com/scau20110726/archive/2013/02/27/2935256.html

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 
 7 int dp[111][77][77];
 8 int row[111];
 9 int s[1<<12];//保存所有士兵合法的状态
10 int num[1<<12];
11 int n,m,ans,state;
12 char str[111];
13 
14 int Get_Num(int x)
15 {
16     int cnt=0;
17     while(x>0){
18         cnt++;
19         x=x&(x-1);
20     }
21     return cnt;
22 }
23 
24 int main()
25 {
26     while(~scanf("%d%d",&n,&m)){
27         memset(row,0,sizeof(row));
28         memset(dp,0,sizeof(dp));
29         memset(num,0,sizeof(num));
30         for(int i=0;i<n;i++){
31             scanf("%s",str);
32             for(int j=0;j<m;j++){
33                 if(str[j]=='H')row[i]=(row[i]<<1)|1;
34                 else row[i]<<=1;
35             }
36         }
37         state=0;
38         for(int i=0;i<(1<<m);i++){
39             if((i&(i<<1))||(i&(i<<2)))continue;
40             s[state]=i; //合法状态
41             num[state++]=Get_Num(i);//可以放置的士兵个数
42         }
43         for(int i=0;i<state;i++){
44             if(s[i]&row[0])continue;
45             dp[0][i][0]=num[i];
46         }
47         for(int i=1;i<n;i++){
48             for(int j=0;j<state;j++){
49                 if(row[i]&s[j])continue;
50                 for(int k=0;k<state;k++){
51                     if(s[j]&s[k])continue;  //i行与i-1行士兵相互攻击
52                     for(int l=0;l<state;l++){
53                         if(s[j]&s[l])continue;//i行与i-2行士兵相互攻击
54                         if(s[k]&s[l])continue;//i-1行与i-2行士兵相互攻击
55                         dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][l]+num[j]);
56                     }
57                 }
58             }
59         }
60         ans=0;
61         for(int i=0;i<state;i++){
62             for(int j=0;j<state;j++){
63                 ans=max(ans,dp[n-1][i][j]);
64             }
65         }
66         printf("%d\n",ans);
67     }
68     return 0;
69 }
70 
71                         
72 
73             
74 
75 
76                 
View Code

 

posted @ 2013-08-30 19:52  ihge2k  阅读(226)  评论(0编辑  收藏  举报