本题凸多边形要划分成三角形可以从定点和定边两个角度来看,从定点角度来看的话定一个点后,后两个点再去分隔所形成的的三个多边形并不是连续的区间。这样的话对于区间dp来说不好处理。
但是从定边这个角度来看的话,定一条边后去选取另外一个点这样形成的一个区域一定是一个三角形,另外两个区域一定是一个连续的区间,那么我们将0,1作为选取的边来看的话也就解决了圈的问题。
所以在这里可以将动态规划转移方程:dp[i][j] = min(dp[i][j], dp[i][k]+dp[k][j]+a[i]*a[j]*a[k]);。
本题的数据过大,得使用int128,这是个比较坑的点。
#include <bits/stdc++.h> //dp[i][j] = min(dp[i][j], dp[i][k]+dp[k][j]+a[i]*a[j]*a[k]); using namespace std; #define int long long const int maxn = 55; int n; __int128 a[maxn]; __int128 dp[maxn][maxn]; __int128 read() { __int128 x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } void write(__int128 x) { if(x<0) { putchar('-'); x=-x; } if(x>9) write(x/10); putchar(x%10+'0'); } signed main() { cin>>n; for (int i=1;i<=n;i++) { a[i] = read(); } for (int len = 3;len<=n;len++) { for (int l=1;l+len-1<=n;l++) { int r = l+len-1; dp[l][r] = 1e30; for (int k=l+1;k<r;k++) { dp[l][r] = min(dp[l][r], dp[l][k]+dp[k][r]+a[l]*a[r]*a[k]); } } } write(dp[1][n]); return 0; }