题意:给出长度为n的字符串和一个数 k ,字符串有 'W' 表示 +1, 'L' 表示 -1, 'D' 表示 0 , '?' 表示不确定。现在要你确定 '?', 问有没有一种方案使得最后所有字符的和等于 k 或者 -k ,且任意长度小于 k 的前缀和不能等于 k 和 -k 。
tags:因为 n <=1000 ,故前缀和的范围是在 -1000至1000 ,所以考虑 dp 。
dp[i][j] 表示前 i 个字符的前缀和为 j 是否可能,同时记录第 i 个字符是什么,最后倒推回去即可。
因为 j 会是负数,我们可以加上一个数比较大的数使之为正数。
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define MP make_pair #define PB push_back #define fi first #define se second typedef long long ll; const int N = 1005, M = 2*N; int n, k, dp[N][M]; char s[N]; int main() { scanf("%d%d%s", &n, &k, s+1); dp[0][1005]=-2; rep(i,1,n-1) { if(s[i]!='?') { int tmp = (s[i]=='W' ? 1 : (s[i]=='L' ? -1 : 0)); rep(j, N-k+1, N+k-1 ) if(dp[i-1][j-tmp]) { dp[i][j] = (tmp ? tmp : 2); } } else { rep(tmp, -1, 1) { rep(j, N-k+1, N+k-1 ) if(dp[i-1][j-tmp]) { dp[i][j] = (tmp ? tmp : 2); } } } } if(s[n]!='?') { int tmp = (s[n]=='W' ? 1 : (s[n]=='L' ? -1 : 0)); rep(j, N-k, N+k ) if(dp[n-1][j-tmp]) { dp[n][j] = (tmp ? tmp : 2); } } else { rep(tmp, -1, 1) { rep(j, N-k, N+k ) if(dp[n-1][j-tmp]) { dp[n][j] = (tmp ? tmp : 2); } } } int cnt=0, j2[3]={N-k, N+k}; rep(j, 0,1) if(dp[n][j2[j]]) { int jj=j2[j]; per(i,n,1) { s[++cnt] = (dp[i][jj]==1 ? 'W' : (dp[i][jj]==-1 ? 'L' : 'D')); jj = (dp[i][jj]==1 ? jj-1 : (dp[i][jj]==-1 ? jj+1 : jj)); } per(i,cnt,1) putchar(s[i]); return 0; } puts("NO"); return 0; }