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

 

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