Codeforces 1138B. Circus

题目

Solution

我感觉这题比这场的CD难多了(E以后没时间看,但99%是做不出的)
刚开始想过 d p dp dp,但发现要保存前 i i i个数, 0 0 0 1 1 1的个数差,还有 s 1 s1 s1中选择的长度,会爆
然后想到了模拟,枚举两个串中 1 1 1的个数 k k k
对于每个 i i i s 1 s1 s1 s 2 s2 s2的情况只有 4 4 4种:
1 : s 1 [ i ] = ′ 0 ′ , s 2 [ i ] = ′ 0 ′ 1:s1[i]='0',s2[i]='0' 1s1[i]=0s2[i]=0
2 : s 1 [ i ] = ′ 0 ′ , s 2 [ i ] = ′ 1 ′ 2:s1[i]='0',s2[i]='1' 2s1[i]=0s2[i]=1
3 : s 1 [ i ] = ′ 1 ′ , s 2 [ i ] = ′ 0 ′ 3:s1[i]='1',s2[i]='0' 3s1[i]=1s2[i]=0
4 : s 1 [ i ] = ′ 1 ′ , s 2 [ i ] = ′ 1 ′ 4:s1[i]='1',s2[i]='1' 4s1[i]=1s2[i]=1
a a a数组来记录 s 1 s1 s1中选择的点, b b b来记录 s 2 s2 s2中选择的点
a [ 1.. k ] a[1..k] a[1..k]装的都是 s 1 [ i ] = ′ 1 ′ s1[i]='1' s1[i]=1的点, a [ k + 1.. n / 2 ] a[k+1..n/2] a[k+1..n/2]装的都是 s 1 [ i ] = ′ 0 ′ s1[i]='0' s1[i]=0的点, b [ ] b[] b[]同理
然后 a a a中尽可能选 3 3 3 b b b中尽可能选 2 2 2(都得 ≤ k ≤k k
然后 a , b a,b a,b中不够的用 4 4 4
如果用 4 4 4都补不满,那肯定不行
如果 4 4 4有多,那么只能填在 a , b a,b a,b [ 1.. k ] [1..k] [1..k]部分,尽可能替代
如果 4 4 4还有多,那肯定不定了
a [ k + 1.. n / 2 ] a[k+1..n/2] a[k+1..n/2]中尽可能填 2 2 2,如果 2 2 2还有多,那肯定也不行了,
因为 2 2 2填在 s 2 s2 s2中就是 1 1 1了,而 s 2 s2 s2 1 1 1已经满了
剩下的都填 1 1 1,然后输出

Code

有很多冗余的部分,毕竟在打比赛时时间比较紧,一般不会去修改这种东西的

#include<bits/stdc++.h>
using namespace std;
const int N=5002;
int i,j,k,a[N],b[N],t1,t2,t3,t4,c1,c2,c3,c4,n,p1,p2,p3,p4;
char s1[N],s2[N];
vector<int>l1,l2,l3,l4;
int main(){
	scanf("%d%s%s",&n,s1+1,s2+1);
	for (i=1;i<=n;i++){
		if (s1[i]=='0' && s2[i]=='0') c1++,l1.push_back(i);
		if (s1[i]=='0' && s2[i]=='1') c2++,l2.push_back(i);
		if (s1[i]=='1' && s2[i]=='0') c3++,l3.push_back(i);
		if (s1[i]=='1' && s2[i]=='1') c4++,l4.push_back(i);
	}
	for (k=0;k<=n/2;k++){//要从0开始
		t1=c1,t2=c2,t3=c3,t4=c4;
		memset(a,0,sizeof(a));
		memset(b,0,sizeof(b));
		for (i=1;i<=k;i++){
			if (t3) t3--,a[i]=3;
			else if (t4) t4--,a[i]=4;
			if (t2) t2--,b[i]=2;
			else if (t4) t4--,b[i]=4;
		}
		if (k && !a[k] || k && !b[k]) continue;//k=0时不需要判断
		for (i=1;i<=k;i++)
			if (a[i]==3 && t4) a[i]=4,t4--,t3++;
		for (i=1;i<=k;i++)
			if (b[i]==2 && t4) b[i]=4,t4--,t2++;
		if (t4) continue;
		for (i=k+1;i<=n/2;i++)
			if (t2) t2--,a[i]=2;
			else if (t1) t1--,a[i]=1;
		if (!a[n/2] || t2) continue;
		for (i=1;i<=n/2;i++){
			if (a[i]==1) printf("%d ",l1[p1++]);
			if (a[i]==2) printf("%d ",l2[p2++]);
			if (a[i]==3) printf("%d ",l3[p3++]);
			if (a[i]==4) printf("%d ",l4[p4++]);
		}
		return 0;
	}
	puts("-1");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值