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=12Nj=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.
* 1N141≤N≤14 * 0vij1090≤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 1000000000
intn;
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中的连边;
            else
                t+=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);
}