方格取数(1)
方格取数(1)
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 12156 Accepted Submission(s): 4557
Problem Description
给你一个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
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e5 + 10; int n; int c[26][26]; int dp[maxn],gcur[maxn],gpos[maxn],lans[maxn],lpos[maxn]; int gsize,lsize,cnt; void dfs(int row,int col,int pos,int val){ if(col>n){ gpos[++gsize]=pos; gcur[gsize]=val; return; } //cout<<pos<<endl; //cout<<(pos|(1<<col))<<endl; dfs(row,col+2,pos|(1<<col),val+c[row][col]); dfs(row,col+1,pos,val); } void solve(){ for(int i=1;i<=n;++i){ gsize=0; dfs(i,1,0,0); for(int j=1;j<=gsize;++j)dp[j]=0; for(int j=1;j<=gsize;++j){ for(int k=1;k<=lsize;++k){ if(gpos[j]&lpos[k])continue; dp[j]=max(dp[j],gcur[j]+lans[k]); } } for(int j=1;j<=gsize;++j){ lans[j]=dp[j]; lpos[j]=gpos[j]; } lsize=gsize; } } int main() { //freopen("1.txt","r",stdin); while(~scanf("%d",&n)){ for(int i=1;i<=n;++i){ for(int j=1;j<=n;++j){ scanf("%d",&c[i][j]); } } lpos[1]=0; lans[1]=0; lsize=1; solve(); int ans=0; for(int i=1;i<=lsize;++i){ ans=max(ans,lans[i]); } printf("%d\n",ans); } return 0; }