题目
题目来源:力扣(LeetCode)
给定 N,想象一个凸 N 边多边形,其顶点按顺时针顺序依次标记为 A[0], A[i], …, A[N-1]。
假设您将多边形剖分为 N-2 个三角形。对于每个三角形,该三角形的值是顶点标记的乘积,三角剖分的分数是进行三角剖分后所有 N-2 个三角形的值之和。
返回多边形进行三角剖分后可以得到的最低分。
示例 1:
输入:[1,2,3]
输出:6
解释:多边形已经三角化,唯一三角形的分数为 6。
示例 2:
输入:[3,7,4,5]
输出:144
解释:有两种三角剖分,可能得分分别为:375 + 457 = 245,或 345 + 347 = 144。最低分数为 144。
示例 3:
输入:[1,3,1,4,1,5]
输出:13
解释:最低分数三角剖分的得分情况为 113 + 114 + 115 + 111 = 13。
思路分析
- 3个点构成1个三角形
- 4个点构成1 + 1个三角形
- 5个点构成1 + 2 或 1 + 1 + 1 = 3个三角形
- 6个点构成1 + 3 或 1 + 1 + 2 = 4个三角形
- 7个点构成1 + 4 或 1 + 1 + 3 或1 + 2 + 2 = 5个三角形
代码实现
/**
* 这道题目的关键是:
* 可以把任何顶点数大于3的凸多边形分解为一个三角形和至多两个凸多边形,并且按这种
* 方式分割,最后n个顶点得到的一定是n - 2个三角形(我不知道最后得到的一定是n - 2个三角形怎么证明
* )。
* 那么这个就可以dp了
* @param {number[]} values
* @return {number}
*/
var minScoreTriangulation = function (values) {
const len = values.length
const dp = new Array(len)
// 因为dp求的是最小值,那么初始化为最大值
for (let i = 0; i < len; i++) dp[i] = new Array(len).fill(Infinity)
for (let i = 0; i < len; i++) {
// 顶点数小于3不能构成三角形,dp中不会有用到顶点数为1的情况。
//i、j包含顶点数小于2的情况的值都初始化为0,便于后面计算
dp[i][(i + 1) % len] = 0
}
// temp_len + 1代表凸多边形的顶点个数
// dp先求凸多边形有3个定点的情况,再求有4个顶点的情况下,直至求出有length个顶点的情况
for (let temp_len = 2; temp_len < len; temp_len++) {
// 这些顶点中第一个顶点是i,最后一个顶点是j。
// i和j都有可能为0 ~ (len - 1)(开闭区间)中的任何一个点
for (let i = 0; i < len; i++) {
let j = (i + temp_len) % len
// 虽然是循环的,但可以认为j在i的后面,也就是k永远不可能等于i或j
for (let k = (i + 1) % len; k !== j; k = (k + 1) % len) {
dp[i][j] = Math.min(dp[i][j], dp[i][k] + dp[k][j] + values[i] * values[k] * values[j])
}
}
}
return dp[0][len - 1]
};