cf Educational Codeforces Round 20 E. Roma and Poker

来源:互联网 发布:mysql自定义函数 编辑:程序博客网 时间:2024/05/24 06:49

原题:
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和k,再给你一个长为n的字符串。其中字符串当中L表示减一分,W表示加一分,D表示不加不减,问号表示待定。
现在让你把这个字符串中的问号变成L、W、D使得总和为k。
要求在最后结果前不能出现和为k的情况。

#include<bits/stdc++.h>using namespace std;int dp[1005][2005];char a[1005];char ans[1005];int main(){    ios::sync_with_stdio(false);    int n,k;    while(cin>>n>>k)    {        memset(ans,' ',sizeof(ans));        memset(dp,0,sizeof(dp));        cin>>a+1;        dp[0][k]=1;        for(int i=1; i<=n; i++)        {            for(int j=0; j<=k*2; j++)            {                if(i!=n)                {                    if(j==0||j==k*2)                        continue;                }                if(a[i]=='?')                {                    if(dp[i-1][j-1]||dp[i-1][j+1]||dp[i-1][j])                        dp[i][j]=1;                }                else                {                    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(dp[n][k*2]==0&&dp[n][0]==0)        {            cout<<"NO"<<endl;            continue;        }        if(dp[n][k*2]==1)        {            int flag=0;            int tmp=2*k;            for(int i=n; i>=1; i--)            {                if(a[i]!='?')                {                    if(a[i]=='W')tmp--;                    if(a[i]=='L')tmp++;                    if(tmp==2*k||tmp==0)flag=1;                    ans[i]=a[i];                }                else                {                    if(tmp!=2*k&&tmp!=0&&dp[i-1][tmp]==1)                        ans[i]='D';                    else                        if(tmp+1<2*k&&dp[i-1][tmp+1]==1)                            ans[i]='L',tmp=tmp+1;                    else                        if(tmp-1>0&&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++)                    cout<<ans[i];                cout<<endl;                continue;            }        }        if(dp[n][0]==1)        {            int flag=0;            int tmp=0;            for(int i=n; i>=1; i--)            {                if(a[i]!='?')                {                    if(a[i]=='W')tmp--;                    if(a[i]=='L')tmp++;                    if(tmp==2*k||tmp==0)flag=1;                    ans[i]=a[i];                }                else                {                    if(tmp!=2*k&&tmp!=0&&dp[i-1][tmp]==1)ans[i]='D';                    else if(tmp+1<2*k&&dp[i-1][tmp+1]==1)ans[i]='L',tmp=tmp+1;                    else if(tmp-1>0&&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++)                    cout<<ans[i];                cout<<endl;            }            else                cout<<"NO"<<endl;        }    }    return 0;}

思路:
比较简单的动态规划问题
转移方程如下
设置布尔型 dp[i][j]表示长为i的字符串能否得到绝对值总和j
那么转移方程就是

如果当前字符串位置为'?'那么dp[i][j]={    dp[i-1][j]|| '?'->'D'    dp[i-1][j+1]|| '?'->'L'    dp[i-1][j-1] '?'->'W'    }如果当前字符粗位置为已经确定的字符dp[i][j]={    dp[i-1][j], 'D'    dp[i-1][j-1], 'W'    dp[i-1][j+1], 'L'    } 

注意,由于L表示减去1,那么就会出现dp[i][j]中j值为负值的情况,j的绝对值范围是0到1000所以,要把数组容量扩大,扩大到原来的2倍即可dp[n][2*k],最后如果有结果,要考察dp[n][0]和dp[n][2*k]分别表示得到-k和+k的值的结果

此题恶心的地方在打印路径,我敲了半天也没敲对,后来瞄了一眼别人的代码写出来的。。。
此题和uva 10564有一个共同点,那就是询问在某些条件,或者挑选的情况下,总和或者是总共的值能否达到某一个状态,那么此时就要将这个状态设置为状态转移方程中的一维作为参数。

0 0