2123D-Binary String Battle
题目
艾丽斯和鲍勃得到一个长度为 \(n\) 的二进制字符串 \(s\),以及一个整数 \(k\)(满足 \(1 \le k < n\))。
如果艾丽斯能够将字符串 \(s\) 中的所有字符都变为零,则艾丽斯获胜。如果艾丽斯在有限步内无法获胜,则鲍勃获胜。
艾丽斯和鲍勃轮流操作,艾丽斯先开始。
- 在艾丽斯的回合,她可以选择字符串 \(s\) 中任意一个长度为 \(k\) 的子序列,然后将该子序列中的所有字符设为零。
- 在鲍勃的回合,他可以选择字符串 \(s\) 中任意一个长度为 \(k\) 的子串,然后将该子串中的所有字符设为一。
注意,如果在游戏进行中任意时候(包括艾丽斯和鲍勃回合之间),字符串全部为零,则艾丽斯获胜。
请判断在最优策略下,谁将获胜。
子序列:字符串 \(s\) 的一个字符集合,字符在 \(s\) 中按顺序出现,但不需要相邻。
子串:字符串 \(s\) 的一个连续字符区间,字符必须是相邻的。
输入格式:
- 第一行包含一个整数 \(t\)(\(1 \le t \le 10^4\)),表示测试用例的数量。
- 每个测试用例的第一行包含两个整数 \(n\) 和 \(k\)(\(2 \le n \le 2 \times 10^5\),\(1 \le k < n\))。
- 第二行包含长度为 \(n\) 的二进制字符串 \(s\)。
保证所有测试用例中 \(n\) 的总和不超过 \(2 \times 10^5\)。
思路
令\(cnt\)为\(1\)的个数,
一.当\(cnt <= k\),\(alice\)获胜, 否则分两种情况讨论
二.当\(n >= 2 * k\),\(bob\)获胜,因为\(alice\)操作完后,一定会有剩余,而\(bob\)可选择最左边或最右边的字串变为\(1\),且一定不会与原有的\(1\)全部重合,所以在\(bob\)操作完后,总有\(cnt>k\)
三。否则,\(n < 2 * k\),\(alice\)获胜
方法
如此类博弈,获胜问题时,优先从获胜条件,状态转移考虑,运用递推,递归的思想,进行分类讨论
code
#include <bits/stdc++.h>
using namespace std;
int t;
int n, k, cnt, l;
string s;
void solve()
{
cin >> n >> k;
cin >> s;
cnt = 0;
l = s.size();
s = ' ' + s;
for(int i = 1;i <= l;i++) if(s[i] == '1') cnt++;
if(cnt <= k) {
cout<<"alice"<<"\n";
return;
}
if(n >= 2 * k){
cout<<"bob"<<"\n";
}else{
cout<<"alice"<<"\n";
}
}
int main(){
ios :: sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> t;
while(t--){
solve();
}
return 0;
}

浙公网安备 33010602011771号