• P4342


    P4342

    考虑 区间DP

    这题的符号既有加号又有乘号,那么就不能简单只维护,([l,r]) 区间的最大值。比如负数和负数相乘就变成整数比维护的最大值还要大这种情况。

    所以我们维护两个值:(dp_{max}[l][r],dp_{min}[l][r])

    分开计算:

    (op == t) : (dp_{max}[l][r] = max(dp_{max}[l][k]+dp_{max}[k + 1][r]),dp_{min}[l][r] = min(dp_{min}[l][k] + dp_{min}[k + 1][r]))

    (op == x):(dp_{max}[l][r] = max(dp_{max}[l][k] imes dp_{max}[k + 1][r],dp_{min}[l][k] imes dp_{min}[k + 1][r],dp_{min}[l][k] imes dp_{max}[k + 1][r],dp_{max}[l][k] imes dp_{min}[k + 1][r])) (dp_{min}[l][r] = min(dp_{min}[l][k] imes dp_{min}[k + 1][r],dp_{min}[l][k] imes dp_{min}[k + 1][r],dp_{min}[l][k] imes dp_{max}[k + 1][r],dp_{max}[l][k] imes dp_{min}[k + 1][r]))) 其实主要是考虑 相乘或相加的两个数大于 (0) 或者小于 (0)

    #include <bits/stdc++.h>
    #define SZ(X) ((int)(X).size())
    #define ALL(X) (X).begin(), (X).end()
    #define rep(I, N) for (int I = 1; I <= (N); ++I)
    #define repp(I, N) for (int I = 0; I < (N); ++I)
    #define FOR(I, A, B) for (int I = (A); I <= (B); ++I)
    #define FORR(I, A, B) for (int I = (A); I >= (B); I--)
    #define SORT_UNIQUE(c) (sort(c.begin(),c.end()), c.resize(distance(c.begin(),unique(c.begin(),c.end()))))
    #define GET_POS(c,x) (lower_bound(c.begin(),c.end(),x)-c.begin())
    #define MP make_pair
    #define PB push_back
    #define MS0(X) memset((X), 0, sizeof((X)))
    #define MS1(X) memset((X), -1, sizeof((X)))
    #define LEN(X) strlen(X)
    #define F first
    #define S second
    using namespace std;
    const int N = 300 + 5;
    const double eps = 1e-7;
    const int mod = 1e9 + 7;
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef long double LD;
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    typedef vector<LL> VL;
    typedef vector<PII> VPII;
    typedef pair<LL,LL> PLL;
    typedef vector<PLL> VPLL;
    LL gcd(LL a,LL b){return b>0?gcd(b,a%b):a;}
    LL ksm(LL a,LL b){LL ans = 1;while(b){if(b&1) ans = ans * a % mod;a = a * a % mod;b >>= 1;}return ans % mod;}
    map<PII, char> mp;
    LL dp_max[N][N];
    LL dp_min[N][N];
    LL a[N];
    char b[N];
    int totb = 0;
    int main() {
        int n;
        cin >> n;
        int tot = 0;
        rep(i,2 * n)
        {
            if(i % 2)
            {
                string s;
                cin >> s;
                b[++totb] = s[0];
            }
            else 
            {
                int x;
                cin >> x;
                a[++tot] = x;
            }
        }
        memset(dp_max,0xcf,sizeof dp_max);
        memset(dp_min, 0x3f, sizeof dp_min);
        rep(i,tot)
        {
            a[i + tot] = a[i];
            b[i + totb] = b[i];
        }
        rep(i,tot * 2) 
        {
            dp_max[i][i] = a[i];
            dp_min[i][i] = a[i];
        }
        FOR(len,2,tot * 2)
        {
            rep(l,tot * 2 - len + 1)
            {
                int r = l + len - 1;
                FOR(k,l,r - 1)
                {
                    if(b[k + 1] == 't')
                    {
                        LL &ans = dp_max[l][r];
                        ans = max(ans,dp_max[l][k] + dp_max[k + 1][r]);
                        LL &t = dp_min[l][r];
                        t = min(t, dp_min[l][k] + dp_min[k + 1][r]);
                    }
                    else 
                    {
                        LL &ans = dp_max[l][r];
                        ans = max(ans, dp_max[l][k] * dp_max[k + 1][r]);
                        ans = max(ans, dp_min[l][k] * dp_min[k + 1][r]);
                        ans = max(ans, dp_max[l][k] * dp_min[k + 1][r]);
                        ans = max(ans, dp_min[l][k] * dp_max[k + 1][r]);
                        LL &t = dp_min[l][r];
                        t = min(t,dp_min[l][k] * dp_min[k + 1][r]);
                        t = min(t,dp_max[l][k] * dp_max[k + 1][r]);
                        t = min(t,dp_max[l][k] * dp_min[k + 1][r]);
                        t = min(t, dp_min[l][k] * dp_max[k + 1][r]);
                    } 
                }
            }
        }
        LL ans = 0;
        vector<int> v;
        rep(i,tot)
        {
            ans = max(ans, dp_max[i][i + n - 1]);
        }
        rep(i,tot)
        {
            if(dp_max[i][i + n - 1] == ans)
                v.push_back(i);
        }
        cout << ans << endl;
        for (int i = 0;i < v.size();i++) cout << v[i] << ' ';
        cout << endl;
        return 0;
    }
    
    
  • 相关阅读:
    WEB前端工程师 – 职业生涯规划
    求Sn=a+aa+aaa+…+aaa…a的值
    输入一行字符,分别统计出其中英文字母 空格 数字和其他字符的个数
    getchar()的用法!
    求1+2+…+n的和不大于1000的最大自然数n
    编程打印输出*金字塔
    从键盘输入一个整数,判断该数是否回文数.
    编程求"水仙花数"
    编程求出1000以内的完全数
    输入两个正整数,求它们的最大公约数和最小公倍数.
  • 原文地址:https://www.cnblogs.com/strategist-614/p/12539413.html
Copyright © 2020-2023  润新知