当前位置: 代码迷 >> 综合 >> 【博弈论】B1. Palindrome Game (easy version)—— Codeforces Round #721 (Div. 2)
  详细解决方案

【博弈论】B1. Palindrome Game (easy version)—— Codeforces Round #721 (Div. 2)

热度:60   发布时间:2023-11-21 17:10:12.0

本题有难易两个版本。

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;//1a2bwhile(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;
}
  相关解决方案