D. Letter Picking

D. Letter Picking

Alice and Bob are playing a game. Initially, they are given a non-empty string s, 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 s, removes it from s and prepends (adds to the beginning) it to their own string.

The game ends when the string s 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 a is lexicographically smaller than a string b if there exists such position i that aj=bj for all j<i and ai<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 t (1t1000) — the number of testcases.

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

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

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

2
forces
abba

output

Alice
Draw

Note

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

  1. Alice picks the first letter in s: s="orces", a="f", b="";
  2. Bob picks the last letter in s: s="orce", a="f", b="s";
  3. Alice picks the last letter in s: s="orc", a="ef", b="s";
  4. Bob picks the first letter in s: s="rc", a="ef", b="os";
  5. Alice picks the last letter in s: s="r", a="cef", b="os";
  6. Bob picks the remaining letter in s: s="", a="cef", 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.

 

解题思路

  动态规划还是很好想到的,但状态转移很复杂最后还是没做出来。当然在写这篇博客的时候感觉逻辑还是有点乱的,不过我已尽量去理清思路,如果我讲不明白请看其他大佬的题解吧。

  把 Alice 先取走一个字符,Bob 再取走一个字符定义为一轮,那么一局游戏会在 n2 轮后结束。假设 Alice 和 Bob 各自的字符串为 sasb,那么首个字符 sa1sb1 就是第 n2 轮结束后得到的,第 2 个字符 sa2sb2 就是第 n21 轮结束后得到的,以此类推字符串最后一个字符 san/2sbn/2 是第 1 轮结束后得到的。

  先用最常规的思路来做这道题。定义状态 f(l,r) 表示以字符串 slsr 进行游戏的结果,如果 f(l,r)=0 则平局,否则 f(l,r)=1 则 Alice 胜,f(l,r)=2 则 Bob 胜。以一轮为单位进行状态转移,分以下两种情况:

  1. 区间 [l,r] 的长度为 2。如果 sl=sr 则为平局,f(l,r)=0。否则 slsr Alice 必然会取最大的那个字符,有 f(l,r)=1
  2. 区间 [l,r] 的长度大于 2f(l,r) 可通过 f(l+1,r1) (Alice 和 Bob 取两端的字符),f(l+2,r)f(l,r2)(Alice 和 Bob 取同一端的字符)转移过来。

  可以知道区间长的状态总是由区间短的状态转移得到,因此状态转移图是一个有向无环图,可以 dp。

  在任意一轮中无非就只有以下 4 中情况:

  1. Alice 取 sl,Bob 取 sl+1
  2. Alice 取 sl,Bob 取 sr
  3. Alice 取 sr,Bob 取 sr1
  4. Alice 取 sr,Bob 取 sl

  考虑 f(l,r)=1 的情况。由于每个人都选择最优的操作,如果 Alice 会取 sl,当且仅当无论 Bob 取 sl+1 或是 sr 都是 Alice 胜。分别考虑 Bob 取 sl+1sr 的情况:

  • Bob 取 sl+1 时 Alice 在什么情况下能胜?
    1. sl<sl+1:由于在这个位置上 Alice 的字符已经比 Bob 的小了,因此只要 f(l+2,r)2sa 的字典序都比 sb 小,即 Alice 胜。
    2. slsl+1:由于在这个位置上 Alice 的字符不比 Bob 的小,因此只有 f(l+2,r)=1 时,sa 的字典序才比 sb 小,Alice 才能胜。
  • Bob 取 sr 时 Alice 在什么情况下能胜?
    1. sl<sr:由于在这个位置上 Alice 的字符已经比 Bob 的小了,因此只要 f(l+1,r1)2sa 的字典序都比 sb 小,即 Alice 胜。
    2. slsr:由于在这个位置上 Alice 的字符不比 Bob 的小,因此只有 f(l+1,r1)=1 时,sa 的字典序才比 sb 小,Alice 才能胜。

  同理分析如果 Alice 取 sr,当且仅当无论 Bob 取 sr1 或是 sl 都是 Alice 胜。

  如果 Alice 取 sl 或是 sr 都不能保证 Alice 胜,那么接下来 Alice 应该尽可能保证是平局。与上面的分析几乎一样,如果 Alice 会取 sl,当且仅当无论 Bob 取 sl+1 或是 sr 都是平局。分别考虑 Bob 取 sl+1sr 的情况:

  • 在已知 Alice 不能胜的情况下,Bob 取 sl+1 时在什么情况下能平局?
    1. slsl+1:由于在这个位置上 Alice 的字符不比 Bob 的大,因此只要 f(l+2,r)2sa 的字典序不比 sb 大,Bob 不能胜。
    2. sl>sl+1:由于在这个位置上 Alice 的字符比 Bob 的大,因此只有 f(l+2,r)=1 时,sa 的字典序才比 sb 小,Bob 不能胜。
  • 在已知 Alice 不能胜的情况下,Bob 取 sr 时在什么情况下能平局?
    1. slsr:由于在这个位置上 Alice 的字符不比 Bob 的大,因此只要 f(l+1,r1)2sa 的字典序不比 sb 大,Bob 不能胜。
    2. sl>sr:由于在这个位置上 Alice 的字符比 Bob 的大,因此只有 f(l+1,r1)=1 时,sa 的字典序才比 sb 小,Bob 不能胜。

  同理分析如果 Alice 取 sr,当且仅当无论 Bob 取 sr1 或是 sl 都是平局。

  如果 f(l,r)=1f(l,r)=0 都不能满足,那么只有 f(l,r)=2 了,即 Bob 胜。

  AC 代码如下,时间复杂度为 O(n2)

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 2010;

char s[N];
int f[N][N];

int dfs(int l, int r) {
    if (f[l][r] != -1) return f[l][r];
    if (r - l + 1 == 2) return f[l][r] = s[l] != s[r];
    f[l][r] = 2;    // 假定Bob胜
    // 判断Alice能否胜
    if ((s[l] < s[l + 1] && dfs(l + 2, r) != 2 || s[l] >= s[l + 1] && dfs(l + 2, r) == 1) && (s[l] < s[r] && dfs(l + 1, r - 1) != 2 || s[l] >= s[r] && dfs(l + 1, r - 1) == 1)) f[l][r] = 1;
    if ((s[r] < s[r - 1] && dfs(l, r - 2) != 2 || s[r] >= s[r - 1] && dfs(l, r - 2) == 1) && (s[r] < s[l] && dfs(l + 1, r - 1) != 2 || s[r] >= s[l] && dfs(l + 1, r - 1) == 1)) f[l][r] = 1;
    if (f[l][r] == 1) return f[l][r];    // Alice能胜,直接断定
    // 否则Alice不能胜,看能否平局
    if ((s[l] <= s[l + 1] && dfs(l + 2, r) != 2 || s[l] > s[l + 1] && dfs(l + 2, r) == 1) && (s[l] < s[r] && dfs(l + 1, r - 1) != 2 || s[l] == s[r] && !dfs(l + 1, r - 1) || s[l] > s[r] && dfs(l + 1, r - 1) == 1)) f[l][r] = 0;
    if ((s[r] <= s[r - 1] && dfs(l, r - 2) != 2 || s[r] > s[r - 1] && dfs(l, r - 2) == 1) && (s[r] < s[l] && dfs(l + 1, r - 1) != 2 || s[r] == s[l] && !dfs(l + 1, r - 1) || s[r] > s[l] && dfs(l + 1, r - 1) == 1)) f[l][r] = 0;
    return f[l][r];
}

void solve() {
    scanf("%s", s);
    memset(f, -1, sizeof(f));
    int n = strlen(s);
    dfs(0, n - 1);
    if (f[0][n - 1] == 0) printf("Draw\n");
    else if (f[0][n - 1] == 1) printf("Alice\n");
    else printf("Bob\n");
}

int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        solve();
    }
    
    return 0;
}

  事实上可以证明游戏的结果只有 Alice 胜或平局这两种结果,这个应该可以通过数学归纳法来证明,不过我想了很久都证不出来,感觉很麻烦。我看其他人的解释是,由于最终状态(长度为 2 的串)只有 Alice 胜和平局两种状态,Bob 不能胜,所以 Bob 无论怎样都不会胜,因为其它状态都是由最终状态转移得到。这里直接用这个结论来定义状态表示。

  定义状态 f(l,r) 表示以字符串 slsr 进行游戏的结果,如果 f(l,r)=0 则平局,否则 f(l,r)=1 则 Alice 胜。

  考虑 f(l,r)=1 的情况(与上面的完全一样)。由于每个人都选择最优的操作,如果 Alice 会取 sl,当且仅当无论 Bob 取 sl+1 或是 sr 都是 Alice 胜。分别考虑 Bob 取 sl+1sr 的情况:

  • Bob 取 sl+1 时 Alice 在什么情况下能胜?
    1. sl<sl+1:由于在这个位置上 Alice 的字符已经比 Bob 的小了,因此只要 f(l+2,r)2sa 的字典序都比 sb 小,即 Alice 胜。
    2. slsl+1:由于在这个位置上 Alice 的字符不比 Bob 的小,因此只有 f(l+2,r)=1 时,sa 的字典序才比 sb 小,Alice 才能胜。
  • Bob 取 sr 时 Alice 在什么情况下能胜?
    1. sl<sr:由于在这个位置上 Alice 的字符已经比 Bob 的小了,因此只要 f(l+1,r1)2sa 的字典序都比 sb 小,即 Alice 胜。
    2. slsr:由于在这个位置上 Alice 的字符不比 Bob 的小,因此只有 f(l+1,r1)=1 时,sa 的字典序才比 sb 小,Alice 才能胜。

  同理分析如果 Alice 取 sr,当且仅当无论 Bob 取 sr1 或是 sl 都是 Alice 胜。如果不能保证 Alice 胜,那么游戏的结果就是平局了,这是因为任意游戏都只有 Alice 胜或平局的结果。

  AC 代码如下,时间复杂度为 O(n2)

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 2010;

char s[N];
int f[N][N];

int dfs(int l, int r) {
	if (f[l][r] != -1) return f[l][r];
	if (r - l + 1 == 2) return f[l][r] = s[l] != s[r];
	f[l][r] = 0;
	if ((s[l] < s[l + 1] || dfs(l + 2, r)) && (s[l] < s[r] || dfs(l + 1, r - 1))) f[l][r] = 1;
	if ((s[r] < s[r - 1] || dfs(l, r - 2)) && (s[r] < s[l] || dfs(l + 1, r - 1))) f[l][r] = 1;
	return f[l][r];
}

void solve() {
    scanf("%s", s);
    memset(f, -1, sizeof(f));
    printf("%s\n", dfs(0, strlen(s) - 1) ? "Alice" : "Draw");
}

int main() {
	int t;
	scanf("%d", &t);
	while (t--) {
		solve();
	}
	
	return 0;
}

 

参考资料

  Educational Codeforces Round 135 D(博弈) E(扩展gcd):https://zhuanlan.zhihu.com/p/562781822

  Educational Codeforces Round 135 Editorial:https://codeforces.com/blog/entry/106805

posted @   onlyblues  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
Web Analytics
点击右上角即可分享
微信分享提示