AcWing 1069. 凸多边形的划分


题目传送门

一、题意分析

二、朴素做法

#include 

using namespace std;
const int N = 55;
const int INF = 0x3f3f3f3f;
int n;
int w[N];
int f[N][N];

int main() {
    //优化输入
    ios::sync_with_stdio(false);
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> w[i];
    //枚举区间长度
    for (int len = 3; len <= n; len++)
        for (int l = 1; l + len - 1 <= n; l++) {//枚举左端点
            int r = l + len - 1;//计算右端点
            f[l][r] = INF;      //预求最小,先设最大
            for (int k = l + 1; k < r; k++)//枚举第三点
                f[l][r] = min(f[l][r], f[l][k] + f[k][r] + w[l] * w[k] * w[r]);
        }
    //输出
    printf("%d", f[1][n]);
    return 0;
}

三、正规做法

#include

using namespace std;
typedef long long LL;
const int N = 55;
int n;              //n个顶点
int w[N];           //每个点的权重
vector f[N][N];//高精度存储最后的结果值

//对比两个高精度的大小
bool cmp(vector A, vector B) {
    if (B.size() == 0) return true;
    if (A.size() != B.size()) return A.size() < B.size();
    for (int i = A.size() - 1; i >= 0; i--)
        if (A[i] != B[i]) return A[i] < B[i];
    return true;
}

//高精加高精
vector add(vector A, vector B) {
    if (A.size() < B.size()) return add(B, A);
    vector c;
    int t = 0;
    for (int i = 0; i < A.size(); i++) {
        t += A[i];
        if (i < B.size()) t += B[i];
        c.push_back(t % 10);
        t /= 10;
    }
    while (t) c.push_back(t % 10), t /= 10;
    return c;
}

//乘法高精*低精
vector mul(vector a, LL b) {
    vector c;
    LL t = 0;
    for (int i = 0; i < a.size(); i++) {
        t += b * a[i];
        c.push_back(t % 10);
        t /= 10;
    }
    while (t) c.push_back(t % 10), t /= 10;
    return c;
}

int main() {
    //优化输入
    ios::sync_with_stdio(false);
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> w[i];

    //区间DP
    //此处初始状态f[l][l+1] = 0 初始就是空vector,不用额外设置
    for (int len = 3; len <= n; len++) {
        for (int l = 1; l + len - 1 <= n; l++) {
            int r = l + len - 1;
            //初始化初始状态
            for (int k = l + 1; k < r; ++k) {
                //三个顶点权值相乘
                vector v = mul(mul({w[l]}, w[k]), w[r]);
                //DP值相加
                v = add(add(f[k][r], f[l][k]), v);
                //是不是可以迁移
                if (cmp(v, f[l][r])) f[l][r] = v;
            }
        }
    }
    //输出最终答案
    vector res = f[1][n];
    //倒序输出
    for (int i = res.size() - 1; i >= 0; i--) printf("%d", res[i]);
    return 0;
}