给你一个n*n的格子的棋盘,每个格子里面有一个非负数。
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大。
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大。
Input包括多个测试实例,每个测试实例包括一个整数n 和n*n个非负数(n<=20)Output对于每个测试实例,输出可能取得的最大的和Sample Input
3 75 15 21 75 15 28 34 70 5
Sample Output
188
插头DP
插头DP其实挺好理解的(相比实际写代码来说),就是转移方程写起来神烦
因为主动不取数的决策忘了加max,WA了三次
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 using namespace std; 9 const int mxn=100010; 10 int read(){ 11 int x=0,f=1;char ch=getchar(); 12 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 13 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 14 return x*f; 15 } 16 int f[2][1<<20]; 17 int n; 18 int mp[21][21]; 19 int main(){ 20 int i,j; 21 while(scanf("%d",&n)!=EOF){ 22 for(i=0;i<n;i++) 23 for(j=0;j<n;j++) 24 mp[i][j]=read(); 25 int now=0,pre=1; 26 int ed=(1<<n)-1; 27 memset(f[now],-1,sizeof f[now]); 28 f[now][0]=0; 29 for(i=0;i<n;i++){ 30 for(j=0;j<n;j++){ 31 swap(now,pre); 32 memset(f[now],-1,sizeof f[now]); 33 for(int k=0;k<=ed;k++){ 34 int x=k&(1<<(j-1)); 35 int y=k&(1<<j); 36 f[now][k&(~(1<<j))]=max(f[now][k&(~(1<<j))],f[pre][k]); 37 if(!j && !y)f[now][k|(1<<j)]=max(f[now][k|(1<<j)],f[pre][k]+mp[i][j]); 38 if(j && !x && !y)f[now][k|(1<<j)]=max(f[now][k|(1<<j)],f[pre][k]+mp[i][j]); 39 if(!j && y)f[now][k^(1<<j)]=max(f[now][k^(1<<j)],f[pre][k]); 40 if(j && (y|x))f[now][k&(~(1<<j))]=max(f[now][k&(~(1<<j))],f[pre][k]); 41 } 42 } 43 } 44 int ans=0; 45 for(int k=0;k<=ed;k++)ans=max(ans,f[now][k]); 46 printf("%d\n",ans); 47 } 48 return 0; 49 }