题目来源:(Codeforces Round #721 (Div. 2))
题意:
有一个长度为n,只包含0或1的字符串,Alice和Bob轮流进行以下操作之一:
1.将字符串中的一个0修改为1,该操作花费为1$;
2.如果当前字符串不是回文字符串且上家未进行操作2,那么可以花费0$将字符串顺序逆置;
如果字符串所有的字符均为1,那么游戏结束
从Alice开始操作,求最后的结果(谁花钱少谁获胜,分Alice胜,Bob胜和平局)
问题的easy版本保证输入字符串一定是回文串,但hard版本不保证。
思路:
先从easy题下开始,考虑回文字符串中字符'0'的个数:
考虑平凡情形:
当0的个数为1时,由于Alice先手,Alice唯一的合法操作便只能是操作1,而Bob没有操作,故Bob胜
当0的个数为2时,由回文条件可知Alice必然第一步只能从对称的两个‘0’中选择一个,由于破坏了对称性,Bob便可以进行操作2,从而Alice需要进行两次操作1后游戏结束,Bob胜。
下面对0的个数大于2的其他情况进行归纳:
当0的个数为偶数时,对于Alice的每一个操作1,Bob可以直接选择回文字符串中另一个与Alice所选择‘0’相对称的‘0’字符进行操作1,直到‘0’的个数降为2为止,有上述可知Bob胜。
当0的个数为奇数时,由回文字符串可知必然有且仅有一个位于字符串中间位置的‘0’字符和其他若干对两两对称的‘0’字符,那么Alice只需选择中间位置的‘0’字符之后问题就转为了Bob先手的偶数个‘0’情况,Alice胜。
可知:easy题的结论为:设k为回文字符串中‘0’字符的数量;
k=1或k为偶数时,Bob胜;反之Alice胜
再考虑hard题下字符串的一般情况:将‘0’的数量分开计算,分为按照字符串位置对称(即:满足easy题位置情况的‘0’字符)和不对称的‘0’字符
考虑到一个较为显然的操作1策略:
由于不花费的操作2的存在,任何一方进行操作1的时候必须要将字符串按照尽量对称的方向修改(否则,由于字符串不对称,下家总可以执行花费为0的操作2)
那么可知:如果字符串中有a个不对称的‘0’字符,那么先手Alice必然可以执行a轮的操作2;换言之,Alice的费用在Bob将字符串修改为回文之前,已经比Bob少了a花费。
那么可知:如果Alice在修改后的回文字符串是获胜情形,那么再由上述操作后,Alice仍然必然获胜。
同样,如果Alice在修改后的回文字符串不是获胜情形,那么Alice可以执行上述操作至只剩一个不对称‘0’字符,并对其执行操作1,问题转化为Bob先手的后手胜字符串情形
此时需要特判:如果修改完成后的回文字符串只有1个‘0’字符,可知此时Bob的花费也为1,此时平局;其他有非对称‘0’字符的情况下都是Alice胜。
如果没有非对称‘0’字符,问题就转化为easy题,照样输出即可。
可知:hard题的结论为:设k为回文字符串中对称‘0’字符的数量(字符串正中间的‘0’字符也包括在内),a为其他‘0’字符的数量;
a>0时:仅在k=1和a=1的情形下平局,其余均是Alice胜;
a==0时:k为1或偶数时,Bob胜,反之Alice胜。
代码如下:
(GNU G++14)
#include<iostream>
#define ll long long
using namespace std;
int main(){
ll t,n,i,j,k,sl,ys;
string sr;
cin>>t;
while(t--){
cin>>n>>sr;
for(i=sl=ys=0;i<=n-1;i++){
if(i>n-1-i) break;
if(i==n-1-i and sr[i]=='0') sl++;
else{
if(sr[i]==sr[n-1-i] and sr[i]=='0') sl+=2;
else if(sr[i]=='0' or sr[n-1-i]=='0') ys++;
}
}
if(ys>0){
if(sl==1 and ys==1) cout<<"DRAW"<<endl;
else cout<<"ALICE"<<endl;
}
else{
if(sl==1 or sl%2==0) cout<<"BOB"<<endl;
else cout<<"ALICE"<<endl;
}
}
return 0;
}
(PyPy 3.7)
t=int(input())
for _ in range(t):
n=int(input())
w=input()
a=0
b=0
for i in range(len(w)):
if(i>n-1-i): break
else:
if(i==n-1-i and w[i]=='0'): b+=1
else:
if(w[i]==w[n-1-i] and w[i]=='0'): b+=2
else:
if(w[i]=='0' or w[n-1-i]=='0'): a+=1
if(a>0):
if(a==1 and b==1): print("DRAW")
else: print("ALICE")
else:
if(b==1 or b%2==0): print("BOB")
else: print("ALICE")