博弈论B1. Palindrome Game (easy version)—— Codeforces Round #721 (Div. 2)
Posted 出尘呢
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了博弈论B1. Palindrome Game (easy version)—— Codeforces Round #721 (Div. 2)相关的知识,希望对你有一定的参考价值。
本题有难易两个版本。
easy version:
https://codeforces.com/contest/1527/problem/B1
/*
当0, B,差1
当00,B,差2
当000,A,中间多1,但最后少2
对于00,A1B1可以
讨论:
eke——只有中间一个0的时候,bob赢。0个数是偶数时,alice每次放一个,bob就放对称,最后一对0,alice填了一个给bob的时候bob不放,这样bob总是比alice少填2个
为奇数的时候,alice填中间那个,把偶数的时候alice面对的状态转移给bob,这样alice总是比bob少填2-1个
b2应该是先让bob把所有非回文的地方补上,昨天晚上太混乱了
灵儿——哦意思就是博弈论能赢就行,不是贪心解法…
我想0个数是偶数时,alice每次放一个,bob就翻一下,alice再放一个对称,bob变成了alice,就乱七八糟的混乱w
其实不面对对称的优势值2分,这样就够了w之后像nim一样在平手情况下,维持这样的优势,躺赢
*/
小错误:
//这里小输入符错!
//注意初始化!
#include<bits/stdc++.h>
#ifdef LOCAL
FILE*FP=freopen("text.in","r",stdin);
#endif
using namespace std;
char str[1003];
void get(int&a,int&b,int&n){
scanf("%d",&n);
scanf("%s",str);//这里小输入符错!
a=0,b=0;//注意初始化!
for(int i=0;i<n/2;i++){
// printf("%c %c\\n",str[i],str[n-i-1]);
if(str[i]=='0'&&str[n-i-1]=='0')a++;
}
if(n%2&&str[n/2]=='0')b++;
// printf("in:%d %d %d\\n",a,b,n);
}
signed main(){
int t,n,a,b;//对称,中间
scanf("%d",&t);
int flag=0;//1a2b
while(t--){
get(a,b,n);
// printf("%d %d %d\\n",a,b,n);
if(b==0||a==0)flag=2;
else flag=1;
printf("%s\\n",(flag==1)?"ALICE":"BOB");
}
return 0;
}
hard version:
有之前的经验,多讨论一下
从A先手希望取胜的方面讨论,首先先手有优势的话保持就是了,这就是关键,从先手的角度看策略。
如何保持先手优势,减小问题规模:
对称00
A只能填一个,B填另一个,不变,平手
谁能让对手处在对称00,其实是占优的
因为A只能填一个,B也可以翻转,则A,-2,而让对方处于这个情况对调了,其实还是A想这样化回来,B被动就有被平手的可能。所以B选择走最小的步长,掌控时机让A-2时刚好下完
——后手胜,-2
不对称0011
A翻转,B填,不变,A+1
——先手胜,+m
有中0:
只有中0:
A只能取之,-1,负
此外只有对称0:
A取中0,-1,之后可保证+2,整体+1,所以必胜
此外只有m个不对称0:
A不要白不要(理解一下不要是不是白不要了)
所以让B填m个,+m,之后自己来填最后一个,-1,最少了,整体m-1
m=1,平,m>1,胜
有对称0和不对称0:
A先白要m个,+m,并且还是到了此外只有对称0,能必胜
无中0:
只有对称0:
即对称00情况
——A负
只有不对称0:
即不对称0011情况
——A胜
有对称0和不对称0:
A要先享受不对称0优势,B填也不会去填对称0创造更多不对称0,A有m-1分
之后A填了最后的不对称0,把对称00局面给了B,A有2分
——整体m-1分,A胜
下结论
为了最后判断,按胜负总结,不是去一个个寻找那么多情况是不是匹配
A负:
1.只有中间0
2.只有对称0
A平:
1.只有(中间0和一个不对称0)
A胜:
1.有中0,有对称0
2.有中0,有多于一个不对称0
3.无中0,有不对称0
#include<bits/stdc++.h>
#ifdef LOCAL
FILE*FP=freopen("text.in","r",stdin);
#endif
using namespace std;
char str[1003];
void get(int&f1,int&f2,int&f3,int&n){
f1=f2=f3=n=0;
scanf("%d",&n);
scanf("%s",str);
if(n%2&&str[n/2]=='0')f1=1;//有中0
for(int i=0;i<n/2;i++){
//printf("%c %c\\n",str[i],str[n-i-1]);
if(str[i]=='0'&&str[n-i-1]=='0')f2++;//对称0
if(str[i]!=str[n-i-1])f3++;
}
//printf("in:%d %d %d\\n",f1,f2,f3);
}
signed main(){
int t,n,f1,f2,f3,f;//中间, 对称, 不对称 //f:a1胜2负3平
scanf("%d",&t);
while(t--){
get(f1,f2,f3,n);
//printf("%d %d %d\\n",f1,f2,f3);
if((f1&&!f2&&!f3)||(f2&&!f1&&!f3))f=2;
else if(f1&&f3==1&&!f2)f=3;
else f=1;
if(f==1)printf("ALICE\\n");
if(f==2)printf("BOB\\n");
if(f==3)printf("DRAW\\n");
}
return 0;
}
以上是关于博弈论B1. Palindrome Game (easy version)—— Codeforces Round #721 (Div. 2)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #721 (Div. 2)B1. Palindrome Game (easy version)B2. Palindrome Game (hard version)题解
Codeforces Round #721 (Div. 2)A. And Then There Were K(位运算,二进制) B1. Palindrome Game (easy version)(