Codeforces 803E--Roma and Poker (DP)

原题链接:http://codeforces.com/problemset/problem/803/E

题意:给一个n长度的字符串,其中‘?‘可以替换成‘D‘、‘W‘、‘L‘中的任意一种,‘D‘等价于0, ‘W‘等价于1、‘L‘等价于-1。输出所有‘?‘被替换掉后,W和L的数目之差为k,且任意一个[1, i]的子串中W和L数目之差不能等于k。

思路:用DP做。定义bool dp[i][j]代表前i个字符W和L数目之差为j, -k<=j<=k(在数组中范围为[0, 2*k]),那么当str[i]为‘D‘时dp[i][j]转移到dp[i-1][j], 为‘W‘时dp[i][j]转移到dp[i-1][j+1], str[i]为‘D‘时dp[i][j]转移到dp[i-1][j-1], 初始值dp[0][0]为true。

接着用一遍dfs倒推求结果,注意字符加的位置。

AC代码:

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<string>
 5 using namespace std;
 6 int dp[2005][4005];
 7 int n,k;
 8 string str;
 9 void change(int i, int L, int D, int W){
10         for(int j=1;j<2*k;j++){
11             if(dp[i-1][j]){
12                 if(D) dp[i][j]=1;
13                 if(L){
14                     if(i!=n&&j-1==0)//[1, i]子串中W和L数目之差不能等于k
15                         continue;
16                     dp[i][j-1]=1;
17                 }
18                 if(W){
19                     if(i!=n&&j+1==2*k)
20                         continue;
21                     dp[i][j+1]=1;
22                 }
23         }
24     }
25     return;
26 }
27 string ss;
28 //int t=0;
29 bool res(int i, int j, string ans){
30     //t++;
31     if(i==0&&j==k){
32         ss=ans;
33         return 1;
34     }
35     if(str[i-1]!=‘?‘){
36         if(str[i-1]==‘D‘) return res(i-1, j, ‘D‘+ans);
37         if(str[i-1]==‘W‘) return res(i-1, j-1, ‘W‘+ans);
38         if(str[i-1]==‘L‘) return res(i-1, j+1, ‘L‘+ans);
39     }
40     else
41     {
42         if(dp[i-1][j]&&res(i-1, j, ‘D‘+ans)) return 1;
43         if(dp[i-1][j-1]&&res(i-1, j-1, ‘W‘+ans)) return 1;
44         if(dp[i-1][j+1]&&res(i-1, j+1, ‘L‘+ans)) return 1;
45     }
46
47     return 0;
48 }
49 int main()
50 {
51     while(cin>>n>>k)
52     {
53         memset(dp, 0, sizeof(dp));
54         dp[0][k]=1;
55         cin>>str;
56         if(str[n-1]==‘D‘){
57             cout<<"NO"<<endl;
58             continue;
59         }
60         for(int i=1;i<=n;i++){
61             if(str[i-1]==‘?‘)
62                 change(i, 1, 1, 1);
63             else if(str[i-1]==‘D‘)
64                 change(i, 0, 1, 0);
65             else if(str[i-1]==‘W‘)
66                 change(i, 0, 0, 1);
67             else
68                 change(i, 1, 0, 0);
69         }
70         string ans;
71         if(dp[n][0]){
72             res(n, 0, ans);
73             cout<<ss<<endl;
74         }
75         else if(dp[n][2*k]){
76             res(n, 2*k, ans);
77             cout<<ss<<endl;
78         }
79         else
80             cout<<"NO"<<endl;
81         //cout<<t<<endl;
82     }
83     return 0;
84 }

这代码调了我好久啊QAQ,感觉自己真菜

时间: 2024-12-28 09:26:17

Codeforces 803E--Roma and Poker (DP)的相关文章

CodeForces - 710E Generate a String (dp)

题意:构造一个由a组成的串,如果插入或删除一个a,花费时间x,如果使当前串长度加倍,花费时间y,问要构造一个长度为n的串,最少花费多长时间. 分析:dp[i]---构造长度为i的串需要花费的最短时间. 1.构造长度为1的串,只能插入,dp[1] = x. 2.当前串的长度i为偶数,可以 (1)长度为i/2的串加倍:dp[i / 2] + y (2)长度为i-1的串插入一个a:dp[i - 1] + x 3.当前串的长度i为奇数,可以 (1)长度为i/2的串加倍,再加上一个a:dp[i / 2]

Codeforces Round #260 (Div. 1) A. Boredom (DP)

题目链接:http://codeforces.com/problemset/problem/455/A A. Boredom time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Alex doesn't like boredom. That's why whenever he gets bored, he comes up with

Codeforces118D Caesar&#39;s Legions(DP)

题目 Source http://codeforces.com/problemset/problem/118/D Description Gaius Julius Caesar, a famous general, loved to line up his soldiers. Overall the army had n1 footmen and n2 horsemen. Caesar thought that an arrangement is not beautiful if somewhe

hdu 5623 KK&#39;s Number(dp)

问题描述 我们可爱的KK有一个有趣的数学游戏:这个游戏需要两个人,有N\left(1\leq N\leq 5*{10}^{4} \right)N(1≤N≤5∗10?4??)个数,每次KK都会先拿数.每次可以拿任意多个数,直到NN个数被拿完.每次获得的得分为取的数中的最小值,KK和对手的策略都是尽可能使得自己的得分减去对手的得分更大.在这样的情况下,最终KK的得分减去对手的得分会是多少? 输入描述 第一行一个数T\left( 1\leq T\leq 10\right)T(1≤T≤10),表示数据组

Ural 1353 Milliard Vasya&#39;s Function(DP)

题目地址:Ural 1353 定义dp[i][j],表示当前位数为i位时,各位数和为j的个数. 对于第i位数来说,总可以看成在前i-1位后面加上一个0~9,所以状态转移方程就很容易出来了: dp[i][j]=dp[i][j]+dp[i][j-1]+dp[i][j-2]+.......+dp[i][j-9]: 最后统计即可. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <

HDU 4908 (杭电 BC #3 1002题)BestCoder Sequence(DP)

题目地址:HDU 4908 这个题是从m开始,分别往前DP和往后DP,如果比m大,就比前面+1,反之-1.这样的话,为0的点就可以与m这个数匹配成一个子串,然后左边和右边的相反数的也可以互相匹配成一个子串,然后互相的乘积最后再加上就行了.因为加入最终两边的互相匹配了,那就说明左右两边一定是偶数个,加上m就一定是奇数个,这奇数个的问题就不用担心了. 代码如下: #include <iostream> #include <stdio.h> #include <string.h&g

Sicily 1146:Lenny&#39;s Lucky Lotto(dp)

题意:给出N,M,问有多少个长度为N的整数序列,满足所有数都在[1,M]内,并且每一个数至少是前一个数的两倍.例如给出N=4, M=10, 则有4个长度为4的整数序列满足条件: [1, 2, 4, 8], [1, 2, 4, 9], [1, 2, 4, 10], [1, 2, 5, 10] 分析:可用动态规划解题,假设dp[i][j],代表满足以整数i为尾数,长度为j的序列的个数(其中每一个数至少是前一个数的两倍).那么对于整数i,dp[i][j] 等于所有dp[k][j-1]的和,其中k满足:

UVA542 - France &#39;98(dp)

UVA542 - France '98(dp) 题目链接 题目大意:之前题目意思还以为看懂了,其实没看明白,它已经把各个选手分在各自所在的区域里面,这就意味着第一次的PK的分组已经确定,而且冠军必须是从两个左右分区出来的胜利者才有机会pk冠军. 解题思路:那么从1-16这个大的区间内诞生出来的冠军可能是来自左边,也可能是右边,然后再左边右边的子区间递归找出冠军.f[i][l][r]表示l-r这个区间的胜利者是i的概率,那么假设i在区间的最左边,f[i][l][r] = Sum(f[i][l][m

HDU 4968 Improving the GPA(dp)

HDU 4968 Improving the GPA 题目链接 dp,最大最小分别dp一次,dp[i][j]表示第i个人,还有j分的情况,分数可以减掉60最为状态 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int t, avg, n; double dp1[15][405], dp2[15][405]; double get(int x) { if