考虑一个贪心:以AB为例,如果是a>b则a->b,如果b>a则b->a,否则a->b或b->a都可以
考虑这个贪心在什么时候是对的:我们的结论是当a+b+c>=3时,这个贪心是对的,证明略,除非第一次就是(0,0),否则一定有解
接下来考虑a+b+c==0,1的情况,直接判断就行了
考虑a+b+c==2的情况,根据下一次的情况判断就行了,更远的影响可以忽略
时间复杂度:O(n)
注意数组别开小了,我在这里WA了很多发
#include<bits/stdc++.h>
using namespace std;
#define N 100005
#define LL long long
int n, a, b, c, i, flag;
char s[3], st[N][3], Sol[N];
int main (void)
{
scanf("%d%d%d%d",&n,&a,&b,&c);
if ((LL)a+b+c>=3) {
flag=0;
for (i=1; i<=n; i++) {
scanf("%s",s);
if (s[0]=='A'&&s[1]=='B') {
if (a>b) a--,b++,Sol[i]='B';
else a++,b--,Sol[i]='A';
if (a<0||b<0) flag=1;
}
else if (s[0]=='A'&&s[1]=='C') {
if (a>c) a--,c++,Sol[i]='C';
else a++,c--,Sol[i]='A';
if (a<0||c<0) flag=1;
}
else {
if (b>c) b--,c++,Sol[i]='C';
else b++,c--,Sol[i]='B';
if (b<0||c<0) flag=1;
}
}
if (flag) puts("No");
else {
puts("Yes");
for (i=1; i<=n; i++) printf("%c
",Sol[i]);
}
}
else {
// assert(0);
flag=0;
for (i=1; i<=n; i++) scanf("%s",st[i]);
for (i=1; i<=n; i++) {
if (st[i][0]=='A'&&st[i][1]=='B') {
if (!a) a++,b--,Sol[i]='A';
else if (!b) a--,b++,Sol[i]='B';
else {
if (st[i+1][0]=='A'&&st[i+1][1]=='C') a++,b--,Sol[i]='A';
else if (st[i+1][0]=='B'&&st[i+1][1]=='C') b++,a--,Sol[i]='B';
else a++,b--,Sol[i]='A';
}
if (a<0||b<0) flag=1;
}
else if (st[i][0]=='A'&&st[i][1]=='C') {
if (!a) a++,c--,Sol[i]='A';
else if (!c) a--,c++,Sol[i]='C';
else {
if (st[i+1][0]=='A'&&st[i+1][1]=='B') a++,c--,Sol[i]='A';
else if (st[i+1][0]=='B'&&st[i+1][1]=='C') c++,a--,Sol[i]='C';
else a++,c--,Sol[i]='A';
}
if (a<0||c<0) flag=1;
}
else {
if (!b) b++,c--,Sol[i]='B';
else if (!c) b--,c++,Sol[i]='C';
else {
if (st[i+1][0]=='A'&&st[i+1][1]=='C') c++,b--,Sol[i]='C';
else if (st[i+1][0]=='A'&&st[i+1][1]=='B') b++,c--,Sol[i]='B';
else b++,c--,Sol[i]='B';
}
if (b<0||c<0) flag=1;
}
}
if (flag) puts("No");
else {
puts("Yes");
for (i=1; i<=n; i++) printf("%c
",Sol[i]);
}
}
return 0;
}