More than 2019 cattle off summer school camp (second game) - F - Partition problem - enumeration

https://ac.nowcoder.com/acm/contest/882/F
Pange code was passed card, the card does not have to write their own past, with an estimated evaluation machine related.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=30;
int g[maxn][maxn],n;
ll ans;
inline void dfs(int mask,int last,int dep,ll sum)
{
    if(!dep){
        if(sum>ans) ans=sum;
        return;
    }
    if(n-last-1<dep) return;
    for(int i=last+1;i<n;++i){
        ll tmp=sum;
        for(int j=0;j<n;++j){
            if(mask>>j&1) tmp-=g[i][j];
            else tmp+=g[i][j];
        }
        dfs(mask|(1<<i),i,dep-1,tmp);
    }
    return;
}
int main()
{
    #ifdef local
    freopen("a.txt","r",stdin);
    #endif // local
    scanf("%d",&n);
    n<<=1;
    for(int i=0;i<n;++i){
        for(int j=0;j<n;++j){
            scanf("%d",&g[i][j]);
        }
    }
    ll sum=0;
    for(int i=1;i<n;++i) sum+=g[0][i];
    dfs(1,0,n/2-1,sum);
    printf("%lld\n",ans);
    return 0;
}

Card should be the most usual idea is folded in half, the contribution of the inner half of the pretreatment 2 ^ 14, again the contribution of the latter half of the inside of the pretreatment.
The answer is, of course, chose the first half of the i 1, choose the latter part of the ni 1, consider the impact of their new merged together.
Then, of course, the violence of each of a first half of a second half of a match each 0. Then the second half of each of one pair of matching first half 0 time.

Complexity of the word, each combination actually be traversed, \ (n-C_ {2N} ^ \) and ultimately a. But each time the number of merger and only about 1. So that requires preprocessing time to "0 the first half of the state's contribution to the second half of a 1" also do it.

Theoretically faster than the search. This is an annotated edition of the code of coffee chicken:

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

ll s[1 << 14], t[1 << 14], p[14], q[14], ret, ans;
int c[30][30], n, d[1 << 14];

//枚举t状态
void dfs(int step, int w, int mask, ll sum) {
    //对后半部分搜索完毕
    if(step == n) {
        ret = max(ret, sum + t[mask]);
        return;
    }
    //选择的人没满,后半部分可以再选一个
    if(w < n)
        //这一次step选1,也就是后半部分的第step位选1,后半部分第step个选1那当然要加step
        dfs(step + 1, w + 1, mask | (1 << step), sum + p[step]);
    //等价于n-step+w>n,也就是剩下的人+已选的人超过需要选的人,那么这一步可以选0
    if(w > step)
        dfs(step + 1, w, mask, sum + q[step]);
}

int main() {
#ifdef Yinku
    freopen("Yinku.in", "r", stdin);
#endif // Yinku
    scanf("%d", &n);
    //d[i]表示i状态有多少个1,用于连接两个集合使用
    d[0] = 0;
    for(int i = 1; i < (1 << n); i++)
        d[i] = d[i / 2] + i % 2;
    for(int i = 0; i < n * 2; i++)
        for(int j = 0; j < n * 2; j++)
            scanf("%d", &c[i][j]);
    //折半枚举
    //s[i]表示前半部分内部的贡献,t[i]表示后半部分内部的贡献
    for(int i = 0; i < (1 << n); i++) {
        for(int j = 0; j < n; j++)
            if(!(i & (1 << j)))
                for(int k = j + 1; k < n; k++)
                    if(i & (1 << k))
                        s[i] += c[j][k], t[i] += c[j + n][k + n];
        for(int j = 0; j < n; j++)
            if(i & (1 << j))
                for(int k = j + 1; k < n; k++)
                    if(!(i & (1 << k)))
                        s[i] += c[j][k], t[i] += c[j + n][k + n];
    }
    //折半枚举
    //p[k]表示当前前半部分为i状态,后半部分的第k个为1的时候的对前半部分的所有的0产生的贡献
    //q[k]表示当前前半部分为i状态,后半部分的第k个为0的时候的对前半部分的所有的1产生的贡献
    for(int i = 0; i < (1 << n); i++) {
        for(int k = 0; k < n; k++)
            p[k] = 0, q[k] = 0;
        for(int j = 0; j < n; j++) {
            if(!(i & (1 << j)))
                for(int k = 0; k < n; k++)
                    p[k] += c[j][k + n];
            else
                for(int k = 0; k < n; k++)
                    q[k] += c[j][k + n];
        }
        ret = 0;
        //前半部分为i状态,它拥有d[i]个已选择的人
        dfs(0, d[i], 0, 0);
        //把前半部分的s[i]状态加进去
        ans = max(ans, ret + s[i]);
    }
    printf("%lld\n", ans);
}

Guess you like

Origin www.cnblogs.com/Yinku/p/11223495.html