B. Circus

链接

[https://codeforces.com/problemset/problem/1138/B]

题意

给你两个字符串0,1那种,你是否可以选出一半的字符串,同时取。
使得当前第一个字符串的1的个数等于,剩下没选的第二个字符串的1的个数。

分析

首先我是真的傻,因为,我一直在哪里分类讨论,结果想了半天,一点都不行。
那么这个时候我们就看数据n<=5000,也就是可以n*n解决。怎么暴力呢?
这题就是你初中的数学功底的体现了。统计00,01,10,11的个数A,B,C,D;
我们假设选的00,01,10,11的个数为a,b,c,d;
a+b+c+d=n/2; A+B+C+D=n;
我们枚举a,那么根据题意需要满足

这题真的就是个数学啊,而且也反应我对复杂度不敏感,有时候可以暴力,就一定暴力,因为它不容易出错比较稳。
复杂度分析,这方面我还是菜了。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e3+10;

char s[N],t[N];
int main(){
    int n;
    while(~scanf("%d",&n)){
    
        scanf("%s",s+1);
        scanf("%s",t+1);
        int a,b,c,d,A=0,B=0,D=0,C=0;
        for(int i=1;i<=n;i++)
        if(s[i]=='0'&&t[i]=='1')
        B++;
        else if(s[i]=='1'&&t[i]=='0')
        C++;
        else if(s[i]=='1'&&t[i]=='1')
        D++;
        A=n-(B+D+C);
        //cout<<A<<' '<<B<<' '<<C<<' '<<D<<endl;
        bool flag=0;
        for(a=0;a<=A&&a<=n/2;a++)
        {
            d=B+D+a-n/2;
            if(d>=0&&d<=D&&(a+d)<=n/2){
                for(b=0;b<=B&&(a+b+d)<=n/2;b++){
                    c=n/2-(a+b+d);
                    if(c>=0&&c<=C){
                        flag=1; break;
                    }
                }
            }
            if(flag) break;
        }
        if(!flag) puts("-1");
        else {
            //cout<<a<<' '<<b<<' '<<c<<' '<<d<<endl;
            for(int i=1;i<=n;i++)
            if(s[i]=='0'){
                if(t[i]=='0'&&a){
                    printf("%d ",i);
                    a--;
                }
                if(t[i]=='1'&&b){
                    printf("%d ",i);
                    b--;
                }
            }
            else{
                if(t[i]=='0'&&c){
                    printf("%d ",i);
                    c--;
                }
                if(t[i]=='1'&&d){
                    printf("%d ",i);
                    d--;
                }
            }
            puts("");
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/mch5201314/p/10974085.html