作为一只菜鸡,本场比赛的题一下子把我搞懵逼了,在队友过了H之后,剩余的时间无所事事,于是就开始各种瞎搞F题,最后还真的用一种制杖操作给过了,在此放出这种方法,主要是因为我也不知道为什么能过,希望和各位大佬一起探讨一下,如果有大佬能给出样例就更好了,欢迎大家指正,求各位轻虐,鄙人在此谢过了233.

主体思路

    这种方法制杖的地方就在于,我是贪心写的orz(可把我牛逼坏了,叉会儿腰,等等......腰呢!?)。我最初的想法是,可以看成一开始就有2*n个人在一组,竞争值是0,这时你要依次取出n个人来,使最终的竞争值最大,然后我就想到了每一步贪心的方法......(是不是很奇葩?)
    最初的想法是这样的,在一开始先将矩阵的每一行的和求出来,这个值的含义是:第i行的和表示你取走第i个人之后增加的竞争值,每次选取最大的那个人,每当取走一个人,就把他所在的行和列删除,然后重复以上过程,n次后就可以得到一个值,但这个答案显然是错误的
    因为每次取下一个人的时候,都会影响之前所得到的竞争值,举个例子说,若是先取走了1号,当前竞争值是,假如接下来取走2号,那么原先的竞争值就会损失一部分,即,然后还会得到,所有从第2步开始,一直到第n步,需要考虑前行的和减去已选取的人的影响/的最大值,但是考虑了这一点之后依然没有过,赛后看结果只过了36%。
    除此之外,还有一个是贪心的起始点的问题,因为当选取第一个人的时候,另一边没有影响,在缺乏这一约束的情况下,起始点的选取应该如何抉择?所以我干脆试了次,然而依然没有过,赛后看结果,这份代码过了68%。
    至此,在赛中我已经放弃了这个方法,后来是学姐帮忙搜过的。(事实上学姐一开始就说搜索,还有枚举也可以,没想到赛后看代码真的有大佬400行枚举)
    赛后我又重新构思,发现好像这个方法只是不断贴近正确结果,例如第一步的选取,我依次尝试,就可以一定程度提高正确率,那么我第二步的选取也遍历一遍呢?按照这个数据量应该是可以把前四步的选取情况都暴力出来的,那么应该差不多过了。
    然后,我只考虑了前两步,后面直接贪,就过了......过了......了......

代码

//加了注释就成了14ms,我也不知道为什么
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
ll a[30][30];//存竞争值的数组 
bool bo[30];//好像是定义了没用上的东西 
ll jl[30];//同上 
struct node{
    ll z;//当前状态下对剩余人的竞争值之和 
    ll f;//标记序号 
    ll si;//已选取的人的影响值 
    ll bj;//标记贡献值,bj=z-si 
}b[30];//存每个人的信息 
bool cmp(node x,node y){
    return x.bj<y.bj;
}
int main(){
    ll n;
    node t1;
    scanf("%lld",&n);
    for(ll i=1;i<=n*2;i++){
        for(ll j=1;j<=n*2;j++){
            scanf("%lld",&a[i][j]);
        }
    }
    ll ans=0,ans1=0;
    for(int k=1;k<=n*2;k++)//初始点选取 
    {
        for(int q=1;q<=n*2;q++){//第二个点 
            ans=0;
            //每次重新初始化b,制杖操作,不要理会 
            for(int hh=1;hh<=n*2;hh++){
                b[hh].z=0;
            }
            for(ll i=1;i<=n*2;i++){
                for(ll j=1;j<=n*2;j++){
                    b[i].z+=a[i][j];
                    b[i].f=i;
                    b[i].si=0;
                }
            }
            if(k==q)
                continue;
            //把要选取的两个点放最后 
            t1=b[k];
            b[k]=b[n*2];
            b[n*2]=t1;
            t1=b[q];
            b[q]=b[n*2-1];
            b[n*2-1]=t1;
            //第一步的处理  
            ans+=b[n*2].z-b[n*2].si;
            for(ll j=1;j<=n*2-1;j++){
                    b[j].z-=a[b[j].f][b[n*2].f];
                    b[j].si+=a[b[j].f][b[n*2].f];
                    b[j].bj=b[j].z-b[j].si;
                }
            //剩下每一步的处理,每次对贡献值排序 
            for(ll i=2;i<=n;i++){
                ans+=b[n*2+1-i].z-b[n*2+1-i].si;
                for(ll j=1;j<=n*2-i;j++){
                    b[j].z-=a[b[j].f][b[n*2+1-i].f];
                    b[j].si+=a[b[j].f][b[n*2+1-i].f];
                    b[j].bj=b[j].z-b[j].si;
                }
                sort(b+1,b+n*2+1-i,cmp);
            }
            //更新答案最大值 
            ans1=max(ans1,ans);
        }
    }
    printf("%lld\n",ans1);
}
/*3
0 3 5 4 1 2
3 0 7 8 9 1
5 7 0 11 2 3
4 8 11 0 5 6
1 9 2 5 0 7
2 1 3 6 7 0*/