给你一个n*n的格子的棋盘,每个格子里面有一个非负数。
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大。
输入
包括多个测试实例,每个测试实例包括一个整数n 和n*n个非负数(n<=15)
输出
对于每个测试实例,输出可能取得的最大的和
样例输入
3
75 15 21
75 15 28
34 70 5
样例输出
188
第一个状压dp
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 7 int n; 8 int val[20][20]; 9 int q[40000];//存所有不相邻的情况,2^15=32768 10 int dp[20][40000];//dp[i][j]为0~i行在j情况下最大和 11 12 int main() 13 { 14 int maxn,cnt,sum;//maxn为最大数,cnt为不相邻情况种数,sum为该行某合理情况下数据和 15 while(~scanf("%d",&n)){ 16 for(int i=0;i<n;i++){ 17 for(int j=0;j<n;j++){ 18 scanf("%d",&val[i][j]); 19 } 20 } 21 memset(dp,0,sizeof(dp)); 22 maxn=(1<<n); 23 cnt=0; 24 for(int i=0;i<maxn;i++){ 25 if((i&(i<<1))==0){ 26 q[cnt++]=i; 27 } 28 } 29 for(int i=0;i<n;i++){ 30 for(int j=0;j<cnt;j++){ 31 sum=0; 32 for(int k=0;k<n;k++){ 33 if((q[j]&(1<<k))!=0){ 34 sum+=val[i][n-k-1]; 35 } 36 } 37 if(i==0){ 38 dp[i][j]=sum; 39 } 40 else if(i>0){ 41 for(int u=0;u<cnt;u++){ 42 if((q[u]&q[j])==0){ 43 dp[i][j]=max(dp[i][j],dp[i-1][u]+sum); 44 } 45 } 46 } 47 } 48 } 49 int res=0; 50 for(int i=0;i<cnt;i++){ 51 res=max(res,dp[n-1][i]); 52 } 53 cout<<res<<endl; 54 } 55 return 0; 56 }