CodeForces - 935E Fafa and Ancient Mathematics

题意:

给定一个长度为 E E 的算式,格式为 d d d d 是个位数字) 或 ( E 1   o p   E 2 ) ( E_1~op~E_2) ,其中 E 1 , E 2 E_1, E_2 均为算式, o p op + + - 。在给定的算式中所有 o p op 均未知,用问号替代,再给定 P P M M ,表示能填入的 + + - 的个数,求表达式的最大值,保证 P + M P + M 等于问号数。 ( E 1 0 4 , m i n { P , M } 100 ) (|E| \leq 10^4, min\{P,M\} \leq 100)

链接:

https://codeforces.com/problemset/problem/935/E

解题思路:

所给的表达式为中缀表达式,可以用一棵二叉树表示。最大化表达式的值,用 d p dp 解决,考虑最后一个操作数,对于加法,需要最大化左右子树的值,减法则需要最大化左子树值、最小化右子树的值,故 m x [ u ] [ i ] [ j ] , m n [ u ] [ i ] [ j ] mx[u][i][j], mn[u][i][j] 分别维护 u u 为根的子树使用 i i 次加法、 j j 次减法的最大、最小值,对应可以转移。注意 m i n { P , M } 100 min\{P, M\}\leq 100 ,数组可以只开较小的那一维,另一维可以隐式表示。

参考代码:

#include<bits/stdc++.h>
 
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define sz(a) ((int)a.size())
#define pb push_back
#define lson (rt << 1)
#define rson (rt << 1 | 1)
#define gmid (l + r >> 1)
const int maxn = 1e4 + 5;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;

vector<int> G[maxn];
char s[maxn];
int mx[maxn][101], mn[maxn][101];
int n, P, M;

int dfs(int &p){

    if(isdigit(s[p])) return p++;
    if(s[p] == '('){

        int v1 = dfs(++p);
        int u = p;
        int v2 = dfs(++p);
        G[u].pb(v1), G[u].pb(v2);
        ++p;
        return u;        
    }
}

void dfs1(int u){

    for(int i = 0; i <= P; ++i){

        mx[u][i] = -inf;
        mn[u][i] = inf;
    }
    if(s[u] != '?'){

        mx[u][0] = mn[u][0] = s[u] - '0';
        return;
    }
    int v1 = G[u][0], v2 = G[u][1];
    dfs1(v1), dfs1(v2);
    for(int i = 0; i <= P; ++i){

        for(int j = P - i; j >= 0; --j){

            mx[u][i + j] = max(mx[u][i + j], mx[v1][i] - mn[v2][j]);
            mn[u][i + j] = min(mn[u][i + j], mn[v1][i] - mx[v2][j]);
            if(i + j + 1 > P) continue;
            mx[u][i + j + 1] = max(mx[u][i + j + 1], mx[v1][i] + mx[v2][j]);
            mn[u][i + j + 1] = min(mn[u][i + j + 1], mn[v1][i] + mn[v2][j]);
        }
    }
}

void dfs2(int u){

    for(int i = 0; i <= M; ++i){

        mx[u][i] = -inf;
        mn[u][i] = inf;
    }
    if(s[u] != '?'){

        mx[u][0] = mn[u][0] = s[u] - '0';
        return;
    }
    int v1 = G[u][0], v2 = G[u][1];
    dfs2(v1), dfs2(v2);
    for(int i = 0; i <= M; ++i){

        for(int j = M - i; j >= 0; --j){

            mx[u][i + j] = max(mx[u][i + j], mx[v1][i] + mx[v2][j]);
            mn[u][i + j] = min(mn[u][i + j], mn[v1][i] + mn[v2][j]);
            if(i + j + 1 > M) continue;
            mx[u][i + j + 1] = max(mx[u][i + j + 1], mx[v1][i] - mn[v2][j]);
            mn[u][i + j + 1] = min(mn[u][i + j + 1], mn[v1][i] - mx[v2][j]);
        }
    }
}

int main(){
 
    ios::sync_with_stdio(0); cin.tie(0);
    cin >> s + 1 >> P >> M;
    int p = 1, rt = dfs(p);
    if(P < M){

        dfs1(rt);
        cout << mx[rt][P] << endl;
    }
    else{

        dfs2(rt);
        cout << mx[rt][M] << endl;
    }
    // for(int i = 1; s[i]; ++i){

    //     if(s[i] == '(' || s[i] == ')') continue;
    //     for(int j = 0; j <= P; ++j){

    //         cout << i << " " << s[i] << " " << j << " " << mx[i][j] << " " << mn[i][j] << endl;
    //     }
    // }
    return 0;
}
发布了57 篇原创文章 · 获赞 0 · 访问量 1870

猜你喜欢

转载自blog.csdn.net/weixin_44059127/article/details/104100019
今日推荐