loj10149. 「一本通 5.1 例 3」凸多边形的划分

时间:2022-05-24 04:50:34

思路:

  区间dp,数值范围较大,需写高精度·。

  以下是两种dp的方法,都可以AC

#include<cstdio>
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 65;
inline void qread(int &x) {
    x = 0;
    register int ch = getchar();
    while(ch < '0' || ch > '9')    ch = getchar();
    while(ch >= '0' && ch <= '9')    x = 10 * x + ch - 48, ch = getchar();
}
struct bignum {
    int num[40];
    bignum(){
        num[0] = 1;
    }
    void set(int x) {
        memset(num, 0, sizeof(num));
        while(x) {
            num[++num[0]] = x % 10;
            x /= 10;
        }
        if(!num[0])    num[0] = 1;
    }
    void clear() {
        memset(num, 0, sizeof(num));
        num[0] = 1;
    }
    void INF() {
        num[0] = 30;
        num[num[0]] = 9;
    }
};
bignum minn(const bignum &a, const bignum &b) {
    if(a.num[0] > b.num[0])    return b;
    if(a.num[0] < b.num[0])    return a;
    for(int i = a.num[0]; i >= 1; --i) {
        if(a.num[i] > b.num[i])    return b;
        if(a.num[i] < b.num[i])    return a;
    }
    return a;
}
bignum add(bignum a, bignum b) {
    bignum c;
    c.clear();
    c.num[0] = max(a.num[0], b.num[0]);
    int jw = 0;
    for(int i = 1; i <= c.num[0]; ++i) {
        c.num[i] = a.num[i] + b.num[i] + jw;
        jw = c.num[i] / 10;
        if(jw)    c.num[i] -= 10;
    }
    if(jw)    c.num[++c.num[0]] = jw;
    return c;
}
bignum mul(bignum a, bignum b) {
    bignum c;
    c.clear();
    c.num[0] = a.num[0] + b.num[0];
    
    for(int i = 1; i <= a.num[0]; ++i){
        int jw = 0;
        for(int j = 1; j <= b.num[0]; ++j) {
            c.num[i + j - 1] += a.num[i] * b.num[j] + jw;
            jw = c.num[i + j - 1] / 10;
            c.num[i + j - 1] %= 10;
        }
        c.num[i + b.num[0]] = jw;
    }
    while(c.num[c.num[0]] == 0)
        --c.num[0];
    if(!c.num[0])    c.num[0] = 1;    
    return c;
}
void show(const bignum &a) {
    for(int i = a.num[0]; i >= 1; --i)
        putchar(a.num[i] + 48);
}
int n;
bignum data[maxn << 1];
bignum dp[maxn << 1][maxn << 1];
int main(void) {
    qread(n);
    for(int i = 1; i <= n; ++i) {
        int x;
        qread(x);
        data[i].set(x);
        data[i + n] = data[i];
    }
    data[n << 1 | 1] = data[1];
    for(int i = 1; i < n; i++)
        dp[i][i + 1].set(0);
    for(int i = 2; i < n; i++)
        for(int j = 1; j <= n - i; j++) {
            dp[j][j + i].INF();
            for(int k = j + 1; k < i + j; k++)
                dp[j][j + i] = minn(dp[j][j + i], add(add(dp[j][k], dp[k][j + i]), mul(mul(data[i + j], data[j]), data[k])));

        }
    show(dp[1][n]);
}
#include<cstdio>
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 65;
inline void qread(int &x){
    x = 0;
    register int ch = getchar();
    while(ch < '0' || ch > '9')    ch = getchar();
    while(ch >= '0' && ch <= '9')    x = 10 * x + ch - 48, ch = getchar();
}
struct bignum{
    int num[40];
    void set(int x){
        memset(num, 0, sizeof(num));
        while(x){
            num[++num[0]] = x % 10;
            x /= 10;
        }
    }
    void clear(){
        memset(num, 0, sizeof(num));
    }
    void INF(){
        num[0] = 30;
        for(int i=1; i<=num[0]; ++i)
            num[i] = 9;
    }    
};
bignum minn(const bignum &a, const bignum &b){
    if(a.num[0] > b.num[0])    return b;
    if(a.num[0] < b.num[0])    return a;
    for(int i=a.num[0]; i>=1; --i){
        if(a.num[i] > b.num[i])    return b;
        if(a.num[i] < b.num[i])    return a;    
    }
    return a;
}    
bignum add(const bignum &a, const bignum &b){
    bignum c;
    c.clear();
    c.num[0] = max(a.num[0], b.num[0]);
    int jw = 0;
    for(int i=1; i<=c.num[0]; ++i){
        c.num[i] = a.num[i] + b.num[i] + jw;
        jw = c.num[i] / 10;
        if(jw)    c.num[i] -= 10;
    }
    if(jw)    c.num[++c.num[0]] = jw;
    return c;
}
bignum mul(bignum a, bignum b) {
    bignum c;
    c.clear();
    c.num[0] = a.num[0] + b.num[0];
    
    for(int i = 1; i <= a.num[0]; ++i){
        int jw = 0;
        for(int j = 1; j <= b.num[0]; ++j) {
            c.num[i + j - 1] += a.num[i] * b.num[j] + jw;
            jw = c.num[i + j - 1] / 10;
            c.num[i + j - 1] %= 10;
        }
        c.num[i + b.num[0]] = jw;
    }    
    while(c.num[c.num[0]] == 0)
        --c.num[0];
    if(!c.num[0])    c.num[0] = 1;    
    return c;
}
void show(const bignum &a){
    for(int i=a.num[0]; i>=1; --i)
        putchar(a.num[i] + 48);
}
int n;
bignum data[maxn << 1];
bignum dp[maxn << 1][maxn << 1];
int main(void){
    qread(n);
    for(int i=1; i<=n; ++i){
        int x;
        qread(x);
        data[i].set(x);
        data[i + n] = data[i];
    }
    data[n << 1 | 1] = data[1];
    for(int L = 2; L < n; ++L)
        for(int i = 1; i <= (n << 1) - L; ++i){
            int j = i + L;
            dp[i][j].INF();
            for(int k = i + 1; k < j; ++k)
                dp[i][j] = minn(dp[i][j], add(dp[i][k], add(dp[k][j], mul(data[i], mul(data[j], data[k])))));    
        }
    bignum ans;
    ans.INF();
    for(int i=1; i<=n; ++i)
        ans = minn(ans, dp[i][i + n -1]);
    show(ans);
    cout << endl;        
}