标签:
Description
Input
Output
Sample Input
3 75 15 21 75 15 28 34 70 5
Sample Output
188
思路:
先算出一行的每个dp,然后枚举以后的每一行,他的dp就是他加上上一行中不冲突的最大的那个dp.第二道状态压缩DP,还是参照了别人的博客,写了这两个状压DP,已经对状压DP理解了很多了,下一道题可以自己做了。(下面说的C题是上一篇博客的题)
代码:
1 #include<iostream> 2 #include<string> 3 #include<cstdio> 4 #include<cmath> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<iomanip> 9 #include<queue> 10 using namespace std; 11 int n,sn; 12 int dp[25][1<<13]; //这里就不需要dp[25][1<<20]了,只要能满足sn的大小就行 13 int map[25][25]; 14 int sta[1<<13]; 15 int max(int x,int y) 16 { 17 return x>y?x:y; 18 } 19 void init() 20 { 21 sn=0; //用sn代替(1<<n)表示状态会节省内存和时间,(1<<n)的方法参见C题 22 for(int i=0;i<(1<<n);i++) 23 { 24 if(i&(i<<1)) continue; 25 sta[sn++]=i; //记录互不相邻的数 26 } 27 } 28 int insum(int a,int b) 29 { 30 int sum=0,j=n; 31 while(b) 32 { 33 if(1&b) 34 sum+=map[a][j]; 35 j--; 36 b=b>>1; 37 } 38 return sum; 39 } 40 int main() 41 { 42 while(scanf("%d",&n)!=EOF) 43 { 44 memset(dp,0,sizeof(dp)); 45 for(int i=1;i<=n;i++) 46 for(int j=1;j<=n;j++) 47 scanf("%d",&map[i][j]); 48 init(); 49 for(int i=0;i<sn;i++) 50 dp[1][i]=insum(1,sta[i]); //这里这里直接用dp[1][i]而不是dp[1][sta[i]],会节省时间与内存 51 for(int i=2;i<=n;i++) 52 { 53 for(int j=0;j<sn;j++) 54 { 55 int tem=insum(i,sta[j]); 56 for(int k=0;k<sn;k++) 57 { 58 if((sta[j]&sta[k])) continue; //判断与上一行状态有没有相邻的数 59 dp[i][j]=max(dp[i][j],dp[i-1][k]+tem); 60 } 61 } 62 } 63 int sum=0; 64 for(int i=0;i<sn;i++) 65 sum=max(dp[n][i],sum); //最后求这一行中的最大的,因为一行中的每一个dp值 66 //已经加上了本行与其不相邻的数 67 printf("%d\n",sum); 68 } 69 return 0; 70 }
标签:
原文地址:http://www.cnblogs.com/--ZHIYUAN/p/5736030.html