Codeforces 803E - Roma and Poker(dp)

题目链接

http://codeforces.com/contest/803/problem/E

思路

dp

状态表示

d[i][j] ,第i局得分为j是否成立

转移方程

  1. 这一局为?,即可能赢,输,平局: d[i][j]=d[i1][j1]|d[i1][j+1]|d[i1][j]
  2. 已经确定该局的状态,直接按照条件转移即可:
    a) ai=W:d[i][j]=d[i1][j1]
    b) ai=L:d[i][j]=d[i1][j+1]
    c) ai=D:d[i][j]=d[i1][j]

细节

  1. 注意可能最后得分是-k,所以在dp的时候,对j加上偏移量。
  2. 注意边界,在 i<j 一定不满足,并且 j=k or j=k 时,i必须为 n

代码

#include 

using namespace std;

inline int in() {int x; scanf("%d", &x); return x;}
#define pr(x) {cout << #x << ' ' << x << endl;}

const int maxn = 1000 + 5;
const int off = 2000;
int d[maxn][maxn + off], n, k;
char a[maxn];

int dfs(int i, int j) {
    if (i == 0) return d[i][j + off] = j ? 0 : 1;
    if (d[i][j + off] != -1) return d[i][j + off];
    if (i < j || (i != n && (j == k || j == -k))) return d[i][j + off] = 0;
    int ans = 0;
    if (a[i] == 'W') ans |= dfs(i - 1, j - 1);
    else if (a[i] == 'L') ans |= dfs(i - 1, j + 1);
    else if (a[i] == 'D') ans |= dfs(i - 1, j);
    else ans = dfs(i - 1, j - 1) | dfs(i - 1, j + 1) | dfs(i - 1, j);
    return d[i][j + off] = ans;
}

void FindPath(int i, int j) {
    if (i == 0) return;
    int ans = (a[i] == '?' ? (d[i - 1][j + 1 + off] ? 1 : (d[i - 1][j - 1 + off] ? -1 : 0)) : (a[i] == 'W' ? -1 : (a[i] == 'L' ? 1 : 0)));
    FindPath(i - 1, j + ans);
    if (ans == 1) cout << 'L';
    else if (ans == -1) cout << 'W';
    else cout << 'D';
}

int main() {
    n = in(), k = in();
    getchar();
    for (int i = 1; i <= n; i++) scanf("%c", &a[i]);
    memset(d, -1, sizeof(d));
    int ans = dfs(n, k);
    if (ans) {
        FindPath(n, k);
    } else {
        memset(d, -1, sizeof(d));
        ans = dfs(n, -k);
        if (ans) FindPath(n, -k);
        else cout << "NO" << endl;
    }
    return 0;
}

你可能感兴趣的:(dp,codeforces)