Codeforces #545 div2 B

题意

给你两行字符串,长度均为n,由01构成,现在让你从中选择n/2个位置,使得选择
的位置上的第一个字符串上的1的个数等于剩下位置上的第二个字符串上的1的个数

思路

一共四种类型, 00 , 10 , 01 , 11 00,10,01,11 00100111,设其总数分别为, v [ 0 ] , v [ 1 ] , v [ 2 ] , v [ 3 ] v[0],v[1],v[2],v[3] v[0]v[1]v[2]v[3]
又设在第一个字符串中,这四种类型的个数分别为 a , b , c , d a,b,c,d abcd
则应有 a + b + c + d = n a+b+c+d =n a+b+c+d=n
设选中的第一个字符串中1的个数(即剩余的第二个字符串中1的个数)为 v a l val val
则因存在:

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

联立可得:

d = v a l − b d = val-b d=valb
c = b + v [ 2 ] + v [ 3 ] − 2 ∗ v a l c = b + v[2] +v[3] - 2*val c=b+v[2]+v[3]2val
a = n 2 − b − c − d a = \frac{n}{2} - b - c -d a=2nbcd

所以我们只要枚举 v a l , b val,b valb得到 a , c , d a,c,d acd然后判断是否合法即可。
AC代码:

#include 
using namespace std;

const int maxn = 5005;
char s1[maxn], s2[maxn];
vector<int> v[4], ans;

int main()
{
    int n, val, flag = 0;
    scanf("%d", &n);
    scanf("%s", s1);
    scanf("%s", s2);
    for (int i = 0; i < n; ++i){
        if (s1[i] == '0' && s2[i] == '0') v[0].push_back(i);
        else if (s1[i] == '1' && s2[i] == '0')  v[1].push_back(i);
        else if (s1[i] == '0' && s2[i] == '1')  v[2].push_back(i);
        else if (s1[i] == '1' && s2[i] == '1')  v[3].push_back(i);
    }
    val = min(v[1].size(), v[2].size()) + v[3].size();
    //cout << val << '\n';
    for (int i = 0; i <= val; ++i) {
        for (int j = 0; j <= i; ++j) {
            int d = i - j;
            int c = j + v[2].size() + v[3].size() - 2*i;
            int a = n / 2 - j - c -d;
            if (j >= 0 && j <= v[1].size() && d >= 0 && d <= v[3].size() && c >= 0 && c <= v[2].size() && a >= 0 && a <= v[0].size()) {
                for (int k = 0; k < a; ++k) ans.push_back(v[0][k]);
                for (int k = 0; k < j; ++k) ans.push_back(v[1][k]);
                for (int k = 0; k < c; ++k) ans.push_back(v[2][k]);
                for (int k = 0; k < d; ++k) ans.push_back(v[3][k]);
            }
            int sz = ans.size();
            if (sz) {
                for (int i = 0; i < sz; ++i) cout << ans[i]+1 << " " ;
                flag = 1;
                break;
            }
        }
        if (flag == 1)  break;
    }
    if (!flag)  cout << "-1" << '\n';
    return 0;
}

你可能感兴趣的:(题目集)