zoukankan      html  css  js  c++  java
  • [P1388] 算式

    Description

    给出 (n le 15) 个数字,不改变它们的相对位置,在中间加入 (k) 个乘号和 ((n-k-1)) 个加号,括号随便加,使最终结果尽量大。

    Solution

    说好不写题解了的老龄选手怎么又来灌水?突然被人甩了个题,难顶

    网上有大量题解都假设了,最优解一定可以表示为若干段和的乘积,但在有 0 存在的情况下显然存在反例

    解决方案是,放弃这个假设,但是最优子结构仍然可以使用

    仍然用 (f[i][j][k]) 表示区间 ([i,j]) 中添加了 (k) 个乘号的方案数

    转移时分别考虑用加号连接和乘号连接的情况即可

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    const int N = 1e2 + 5;
    int n, K;
    int a[N];
    int f[N][N][N];
    
    signed main()
    {
        cin >> n >> K;
        for (int i = 0; i < n; i++)
            cin >> a[i];
        memset(f, -1, sizeof f);
        for (int i = 0; i < n; i++)
            for (int j = i; j < n; j++)
                f[i][j][0] = a[j] + (j > i) * f[i][j - 1][0];
        for (int l = 0; l < n; l++)
            for (int i = 0, j = i + l; j < n; i++, j++)
                for (int k = 0; k <= K; k++)
                    for (int m = i; m < j; m++)
                        for (int x = 0; x <= k; x++)
                        {
                            if (~f[i][m][x] && ~f[m + 1][j][k - x])
                                f[i][j][k] = max(f[i][j][k], f[i][m][x] + f[m + 1][j][k - x]);
                            if (x < k)
                                if (~f[i][m][x] && ~f[m + 1][j][k - x - 1])
                                    f[i][j][k] = max(f[i][j][k], f[i][m][x] * f[m + 1][j][k - x - 1]);
                        }
        cout << f[0][n - 1][K] << endl;
    }
    
  • 相关阅读:
    HTTP浅析
    PHP CURL获取cookies模拟登录
    C++ builder 通过WMI方式修改DNS
    C语言List使用样例
    C语言 获取系统临时目录并获取临时文件名
    C语言 写文件样例
    vb wmi 修改ip地址、网关、DNS
    正则表达式校验IP地址
    c语言 vector使用样例
    C++ builder 通过WMI查询网卡对应的序号
  • 原文地址:https://www.cnblogs.com/mollnn/p/14721696.html
Copyright © 2011-2022 走看看