2019頭の牛のオフより学校2番目のフィールドF-パーティションの問題(検索+剪定)

パーティションの問題

トピックポータル

問題解決のためのアイデア

白チームに割り当てられた赤チームの一つは、+ =すべてに対して、赤チームの値は、すべての白のチームに対して、S-値= sの場合は、チームのSに対する現在の値を仮定します。だから我々は、赤チームのみんな、白チームに割り当てられた男は、すべての場合は最大値を求めて列挙すると仮定することができます。
その後、剪定を続ける:
1.私たちは、1をさせることができ、白チームに固定されています。
列挙の重複を避けるために、検索処理でインクリメント2.ましょう。
3.必ずしも十分ではない、残りのオプションのに十分な数を確認してください。

コードは以下の通りです

#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;
}

おすすめ

転載: www.cnblogs.com/whisperlzw/p/11224870.html