首页 > 软件开发 > 软件开发

软件开发Palindrome Game (hard version) (自带不正经的游戏策略分析

admin 软件开发 2021-05-25 09:26:20 字符串 算法 acm竞赛 
后台-系统设置-扩展变量-手机广告位-内容正文底部

Palindrome Game (hard version)

The only difference between the easy and hard versions is that the given string ss in the easy version is initially a palindrome, this condition is not always true for the hard version.

A palindrome is a string that reads the same left to right and right to left. For example, "101101" is a palindrome, while "0101" is not.

Alice and Bob are playing a game on a string ss of length nn consisting of the characters '0' and '1'. Both players take alternate turns with Alice going first.

In each turn, the player can perform one of the following operations:

  1. Choose any i (1≤i≤n), where s[i]= '0' and change s[i] to '1'. Pay 1 dollar.
  2. Reverse the whole string, pay 0 dollars. This operation is only allowed if the string is currently not a palindrome, and the last operation was not reverse. That is, if Alice reverses the string, then Bob can't reverse in the next move, and vice versa.

Reversing a string means reordering its letters from the last to the first. For example, "01001" becomes "10010" after reversing.

The game ends when every character of string becomes '1'. The player who spends minimum dollars till this point wins the game and it is a draw if both spend equal dollars. If both players play optimally, output whether Alice wins, Bob wins, or if it is a draw.

Input

The first line contains a single integer t (≤t≤10^3). Then tt test cases follow.

The first line of each test case contains a single integer n (1≤n≤10^3).

The second line of each test case contains the string s of length n, consisting of the characters '0' and '1'. It is guaranteed that the string s contains at least one '0'.

Note that there is no limit on the sum of nn over test cases.

Output

For each test case print a single word in a new line:

  • "ALICE", if Alice will win the game,
  • "BOB", if Bob will win the game,
  • "DRAW", if the game ends in a draw.

Example

Input

3
3
110
2
00
4
1010

Output

ALICE
BOB
ALICE

解析

题目大意为:给一个字符串,Alice与Bob交替进行操作1或2。

  1. 将某个0置换为1,并花费1刀
  2. 当字符串非回文,且对手的上一次操作是操作1时,将字符串反转,花费0刀

字符串中的字符全变为1时,花费最少者获胜。(当然,不考虑任何一方消极游戏的情况) 

       先从简单版说起。其中,Alice初始拿到的字符串即为回文(这也是简单版与困难版的唯一区别)(由回文,易得简单版中Alice不得不先进行操作1,使其堪称Alice的困难模式)。此时,游戏胜负取决于字符串中0的个数。分析以下情况:

  1. 假如有偶数个0,由于Alice在第一步必须进行操作1,Bob只需与Alice对称放置,保持字符串回文,直至剩最后一个0时选择操作2,迫使Alice最后多进行一次操作1,即最终比Bob多消耗1刀。
  2. 假如有奇数个0,依据回文,则字符串长度为奇数,且中间处有一个0。Alice只需先把中间的0变成1,即可将上一种情况甩给Bob。应小心只有1个0的特殊情况,此时Alice纵有如此阴间战术加持,也只得落得败绩。

代码如下:

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n,t,num;
	char c;
	cin>>t;
	while(t--)
	{
		cin>>n;
		getchar();
		int cnt=0;
		for(int i=1;i<=n;i++)
		{
			cin>>c;
			num=c-'0';
			if(!num)cnt++;
		}
		if(!(cnt%2)||cnt==1)cout<<"BOB"<<endl;
		else cout<<"ALICE"<<endl;
	}
}

       再考虑复杂版。笔者最先想到的思路是先判断初始字符串是否回文。若为真则可按简单版处理,若为假则另辟蹊径。当初始字符串不回文时,先手的Alice时十分舒服的,分为以下两情况。

  • 需操作一次即可回文,那么Alice可以“故技重施”,参照简单版的情况2,将回文字符串甩给Bob,留后者在微风中凌乱。
  • 需要更多次数才能转化为回文,则Alice可以先不断进行反转,迫使Bob不断进行操作1(十分有压迫性的打法),直至还需最后一次操作。此时可按上述方式处理。

       需要注意的是,即便Alice以上两情况中打得很爽,她也不能稳赢。在前一种情况中,假如她“大E”了,把只有一个0的回文串给到Bob ,忘记自己如何在简单版的情况2中败北 ,那么两人均只操作了一次,打平。(原始字符串长度为奇数,只含有两个0,其中一个在中间。例如“11010”)这种情况下Alice能否取胜的?她可否重置一下就把字符串丢给Bob呢?本以为Bob会一脸无奈地接盘,没想到他双眼燃起光芒。只见他把不在中间的0置换为1,Alice只得置换中间的0,仍旧打平。Alice“大意失荆州”也好,Bob“顽强逼平”也罢, 平局是双方在此情景的最好局面(这个残酷的游戏竟有次和谐一面,也是实属难得) 

代码如下:

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n,t,num;
	char c;
	cin>>t;
	while(t--)
	{
		cin>>n;
		getchar();
		int cnt=0,cou=0;
		int a[1007];
		for(int i=1;i<=n;i++)
		{
			cin>>c;
			num=c-'0';
			a[i]=num;
			if(!num)cnt++;
		}
		for(int i=1;i<=n/2;i++)
		{
			if(a[i]!=a[n-i+1]){
				cou++;
			}
		}
		if(cou)
		{
			if(cou==1&&cnt==2) cout<<"DRAW"<<endl;
			else cout<<"ALICE"<<endl;
		}
		else
		{
			if(!(cnt%2)||cnt==1)cout<<"BOB"<<endl;
			else cout<<"ALICE"<<endl;
		}
	}
}

其中cnt记录字符串中0的个数,cou记录转化为回文所需要的操作步数。

       本题的解析到这里也就可以结束了,但是我 偏不 总觉得讨论起来有点麻烦,而且在简单和复杂版本中,均有涉及到同一特殊情况,可否二者合并呢?其实,稍加分析可知 (从简单版中Alice占据先手,却被回文字符串整得十分狼狈看出) ,本游戏的取胜之道,即是不断将回文的字符串甩给对手。因为每接到不全为1的回文字符串,游戏局面转化为简单版的情况1,接到字符串者难以获胜。可以说谁先将字符串改造为回文,谁就基本占据了主动权。是所以说是基本,是因为如果字符串长度为奇数,且不止中间位置一处为0,则仍会败北。对方只需先把中间的0置换为1,就把主动权夺回来了, 小丑竟又成了你自己

       既然奇数长度字符串中间的0足以逆转胜负,先手可否抢先“占据”这个战略要地?非也!如果把先手优势用在此处,对方将可以造出偶数个0的回文字符串,锁定胜局。更何况,在形如“1010110”的情况时,牢牢占据制造回文字符串的主动权,你也可以获得胜利。

       明确了这一游戏策略后,就不难发现,简单版所研究的内容,恰好可以看作是复杂版中字符串到达回文状态后的情况。我们可以把游戏分为两个部分:转化为回文的部分 (争夺战略要地) ,和回文后的部分 (大局已定) 。如果初始字符串非回文,先手者会在第一阶段取得少付出1个代价的优势。如果开局即回文,则先手的优势丧失。在第二阶段,依据回文字符串的形态,即可判断两者谁可以在本阶段少付出1个代价。将两阶段结果叠加,即可得知最终的胜者。

       综上所述,若Bob想获胜,初始字符串不仅要回文,还有其它限制,即长度为偶数,或者为奇数且只含一个零(即中间位置的0)。即他既要追求字符串开局即回文(让Alice享受不了先手优势),又要保证回文字符串形态有利。当初始字符串不为回文,长度为奇数,且中间和另一位置为0时,二者必然打平。此外情况,Alice必然获胜。一言以蔽之,谁将含偶数个或1个0的回文字符串甩给对手,谁就获得了最终的胜利。

       

文章来源:https://blog.csdn.net/weixin_53721121/article/details/117195244

后台-系统设置-扩展变量-手机广告位-内容正文底部
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。
本文地址:https://www.jcdi.cn/ruanjiankaifa/30789.html

留言与评论(共有 0 条评论)
   
验证码:
后台-系统设置-扩展变量-手机广告位-评论底部广告位

教程弟

https://www.jcdi.cn/

统计代码 | 京ICP1234567-2号

Powered By 教程弟 教程弟

使用手机软件扫描微信二维码