• 2019牛客暑期多校训练营(第二场)F.Partition problem


    链接:https://ac.nowcoder.com/acm/contest/882/F
    来源:牛客网

    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.
    示例1

    输入

    1
    0 3
    3 0

    输出

    3

    题意:
    将n*2个人分为两部分,每一个人与另外一半的每一个人贡献一个权值,求贡献和的最大值。
    思路:
    暴力搜索,最坏的复杂度是C(2*14,14),也就是差不多4e7,如果你确定某一个人在第一部分,还可以将复杂度除而2
    关于算贡献,你可以选择14*14的复杂度,但是肯定会T
    在搜索的时候,如果n=5,那么第一次选在第一部分的人就是 1 2 3 4 5.
    第二次选在第一部分的人就是 1 2 3 4 6,可以发现只有一个数字不同。
    分析一下,其实在整个搜索的过程中,也会出现很多这样只差一个的数组。
    于是,我们可以记录上一个状态,通过上个状态算出当前状态,这样可以减小很多算贡献的复杂度。
    就这样,我的代码跑了3700ms之后卡过去了。
    #include <bits/stdc++.h>
    #define eps 1e-8
    #define INF 0x3f3f3f3f
    #define PI acos(-1)
    #define lson l,mid,rt<<1
    #define rson mid+1,r,(rt<<1)+1
    #define CLR(x,y) memset((x),y,sizeof(x))
    #define fuck(x) cerr << #x << "=" << x << endl;
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int seed = 131;
    const int maxn = 1e5 + 5;
    const int mod = 1e9 + 7;
    int n;
    ll mp[30][30];
    bool vis[30];
    ll MIN;
    int v1[30];
    int v2[30];
    int prev1[30];
    int prev2[30];
    ll prenum = 0;
    ll C[35][35];
    //C[n][m]就是C(n,m)
    int tot;
    void init(int N) {
        for (int i = 0; i < N; i ++) {
            C[i][0] = C[i][i] = 1;
            for (int j = 1; j < i; j ++) {
                C[i][j] = C[i - 1][j] + C[i - 1][j - 1];
                C[i][j] %= mod;
            }
        }
    }
    
    
    void dfs(int x, int deep) {//必须>=x开始,已经选了num个人
        if (deep == n) {
            tot--;
            if(tot<0){return;}
            int cnt1 = 0;
            int cnt2 = 0;
            for (int i = 1; i <= 2 * n; i++) {
                if (vis[i]) v1[++cnt1] = i;
                else v2[++cnt2] = i;
            }
            ll num = prenum;
            int pos = 1;
            for (int i = 1; i <= n; i++) {
                if (v1[i] != prev1[i]) {
                    pos = i;
                    break;
                }
            }
            for (int i = pos; i <= n; i++) {
                for (int j = 1; j <= n; j++) {
                    num -= mp[prev1[i]][prev2[j]];
                    num -= mp[v1[i]][prev1[j]];
                }
                for (int j = 1; j <= n; j++) {
                    num += mp[v1[i]][v2[j]];
                    num += mp[v1[j]][prev1[i]];
                }
            }
            MIN = max(MIN, num);
            for (int i = 1; i <= n; i++) {
                prev1[i] = v1[i];
                prev2[i] = v2[i];
                prenum = num;
            }
            return ;
        }
        for (int i = x + 1; i <= 2 * n; i++) {
            vis[i] = 1;
            dfs(i, deep + 1);
            if(tot<0){return;}
            vis[i] = 0;
        }
    }
    int main() {
        MIN = -1;
        init(30);
        scanf("%d", &n);
        tot=C[2*n][n];
        tot/=2;
        for (int i = 1; i <= 2 * n; i++) {
            for (int j = 1; j <= 2 * n; j++) {
                scanf("%lld", &mp[i][j]);
            }
        }
        dfs(0, 0);
        printf("%lld
    ", MIN);
        return 0;
    }
    View Code
  • 相关阅读:
    [排错] VO对象和POJO对象的关系
    celery(异步处理)+redis
    django开发经验(每日生鲜)
    开发流程
    linux 使用问题
    磁盘的操作
    文件系统的简单操作
    LINUX磁盘与档案系统
    文件操作
    Linux文档修改
  • 原文地址:https://www.cnblogs.com/ZGQblogs/p/11218583.html
Copyright © 2020-2023  润新知