D. Letter Picking- 博弈论 与 区间 DP

Problem - D - Codeforces

D. Letter Picking

time limit per test

2 seconds

memory limit per test

512 megabytes

input

standard input

output

standard output

Alice and Bob are playing a game. Initially, they are given a non-empty string ss, consisting of lowercase Latin letters. The length of the string is even. Each player also has a string of their own, initially empty.

Alice starts, then they alternate moves. In one move, a player takes either the first or the last letter of the string ss, removes it from ss and prepends (adds to the beginning) it to their own string.

The game ends when the string ss becomes empty. The winner is the player with a lexicographically smaller string. If the players' strings are equal, then it's a draw.

A string aa is lexicographically smaller than a string bb if there exists such position ii that aj=bjaj=bj for all j<ij<i and ai<biai<bi.

What is the result of the game if both players play optimally (e. g. both players try to win; if they can't, then try to draw)?

Input

The first line contains a single integer tt (1≤t≤10001≤t≤1000) — the number of testcases.

Each testcase consists of a single line — a non-empty string ss, consisting of lowercase Latin letters. The length of the string ss is even.

The total length of the strings over all testcases doesn't exceed 20002000.

Output

For each testcase, print the result of the game if both players play optimally. If Alice wins, print "Alice". If Bob wins, print "Bob". If it's a draw, print "Draw".

Example

input

Copy

 

2

forces

abba

output

Copy

Alice
Draw

Note

One of the possible games Alice and Bob can play in the first testcase:

  1. Alice picks the first letter in ss: s=s="orces", a=a="f", b=b="";
  2. Bob picks the last letter in ss: s=s="orce", a=a="f", b=b="s";
  3. Alice picks the last letter in ss: s=s="orc", a=a="ef", b=b="s";
  4. Bob picks the first letter in ss: s=s="rc", a=a="ef", b=b="os";
  5. Alice picks the last letter in ss: s=s="r", a=a="cef", b=b="os";
  6. Bob picks the remaining letter in ss: s=s="", a=a="cef", b=b="ros".

Alice wins because "cef" < "ros". Neither of the players follows any strategy in this particular example game, so it doesn't show that Alice wins if both play optimally.

---------------------------------------------------------------------------------------------------------------------------------

A B每次从当前 S 首部或者尾部选择一个字母,删除这一字母,并且放在自己串的开头

典型的区间博弈DP,用短小区间更新大区间,最终答案为dp[1][n]

为了方便操作,设置DP值越小,对A越有利

0 初始值

1 A赢

2 平局

3 B输

初始化 长度为2的区间,因为A先手,所以只要是s[i]!=s[i+1],那么dp[i][i+1]就等于1 ,否则就为平局

然后开始进行区间DP,题目保证偶数,每次长度+2即可

设当前区间 [L,R],长度len ,由 len-2长度转移而来,A无非两种情况,

l或者r

 选择l时 ,B无非两种选择 l+1, r中最优的,也就是最大的
 选择r时 ,B无非两种选择 r-1 ,l中最优的,也就是最大的

 而A就选择l,r中最优的,也就是最小的
 值得注意的是,我们是最后选的防止在串开头,那么就以为这小区间答案的优先级高于大区间,比如小区间dp值为1 ,那么无论当前选择什么,小区间决定的当前dp值必定也为1

# include<bits/stdc++.h>
using namespace std;
typedef long long int ll;

int dp[2010][2010];
string s;
int getf(int a,int b)
{
    if(s[a]==s[b])
        return 2;
    if(s[a]<s[b])
        return 1;
    return 3;
}
int main()
{

    int t;
    cin>>t;

    while(t--)
    {

        cin>>s;
        int n=s.length();
        s=" "+s;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                dp[i][j]=0; //无解
            }
        }
        //设置 A赢为 1  平局为 2 B赢为3
        for(int i=1;i<n;i++)
        {
            if(s[i]==s[i+1])
                dp[i][i+1]=2;
            else
                dp[i][i+1]=1;
        }

        for(int len=4;len<=n;len+=2)
        {
            for(int i=1;i+len-1<=n;i++)
            {
                int l=i,r=i+len-1;
               /* 当前A无非两种选择,l或者r
                选择l时 ,B无非两种选择 l+1 r中最优的,也就是最大的
                选择r时 ,B无非两种选择 r-1 l中最优的,也就是最大的

                而A就选择l,r中最优的,也就是最小的
                A选择l时*/
                int ans1=1e9,ans2=1e9;
                int temp1=getf(l,l+1); //仅考虑当前两个的情况

                if(dp[l+2][r]==3)   //前面一局优先级大于当前局
                    temp1=3;
                else if(dp[l+2][r]==2)
                    temp1=temp1;
                else if(dp[l+2][r]==1)
                    temp1=1;

                int temp2=getf(l,r);
                if(dp[l+1][r-1]==3)
                    temp2=3;
                else if(dp[l+1][r-1]==2)
                    temp2=temp2;
                else if(dp[l+1][r-1]==1)
                    temp2=1;

                ans1=max(temp1,temp2);

                temp1=getf(r,r-1);

                if(dp[l][r-2]==3)
                    temp1=3;
                else if(dp[l][r-2]==2)
                    temp1=temp1;
                else if(dp[l][r-2]==1)
                    temp1=1;

                temp2=getf(r,l);

                if(dp[l+1][r-1]==3)
                    temp2=3;
                else if(dp[l+1][r-1]==2)
                    temp2=temp2;
                else
                    temp2=1;

                ans2=max(temp1,temp2);

                dp[l][r]=min(ans1,ans2);



            }
        }

        if(dp[1][n]==1)
        {
            cout<<"Alice"<<endl;
        }
        else if(dp[1][n]==2)
        {
            cout<<"Draw"<<endl;
        }
        else
        {
            cout<<"Bob"<<endl;
        }
    }



    return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qinsanma and Code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值