2019牛客暑期多校訓練營(第二場)-F artition problem

題目連接:https://ac.nowcoder.com/acm/contest/882/F優化

題意:將2×n我的分紅兩組,每組n我的,求一個組中全部人和另一組的全部人的競爭值之和。spa

思路:code

  比賽時看錯題了,覺得求得是每一隊人的競爭值之和,寫了兩個小時,提交時覺得會T,結果一直WA,自閉。。blog

  看懂題後,就開始T了。。it

  n<=14,用搜索+剪枝是能夠作的。搜索有C(2*n,n)的複雜度,但每種結果須要O(n*n)的複雜度來計算,總複雜度爲O(n*n*C(2*n,n)),確定會T。io

  優化:簡化計算結果,先預處理每一行的和v2,v2[i]即第i我的和其它全部人的競爭值的和,用vector存儲已經選過的人,選擇下一我的x時,用v2[i]減去2×(全部的v1[x][i]),i是已經選過得人的編號,乘2是由於以前加入i時沒有減。這樣複雜度就降爲O(n*C(2*n,n)),由於題目給了4s,是能夠過的。class

     另外,能夠把第1我的直接選上,由於第1我的確定要被其中1個隊選上,結果同樣,這樣能將複雜度減1倍。test

 AC代碼:搜索

#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;

typedef long long LL;
int n;
LL v1[30][30],v2[30],ans;
vector<int> vc;

void dfs(int x,LL sum){
    if(vc.size()==n){
        if(sum>ans) ans=sum;
        return;
    }
    if(x>2*n) return;
    LL tmp=v2[x];
    for(int i=0;i<vc.size();++i)
        tmp-=2*v1[x][vc[i]];
    vc.push_back(x);
    dfs(x+1,sum+tmp);
    vc.pop_back();
    dfs(x+1,sum);
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<=2*n;++i)
        for(int j=1;j<=2*n;++j)
            scanf("%lld",&v1[i][j]),v2[i]+=v1[i][j];
    vc.push_back(1);
    dfs(2,v2[1]);
    printf("%lld\n",ans);
    return 0;
}
相關文章
相關標籤/搜索