题目:
给定 N,想象一个凸 N 边多边形,其顶点按顺时针顺序依次标记为 A[0], A[i], ..., A[N-1]。
假设您将多边形剖分为 N-2 个三角形。对于每个三角形,该三角形的值是顶点标记的乘积,三角剖分的分数是进行三角剖分后所有 N-2 个三角形的值之和。
返回多边形进行三角剖分后可以得到的最低分。
示例 :
![0b3fe7ed6efb29a3228d5ba3ea4f7448.png](https://i-blog.csdnimg.cn/blog_migrate/b6475430250d399bc41445aed9cf82ec.png)
输入:[3,7,4,5]
输出:144
解释:有两种三角剖分,可能得分分别为:3*7*5 + 4*5*7 = 245,或 3*4*5 + 3*4*7 = 144。最低分数为 144。
思路:
用三重循环进行求解,第一重循环用i表示多边形的第一个角,第二重循环用j表示多边形的最后一个角,用组成这个多边形的角表示该多边形为:i,i+1,……,j-1,j;再加第三重循环,该循环中用m表示对当前多边形的划分;将多边形划分为两部分:i,i+1,……m,j 和 i,m,……,j-1,j;这样多边形i,i+1,……,j-1,j的得分变为两个子多边形的得分之和;
![80c4c479388e8060217fba73e82eb1e7.png](https://i-blog.csdnimg.cn/blog_migrate/691f87d890e125487eb0c5bb7cbb75f2.png)
例如,对于图中的多边形,在计算其子多边形01234的得分时,可将其划分为012和023两个多边形以及三角形024的得分。
用数组dp[i][j]记录子多边形i,i+1,……,j-1,j的得分,下面给出dp[0][4]的遍历过程,读者可结合代码进行理解:
![578a5456fcc05e52c07436263798a535.png](https://i-blog.csdnimg.cn/blog_migrate/972e5afa7fd23d2d39f13d41afe9ed9b.jpeg)
leetcode链接:力扣
哔哩哔哩链接:https://www.bilibili.com/video/BV1aE411p7pt?p=7
代码和注释:
/**
* 注释及测试:Team317
* 题解:njyang-yang-yang
**/
#include<iostream>
#include<vector>
#include<string.h>
using namespace std;
class Solution {
public:
int minScoreTriangulation(vector<int>& A) {
int dp[50][50]; // 定义一个DP数组,用于存储计算数据
memset(dp, 0, sizeof(dp)); // 将dp数组初始化为0
for(int j=2;j<A.size();j++){ // j为子多边形的最后一个角
for(int i=j-2;i>=0;i--){ // i为子多边形的第一个角
for(int m=i+1;m<j;m++){ // m为子多边形的进一步划分
if(dp[i][j]==0){ // 如果多边形i,i+1,……,j-1,j为被计算
// 由m划分子多边形后,子多边形的得分变为三角形imj和两个更小的多边形的得分之和
dp[i][j]=A[i]*A[j]*A[m]+dp[i][m]+dp[m][j];
}else{
// 如果多边形i,i+1,……,j-1,j的得分已经计算过了,则更新其得分
dp[i][j]=min(dp[i][j], A[i]*A[j]*A[m]+dp[i][m]+dp[m][j]);
}
// cout<<"i,j,m"<<i<<j<<m<<endl;
}
}
}
return dp[0][A.size()-1]; // dp[0][n-1]记录了多边形的最终得分
}
};
int main(){
vector<int> arr = {1, 3, 1, 4, 1, 8};
Solution S;
int result = S.minScoreTriangulation(arr);
cout<<"result:"<<result<<endl;
system("pause");
return 0;
}