Codeforces 803E Roma and Poker【Dp+记录路径】

本文探讨了一个特殊的在线扑克游戏问题,玩家需要根据已知的比赛结果序列,确定未知比赛结果的可能性,以确保最终胜利次数与失败次数之差达到指定值,同时避免过程中出现提前达标的状况。

E. Roma and Poker
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Each evening Roma plays online poker on his favourite website. The rules of poker on this website are a bit strange: there are always two players in a hand, there are no bets, and the winner takes 1 virtual bourle from the loser.

Last evening Roma started to play poker. He decided to spend no more than k virtual bourles — he will stop immediately if the number of his loses exceeds the number of his wins by k. Also Roma will leave the game if he wins enough money for the evening, i.e. if the number of wins exceeds the number of loses by k.

Next morning Roma found a piece of paper with a sequence on it representing his results. Roma doesn't remember the results exactly, and some characters in the sequence are written in a way such that it's impossible to recognize this character, so Roma can't recall whether he won k bourles or he lost.

The sequence written by Roma is a string s consisting of characters W (Roma won the corresponding hand), L (Roma lost), D (draw) and ? (unknown result). Roma wants to restore any valid sequence by changing all ? characters to W, L or D. The sequence is called valid if all these conditions are met:

  • In the end the absolute difference between the number of wins and loses is equal to k;
  • There is no hand such that the absolute difference before this hand was equal to k.

Help Roma to restore any such sequence.

Input

The first line contains two numbers n (the length of Roma's sequence) and k (1 ≤ n, k ≤ 1000).

The second line contains the sequence s consisting of characters W, L, D and ?. There are exactly n characters in this sequence.

Output

If there is no valid sequence that can be obtained from s by replacing all ? characters by W, L or D, print NO.

Otherwise print this sequence. If there are multiple answers, print any of them.

Examples
Input
3 2
L??
Output
LDL
Input
3 1
W??
Output
NO
Input
20 5
?LLLLLWWWWW?????????
Output
WLLLLLWWWWWWWWLWLWDW

题目大意:


给你一个长度为N的字符串,其中包含四种字符:L,D,W,?.其中L表示罗马队输了,D代表平,W代表赢了,?表示不确定。

?可以填充为L,D,W任意一个。

现在要求找到一个合法的情况使得满足以下两个条件:

①在结尾的时候,Abs(L的数量-W的数量)==k

②在结尾之前,Abs(L的数量-W的数量)不能有等于k的时候。


思路:


1、当前位子的?设定为某一种情况会影响之后的设定方案,但是不会影响之前的设定方案,那么无后效性的一个问题,我们首先考虑dp.

设定dp【i】【j】表示到位子i,W比L多的个数为j(j可能为负,表示L比W多的个数为-j)个的情况是否存在。

因为数组范围界定条件有限,所以我们开数组为dp【1005】【5005】即可,设定mid==2500.也就是表示0的位子,那么2499就表示dp【i】【-1】;


2、接下来考虑状态转移方程:
①a【i】==‘L’:dp【i】【j】=dp【i-1】【j+1】;

②a【i】==‘W’:dp【i】【j】=dp【i-1】【j-1】;

③a【i】==‘D’:dp【i】【j】=dp【i-1】【j】;

④a【i】==‘?’:dp【i】【j】=max(dp【i-1】【j+1】,dp【i-1】【j-1】,dp【i-1】【j】);

初始化dp【0】【0】=1;


3、接下来逆向维护一条可行路径出来即可。

注意不满足条件的情况一定不能走,稍微注意点细节就行了。


Ac代码:

#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
int dp[1005][5005];
char a[1005];
char ans[1005];
int main()
{
    int mid=2502;
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        memset(ans,' ',sizeof(ans));
        memset(dp,0,sizeof(dp));
        scanf("%s",a+1);
        dp[0][mid]=1;
        for(int i=1; i<=n; i++)
        {
            for(int j=mid-m; j<=mid+m; j++)
            {
                if(i!=n)
                {
                    if(j==mid-m||j==mid+m)continue;
                }
                if(a[i]=='W')dp[i][j]=dp[i-1][j-1];
                if(a[i]=='L')dp[i][j]=dp[i-1][j+1];
                if(a[i]=='D')dp[i][j]=dp[i-1][j];
                if(a[i]=='?')
                {
                    dp[i][j]=max(dp[i][j],dp[i-1][j-1]);
                    dp[i][j]=max(dp[i][j],dp[i-1][j+1]);
                    dp[i][j]=max(dp[i][j],dp[i-1][j]);
                }
            }
        }
        if(dp[n][mid+m]==0&&dp[n][mid-m]==0)
        {
            printf("NO\n");
            return 0;
        }
        if(dp[n][mid+m]==1)
        {
            int flag=0;
            int tmp=mid+m;
            for(int i=n; i>=1; i--)
            {
                if(a[i]!='?')
                {
                    if(a[i]=='W')tmp--;
                    if(a[i]=='L')tmp++;
                    if(tmp==mid+m||tmp==mid-m)flag=1;
                    ans[i]=a[i];
                }
                else
                {
                    if(tmp!=mid+m&&tmp!=mid-m&&dp[i-1][tmp]==1)ans[i]='D';
                    else if(tmp+1<mid+m&&dp[i-1][tmp+1]==1)ans[i]='L',tmp=tmp+1;
                    else if(tmp-1>mid-m&&dp[i-1][tmp-1]==1)ans[i]='W',tmp=tmp-1;
                    else flag=1;
                }
            }
            if(flag==0)
            {
                for(int i=1; i<=n; i++)printf("%c",ans[i]);
                printf("\n");
                return 0;
            }
        }
        if(dp[n][mid-m]==1)
        {
            int flag=0;
            int tmp=mid-m;
            for(int i=n; i>=1; i--)
            {
                if(a[i]!='?')
                {
                    if(a[i]=='W')tmp--;
                    if(a[i]=='L')tmp++;
                    if(tmp==mid+m||tmp==mid-m)flag=1;
                    ans[i]=a[i];
                }
                else
                {
                    if(tmp!=mid+m&&tmp!=mid-m&&dp[i-1][tmp]==1)ans[i]='D';
                    else if(tmp+1<mid+m&&dp[i-1][tmp+1]==1)ans[i]='L',tmp=tmp+1;
                    else if(tmp-1>mid-m&&dp[i-1][tmp-1]==1)ans[i]='W',tmp=tmp-1;
                    else flag=1;
                }
            }
            if(flag==0)
            {
                for(int i=1; i<=n; i++)printf("%c",ans[i]);
                printf("\n");
                return 0;
            }
            else printf("NO\n");
        }
    }
}








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值