B2. Palindrome Game (hard version)
题目大意:
与简单版本相同,只不过这个版本给出的01串不一定为回文串。两个人在一起做游戏,ALICE先手,Bob后手,他们可以从以下两种操作中选一个:
1.
1.
1.任选某个为0的位置将其变为1,代价为1。
2.
2.
2.若该01串目前不为回文串,且上一个操作不为操作2的情况下可以将整个01串翻转。
代价少的人获胜,否则平局。
思路:
首先输入字符串时,先判断一下是不是回文串,如果是,那我们就将它放入简单版本中的代码里。
如果不是那我们就看一看这个串距离一个回文串有多少次操作,因为如果输入的字符串不是回文串的话那么BOB肯定会以最快的速度先构造出一个回文串才能有和ALICE抗衡的机会,而在此期间ALICE只需要不停翻转原串即可。
当BOB终于构造出一个回文串时,这时如果剩下的0的个数为偶数,那么ALICE是必胜的,因为:如果假设剩下x个0, h为Bob进行的操作数那么肯定有
h
(
B
O
B
)
+
x
/
2
>
x
/
2
h(BOB) + x/ 2 > x / 2
h(BOB)+x/2>x/2故ALICE必胜,若剩下0的个数为奇数时,当且仅当Bob进行的操作次数为1且剩下的0也为1个时,两人平局,否则均是ALICE胜。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<cmath>
#include<iomanip>
#include<queue>
using namespace std;
typedef long long ll;
const int p = 1e9 + 7;
typedef pair<int, int> pii;
const int N = 1e6+10;
map<int, int>mp;
int n;
char s[10000];
int h;
bool check() {
for (int i = 1; i <= n/2; i++) {
if (s[i] != s[n - i + 1])h++;
}
if(!h)return true;
return false;
}
int main() {
int t;
cin >> t;
while (t--)
{
h = 0;
cin >> n;
cin >> s + 1;
int cnt = 0;
for (int i = 1; i <= n ; i++) {
if (s[i] == '0')cnt++;
}
check();
cnt -= h;
if (!h) {
if (cnt == 1) {
puts("BOB");
}
else if (cnt % 2 && cnt != 1) {
puts("ALICE");
}
else if (cnt % 2 == 0) {
if (cnt >= 2) {
puts("BOB");
}
else puts("DRAW");
}
else if (cnt == 0)puts("DRAW");
}
else {
if (cnt % 2) {
if (h == 1 && cnt == 1)puts("DRAW");
else puts("ALICE");
}
else {
puts("ALICE");
}
}
}
}