CodeForces - 545B Circus 簡單(劃掉)枚舉

鏈接:

B. Circus

題意:

有n個人,參加兩場表演,有的人擅長第一場,有的人擅長第二場,也有全擅長全不擅長的。

從n個人裏選n/2個,去第一場,剩下人去第二場。

要求去第一場的人裏擅長第一場的人數和去第二場的人裏擅長第二場的人數相等。

思路:

官方給打的標籤是"brute force",說明這道題沒有什麼高深的知識點,很簡單,然而我還是做了兩個小時。。搞得其他題都沒看。。這場掉分掉不少。。一道1000分的題做到300分才AC...

這道題很容易走彎路分類討論,先把某些人扔到某一場,再來回轉移、轉移...

思路很自然,但是代碼bug很多。寫了一小時沒寫出來,決定換種思路:

考慮去第一場的人裏,四種人(全都不擅長、只擅長第一場、只擅長第二場、都擅長)分別有a、b、c、d個。

則應存在:a+b+c+d = \frac{n}{2}  (加起來等於去第一場的總人數)

假設 “去第一場的人裏擅長第一場的人數”(也就是“去第二場的人裏擅長第二場的人數”)爲val,並稱其爲"擅長值"。

則應存在 b+d = val

假設全部的n個人裏面,四種人分別有v[0]、v[1]、v[2]、v[3]種,那麼對於第二場:

(v[0]-a) + (v[1]-b) + (v[2]-c) + (v[3]-d) = \frac{n}{2}

(v[2]-c) + (v[3]-d) = val

四個式子聯立,得到:

d = val-b

c = b+v[2]+v[3]-2\cdot val

a = \frac{n}{2}-b-c-d

因此通過枚舉val和b,得到a,c,d,然後判斷a,c,d是否合法,即可得出去第一場的人裏每一種的數量,從中選出對應數量的人,輸出即可。

代碼:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
static const int maxn = 100010;
static const int INF = 0x3f3f3f3f;
static const int mod = (int)1e9 + 7;
static const double eps = 1e-6;
static const double pi = acos(-1);

void redirect(){
    #ifdef LOCAL
        freopen("test.txt","r",stdin);
    #endif
}
char A[5010],B[5010];
int type[5010];
vector<int>v[4],ans;
map<int,set<int> >m;
int main(){
    redirect();
    int n,val = -1;
    scanf("%d",&n);
    scanf("%s",A+1);
    scanf("%s",B+1);
    for(int i = 1;i <= n;i++){
        type[i] = (A[i]=='1'?1:0) + (B[i]=='1'?2:0);
        v[type[i]].push_back(i);
    }
    for(int val = 0;val <= min(v[1].size(),v[2].size())+v[3].size();val++)
    for(int b = 0;b <= val;b++){
        int d = val-b;
        int c = b+v[2].size()+v[3].size()-2*val;
        int a = n/2-b-c-d;
        if(0<=b&&b<=v[1].size() && 0<=d&&d<=v[3].size() && 0<=c&&c<=v[2].size() && 0<=a&&a<=v[0].size()){
            for(int i = 0;i < a;i++)ans.push_back(v[0][i]);
            for(int i = 0;i < b;i++)ans.push_back(v[1][i]);
            for(int i = 0;i < c;i++)ans.push_back(v[2][i]);
            for(int i = 0;i < d;i++)ans.push_back(v[3][i]);
            goto label;
        }
    }
    label:
    int sz = ans.size();
    if(sz)for(int i = 0;i < sz;i++)printf("%d%c",ans[i],i==sz-1?'\n':' ');
    else puts("-1");
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章