2019 cattle off more school second field F-Partition problem (search + pruning)

Partition problem

Topic Portal

Problem-solving ideas

Suppose the current value against teams s, if one of the red team assigned to a white team, s + = a value of the red team against all, s- = value against a team of all white. So we can assume that everyone in the red team, a man assigned to the white team, enumerate all cases seek maximum.
Then continue pruning:
1. We can let 1 is fixed on the white team.
2. Let incremented in the search process, in order to avoid duplication of enumeration.
3. Ensure sufficient number of remaining options, not necessarily enough.

code show as below

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;

inline int read(){
    int res = 0, w = 0; char ch = 0;
    while(!isdigit(ch)){
        w |= ch == '-', ch = getchar();
    }
    while(isdigit(ch)){
        res = (res << 3) + (res << 1) + (ch ^ 48);
        ch = getchar();
    }
    return w ? -res : res;
}

const int N = 30;

ll a[N][N];
bool in[N];
ll ans;
int n;

void dfs(int x, int c, ll sum)
{
    if(c == n){  //已经选择了n个人到白队
        ans = max(ans, sum);
        return;
    }
    for(int i = x + 1; i <= n + c + 1; i ++){ //保证剩下的够选
        ll temp = sum;
        for(int j = 1; j <= 2 * n; j ++){
            if(in[j])
                sum -= a[i][j];
            else
                sum += a[i][j];
        }
        in[i] = true;
        dfs(i, c + 1, sum);
        in[i] = false;  //回溯
        sum = temp;
    }
}

int main()
{
    cin >> n;
    for(int i = 1; i <= 2 * n; i ++){
        for(int j = 1; j <= 2 * n; j ++){
            a[i][j] = read();
        }
    }
    ll sum = 0;
    in[1] = true;  //1固定在白队
    for(int i = 2; i <= 2 * n; i ++)
        sum += a[1][i];
    dfs(1, 1, sum);
    cout << ans << endl;
    return 0;
}

Guess you like

Origin www.cnblogs.com/whisperlzw/p/11224870.html