Problem C
Problem Description
新年伊始,集训队迎来了15级新生。教练打算将大家N(2<=N<=20)个人分成AB两队,已知每两个新生之间都有相互的思念值,如果分到一队的话经常见面不会思念,但是如果不被分到一队的话,他们就会无比思念对方,此时两个人之间的思念值为f(0<=f<=10000),教练想知道,分队使大家的思念值总和(即A队的每个人与B队的每个人之间的思念值的总和)达到的最大值是多少。PS:两个人如果在不同队伍才加入思念值总和
Input
多组用例,处理到EOF
对于每组用例:
第一行 N
接下来的N行,每行N个数
第i行第j个数表示i和j分到两个队时彼此的思念值
第i行第j个数等于第j行第i个数,当i=j时,思念值为0
对于每组用例:
第一行 N
接下来的N行,每行N个数
第i行第j个数表示i和j分到两个队时彼此的思念值
第i行第j个数等于第j行第i个数,当i=j时,思念值为0
Output
思念值总值的最大值
Sample Input
3 0 50 30 50 0 40 30 40 0
Sample Output
90#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n; int o[1<<20]; int a[24][24]; int d[24]; int sum; int f[1<<20]; int b[24]; void solve() { int lost=sum; int top=1<<n;//上限 f[0]=sum;//初始所有人都在groupA for(int i=1;i<top;++i) { int x=i; int num=0; while(x)//取出i的2进制中所有为1的部分 { int y=o[x&-x]; x-=x&-x; b[++num]=y; } f[i]=f[i-(1<<b[1])];//i的2进制最低位1在的位置被加入groupB int tmp=0; for(int j=2;j<=num;++j) tmp+=a[b[1]][b[j]];//记录当前b[1]与groupA成员的相互思念值 f[i]+=tmp-(d[b[1]]-tmp);//更新思念值 lost=min(lost,f[i]);//更新lost } printf("%d\n",sum-lost); } int main() { for(int i=0;i<20;++i) o[1<<i]=i; while(~scanf("%d",&n)) { memset(d,0,sizeof(d)); sum=0; for(int i=1;i<=n;++i) { for(int j=1;j<=n;++j) { scanf("%d",&a[i][j]); d[i]+=a[i][j];//d[i]记录i和其他所有的思念值 if(i<j) sum+=a[i][j];//记录所有的相互思念值 } } solve();//计算所有情况 } return 0; }