凸多边形的划分 ———区间dp

https://ac.nowcoder.com/acm/contest/24213/1036

  • 一眼区间dp
  • 枚举中间节点,将左右区间合并,左区间为dp[i][k],右区间为dp[k][j],此次答案的贡献为arr[k]* arr[i]* arr[j]
  • 数据过大,使用int128
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n;
__int128 arr[200];
__int128 dp[200][200];
void put(__int128 x)
{
    if(x<0)
    {
        x=-x;
        putchar('-');
    }
    if(x>9) put(x/10);
    putchar(x%10+'0');
} 
signed main(){
    cin>>n;
    for(int i = 1;i<=2*n;i++){
        for(int j = 1;j<=2*n;j++){
            dp[i][j] = 1e30;
        }
    } 
    int len = 2;
    for(int i = 1;i<=2*n;i++){
            int j = i+len-1;
            dp[i][i] = 0;
            dp[i][j] = 0;
     }
    int num;
    for(int i = 1;i<=n;i++) cin>>num,arr[n+i] = arr[i] = __int128(num);
    for(len = 3;len<=n;len++){
        for(int i = 1;i<=2*n&&i+len-1<=2*n;i++){
            int j = i+len-1;
            if(len==3)  dp[i][j] = __int128(arr[i]*arr[i+1]*arr[j]);
            else
            for(int k = i+1;k<=j-1;k++){
                dp[i][j] = min(dp[i][j],dp[i][k]+dp[k][j]+__int128(arr[k]*arr[i]*arr[j]));
            }
        }
    } 
    __int128 maxn = 1e30;
    for(int i = 1;i<=n;i++){
        maxn = min(maxn,dp[i][i+n-1]);
       // cout<<dp[i][i+n-1]<<endl;
    }
    put(maxn);
}
posted @ 2023-04-24 19:36  重生之我是菜鸟  阅读(71)  评论(0)    收藏  举报