Educational Codeforces Round 135 (Rated for Div. 2) D. Letter Picking
D. Letter Picking
题目大意
给一个字符串s,长度为偶数,Alice和Bob初始时都只有一个空字符串,Alice先行动。每次从s的头和尾选择一个字符,插入自己的字符串的首。
到最后,谁的字符串的字典序小谁赢。
分析
看到数据范围,不免让人想到DP。因为每次操作,选择都是头和尾操作,因此我们考虑区间DP。
初始化是对于长度为2,我们只需要看两个字符相同与否,相同则平局,否则则A赢。
接下来,开始进行区间DP,每次我们只需要考虑偶数长度,接下来的分析会知道为什么。
设dp[l][r]:1表示为A赢,0表示平局,-1表示B赢
我们考虑,每次都是A先行动,然后B行动,依据此可以分为四种转移,
A选l
对于A选l后,B选择有两种情况,其一定选择能使答案变小的选择。设在A选l的条件下,B两种选择结果最小为ret1,初始化为1
B选r
if(dp[l+1][r-1]) ret1 = min(ret1,dp[l+1][r-1]);
else if(s[r]<s[l]) ret1 = -1;
else if(s[r]==s[l]) ret1 = min(ret1,0);
B选l+1
if(dp[l+2][r]) ret1 = min(ret1,dp[l+2][r]);
else if(s[l+1]<s[l]) ret1 = -1;
else if(s[l+1]==s[l]) ret1 = min(ret1,0);
A选r
此时,我们在设一个ret2,与ret1定义相同。
B选l
if(dp[l+1][r-1]) ret2 = min(ret2,dp[l+1][r-1]);
else if(s[r]>s[l]) ret2 = -1;
else if(s[r]==s[l]) ret2 = min(ret2,0);
B选r-1
if(dp[l][r-2]) ret2 = min(ret2,dp[l][r-2]);
else if(s[r-1]<s[r]) ret2 = -1;
else if(s[r-1]==s[r]) ret2 = min(ret2,0);
对于A的两种选择,A一定是选择能让答案尽量大的结果,因此,dp[l][r] = max(ret1,ret2)
来看代码吧
Ac_code
#include <bits/stdc++.h>
#define fi first
#define se second
#define endl '\n'
#define ios ios::sync_with_stdio(false); cin.tie(0), cout.tie(0)
typedef long long LL;
using namespace std;
const int N = 2010,M = N*2;
int dp[N][N];
string s;
int n;
void solve()
{
cin>>s;
n = s.size();
s = " " + s;
for(int i=1;i<=n-1;i++)
if(s[i]==s[i+1]) dp[i][i+1] = 0;
else dp[i][i+1] = 1;
for(int len=4;len<=n;len+=2)
for(int l=1;l<=n-len+1;l++)
{
int r = l + len - 1;
dp[l][r] = -1;
int ret = 1;
if(dp[l+1][r-1]) ret = min(ret,dp[l+1][r-1]);
else if(s[r]<s[l]) ret = -1;
else if(s[r]==s[l]) ret = min(ret,0);
if(dp[l+2][r]) ret = min(ret,dp[l+2][r]);
else if(s[l+1]<s[l]) ret = -1;
else if(s[l+1]==s[l]) ret = min(ret,0);
dp[l][r] = max(dp[l][r],ret);
ret = 1;
if(dp[l+1][r-1]) ret = min(ret,dp[l+1][r-1]);
else if(s[r]>s[l]) ret = -1;
else if(s[r]==s[l]) ret = min(ret,0);
if(dp[l][r-2]) ret = min(ret,dp[l][r-2]);
else if(s[r-1]<s[r]) ret = -1;
else if(s[r-1]==s[r]) ret = min(ret,0);
dp[l][r] = max(dp[l][r],ret);
}
if(dp[1][n]==1) cout<<"Alice\n";
else if(dp[1][n]==0) cout<<"Draw\n";
else cout<<"Bob\n";
}
int main()
{
ios;
int T=1;
cin>>T;
while(T -- ) {
solve();
}
return 0;
}

浙公网安备 33010602011771号