题解 CF803E 【Roma and Poker】

· · 题解

这道题实际上就是一个记忆化搜索的模板题

题目要求输赢相差不超过k且在最后一回合是必须等于k,就可以用这做完终止条件

    if(x==n and abs(y)==k)return true;
    if(x==n or abs(y)>=k)return false;

然后,若当前回合输赢已经确定,就直接进入下一层递归;否则,枚举3种情况分别递归,只要有一种情况成立,就返回true

    if(s[x]=='W')return dfs(x+1,y+1);
    if(s[x]=='D')return dfs(x+1,y);
    if(s[x]=='L')return dfs(x+1,y-1);
    if(dfs(x+1,y+1))return s[x]='W',true;
    if(dfs(x+1,y))return s[x]='D',true;
    if(dfs(x+1,y-1))return s[x]='L',true;

然而,这样做肯定超时,于是开始记忆化搜索

用dp[x][y]表示在第x回合时赢的回合-输的回合数是y,当然,y有可能是负数

记忆化的过程也很简单,只要在递归函数中间加一个dp[x][y]=1就行了

上完整代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll read(){
    ll a=0,b=getchar(),c=1;
    while(!isdigit(b))c=b=='-'?-1:1,b=getchar();
    while(isdigit(b))a=a*10+b-'0',b=getchar();
    return a*c;
}
int n,k,dp[1005][1005];
string s;
bool dfs(int x,int y){
    if(x==n and abs(y)==k)return true;
    if(x==n or abs(y)>=k)return false;
    if(dp[x][y])return false;
    dp[x][y]=1;
    if(s[x]=='W')return dfs(x+1,y+1);
    if(s[x]=='D')return dfs(x+1,y);
    if(s[x]=='L')return dfs(x+1,y-1);
    if(dfs(x+1,y+1))return s[x]='W',true;
    if(dfs(x+1,y))return s[x]='D',true;
    if(dfs(x+1,y-1))return s[x]='L',true;
}
int main(){
    n=read(),k=read();
    cin >> s;
    if(dfs(0,0))cout << s;
    else puts("NO");
    return 0;
}