凸多边形的划分 ———区间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);
}
浙公网安备 33010602011771号