Newcoder 109 F.玩遊戲(博弈論)
阿新 • • 發佈:2018-12-16
Description
給定兩個串和,。
和輪流操作串,先手。
對於每次操作,或會選擇刪掉的第一位或最後一位。
當操作以後的串的長度等於時,遊戲停止。
如果停止時的串,則獲勝,否則獲勝。
問在和均採取最優策略的情況下,誰贏?
Input
第一行一個整數表示資料組數。
接下來行每行兩個整數字符串。
Output
行。對於每組資料,贏輸出,$ bob’Bob’$。
Sample Input
5 aba b bab b aaab aab xyz mnk xyz xyz
Sample Output
Alice Alice Bob Bob Alice
Solution
一.若,此時則後手勝,否則先手勝
二.若,記,那麼先手可以操作次,後手可以操作次,記為中所有可以與匹配的區間,那麼有
1.若為偶數,那麼,我們首先證明先手必然可以破壞所有滿足的匹配,先手首先任選一邊刪去一個,之後後手刪哪邊先手就刪另一邊,這樣可以保證兩邊都至少刪去了次,那麼所有這種匹配都會因為或被破壞
注意到先手可以破壞一邊至多次,故對於的匹配顯然可以儲存下來,但是對於的情況,如果只存在一個匹配滿足該條件,那麼先手只需儘可能刪除一邊即可破壞該匹配,故此時必須至少存在兩個匹配使得,如此先手無論怎麼刪都至少會有一個匹配儲存下來
2.若為奇數,那麼,同理至少需要兩個匹配使得,這樣先手無論刪哪一邊,只要後手刪另一邊,就可以保證至少有一個匹配儲存下來
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=500005;
int T,n,m;
char s[maxn],t[maxn];
bool check(int x)
{
for(int i=x+1,j=1;j<=m;i++,j++)
if(s[i]!=t[j])return 0;
return 1;
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%s%s",s+1,t+1);
n=strlen(s+1),m=strlen(t+1);
int flag=0;
if(n==m)
{
if(strcmp(s+1,t+1)==0)flag=1;
}
else
{
if((n-m)&1)
{
if(check((n-m)/2)&&check((n-m)/2+1))flag=1;
}
else
{
if(check((n-m)/2)||check((n-m)/2-1)&&check((n-m)/2+1))flag=1;
}
}
if(flag)printf("Alice\n");
else printf("Bob\n");
}
return 0;
}