考虑一个贪心:以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; }