B1. Palindrome Game (easy version)
博弈类型的题目最优步骤很重要
要注意 模仿 ,这个是解题的关键
先找找规律,爱丽丝先手
1001 :1101 1111 没啥悬念,BOB必胜
10001 : 10101 11101 11111,可以发现当中间的0变成1之后,问题就变成上一个,这次输的是BOB
100001 :
100011 A = 1
110011 B = 1
111011 A = 2
111111 A = 3
策略:在0的个数满足 <= 2 之前,BOB模仿ALICE的动作,最后重复情况1,然后BOB胜利
思考:每次选择把哪个0变成1,为什么?
贪心思想,考虑贡献,我们每次选择操作之后能让串更接近回文的0,把它变成1,因为变成回文之后ALICE就不能白嫖了,就必须进行花费操作
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3e5 + 9;
string s;
int main()
{
int t, n, q;
cin >> t;
while(t--)
{
cin >> n >> s;
int sum0 = 0;
for(int i = 0; i < n; ++i) if(s[i] == '0') sum0++;
if(sum0 <= 2) cout << "BOB\n";
else if(sum0 % 2 == 1)
cout << "ALICE\n";
else cout << "BOB\n";
}
return 0;
}
B2. Palindrome Game (hard version)
若字符串为回文串,则与Easy版本一样;
若字符串不为回文串,则Alice胜或平手。因为Alice可以通过不断执行翻转操作,迫使Bob执行修改操作,直到字符串差一步变为具有偶数个 0 的回文串。此时Alice花费 1 将其变为偶数个 0 ,即Bob将面对后续花费比Alice多 2 的局面。这样Bob至少比Alice多花费 1 。某些情况下,Alice会一直翻转,例如 0011 。只有当字符串有一个居中 0 且另有一个不对称的时,双方平手,例如 001。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3e5 + 9;
string s;
int main()
{
int t, n, q;
cin >> t;
while(t--)
{
cin >> n >> s;
int sum0 = 0;
bool f = 1;
for(int i = 0; i < n; ++i)
{
if(s[i] == '0') sum0++;
if(i < n/2 && s[i] != s[n-1-i]) f = 0;
}
if(f)
{
if(sum0 <= 2) cout << "BOB\n";
else if(sum0 % 2 == 1)
cout << "ALICE\n";
else cout << "BOB\n";
}
else
{
if(sum0 != 2) cout << "ALICE\n";
else
{
bool f1 = 0;
for(int i = 0; i < n / 2; ++i)
if(s[i] != s[n-1-i]) f = 1;
if(n & 1 && s[n/2] == '0' && f) cout << "DRAW\n";
else cout << "ALICE\n";
}
}
}
return 0;
}