Palindrome Game---(贪心)

题目来源:(Codeforces Round #721 (Div. 2))

Problem - B1 - Codeforces

Problem - B2 - Codeforces

题意:

有一个长度为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")

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值