hdu 2167(状压dp)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2167

思路:经典的状压dp题,前后,上下,对角8个位置不能取,状态压缩枚举即可所有情况,递推关系是为dp[i][j]=max(dp[i][j],dp[i-1][k]+sum[i][j]),具体的含义见code:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 
 7 int s[1<<16];
 8 int sum[16][1<<16];
 9 int dp[16][1<<16];
10 int map[16][16];
11 int n,m,ans;
12 
13 void Solve()
14 {
15     m=0;
16     for(int i=0;i<(1<<n);i++){
17         if((i&(i<<1))==0)s[m++]=i;//所有合法的状态
18     }
19     memset(sum,0,sizeof(sum));
20     memset(dp,0,sizeof(dp));
21     for(int i=0;i<n;i++){
22         for(int j=0;j<m;j++){
23             for(int k=0;k<n;k++){
24                 if(s[j]&(1<<k))sum[i][j]+=map[i][k];//sum又来保存每一行的合法状态下的所有数的和
25             }
26         }
27     }
28     for(int i=0;i<m;i++)dp[0][i]=sum[0][i];
29     for(int i=1;i<n;i++){
30         for(int j=0;j<m;j++){
31             for(int k=0;k<m;k++){ //上一行状态
32                 if(s[j]&s[k])continue;
33                 if(s[j]&(s[k]>>1))continue;
34                 if(s[j]&(s[k]<<1))continue;
35                 dp[i][j]=max(dp[i][j],dp[i-1][k]+sum[i][j]);
36             }
37         }
38     }
39     ans=0;
40     for(int i=0;i<m;i++){
41         ans=max(ans,dp[n-1][i]);
42     }
43     printf("%d
",ans);
44 }
45                 
46 
47 int main()
48 {
49     char str[111];
50     while(gets(str)){
51         int len=strlen(str);
52          n=0;
53         for(int i=0;i<len;i+=3){
54             map[0][n++]=(str[i]-'0')*10+(str[i+1]-'0');
55         }
56         for(int i=1;i<n;i++){
57             int nn=0;
58             gets(str);
59             for(int j=0;j<len;j+=3){
60                 map[i][nn++]=(str[j]-'0')*10+(str[j+1]-'0');
61             }
62         }
63         Solve();
64         getchar();
65     }
66     return 0;
67 }
68 
69             
View Code
原文地址:https://www.cnblogs.com/wally/p/3291761.html