Given 2N people, you need to assign each of them into either red team or white team such that each team consists of exactly N people and the total competitive value is maximized.
Total competitive value is the summation of competitive value of each pair of people in different team.
The equivalent equation is ∑2Ni=1∑2Nj=i+1(vij if i-th person is not in the same team as j-th person else 0)∑i=12N∑j=i+12N(vij if i-th person is not in the same team as j-th person else 0)
输入描述:
The first line of input contains an integers N. Following 2N lines each contains 2N space-separated integers vijvij is the j-th value of the i-th line which indicates the competitive value of person i and person j. * 1≤N≤141≤N≤14 * 0≤vij≤1090≤vij≤109 * vij=vjivij=vji
输出描述:
Output one line containing an integer representing the maximum possible total competitive value.
题意:给出2*n个人,以及给出他们之间的关系数值,现在要求将这些人分成两拨,一拨有n个人,然后求
这个最大
我们考虑对于集合A,B是不是等价于集合B,A,所以我们一开始将1放入A中,其余都放入B中,然后按照顺序从前向后枚举编号,将之从B中弹出,加入到A中,一个元素从B中弹出就需要减去与原A中元素的连边,加上与B中其他元素的连边即可。剪枝:可行性剪枝,如果将剩下的所有数字都加入到A中都无法凑够n个人说明不可行,剪掉。
时间复杂度为,这时间复杂度看上去不对劲,事实上加上剪枝可以3秒跑完emmm
方案数为组合数,算答案为2*n。
下面贴代码:
#include<bits/stdc++.h>usingnamespacestd;#define ll long long#define INF 0x3fffffff#define maxn 100005#define mod 1000000000intn;ll a[30][30],ans;//参数依次为:msk二进制下为1的位置为A中的元素,num为A中的元素个数,//pre表示区间[0,pre]已被使用,ans2为当前答案voidac(intmsk,intnum,intpre,ll ans2){if(num<<1==n){ans=max(ans,ans2);return;}if(((pre+1-num)<<1)>n)return;for(intnxt=pre+1;nxt<n;++nxt){ll t=ans2;for(inti=0;i<n;++i){if((msk>>i)&1)t-=a[nxt][i];//减掉与A中的连边;elset+=a[nxt][i];//加上与B中的连边;}ac(msk|(1<<nxt),num+1,nxt,t);}}intmain(){scanf("%d",&n);n<<=1;for(inti=0;i<n;++i)for(intj=0;j<n;++j)cin>>a[i][j];ll ans2=0;for(inti=0;i<n;++i)ans2+=a[0][i];ac(1,1,0,ans2);printf("%lld\n",ans);}