多变三角剖分的最低得分

25 篇文章 0 订阅
5 篇文章 0 订阅

来源: LeetCode 1039 多变三角剖分的最低得分

题目描述

给定 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
解释:有两种三角剖分,可能得分分别为:3*7*5 + 4*5*7 = 245,或 3*4*5 + 3*4*7 = 144。最低分数为 144。

示例 3:
输入:[1,3,1,4,1,5]
输出:13
解释:最低分数三角剖分的得分情况为 1*1*3 + 1*1*4 + 1*1*5 + 1*1*1 = 13。
 
 提示:
3 <= A.length <= 50
1 <= A[i] <= 100

思路分析

这道题仍然是一道典型的区间DP
区间DP最关键的就是要确定基本情况和如何刻画区间
假设我们得到的多边形是三角形那么答案就是这三个点的乘积
一个多边形我们可以用点集来表示
dp[i][j] 表示[i,j]区间的最低得分
那么区分子问题与父问题的参数应该就是区间长度
base case 为 长度为3 那么低于3的长度都应该为0
- 输入
dp[i][j] = 0  j - i <2
- 输出
dp[0][len - 1]
- 状态转换
dp[i][j] = dp[i][k] + dp[k][j] + A[i]*A[k]*A[j]
k from i + 1 to j-1
- 区间长度作为区分子问题和父问题的点 

代码

class Solution {
public:
    int minScoreTriangulation(vector<int>& A) {
        // N^2种分割的可能
        // N^2 - n^3
        // dp[i][j] [i,j]的最低得分 i +1 < k < j dp[i][j] =min(dp[i][k] + dp[k][j] + A[i]*A[k]*A[j])
        // base case r = 3 j - i = 2       
        vector<vector<int>> dp(A.size(), vector<int>(A.size(), 0));
        for(int r = 2; r<A.size(); ++r){
            int j;
            for(int i = 0; i+r<A.size(); ++i){
                j = i+r;
                dp[i][j] = INT_MAX;
                for(int k = i+1; k<j; ++k){
                    dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j] + A[i] * A[k] * A[j]);
                }
            }
        } // 区间DP,以区间长度作为区分的标志
        // for(auto a:dp){cout << endl; for(auto b:a) cout << b << '\t';}
        return dp[0].back();
    }
};

算法分析

时间复杂度: 	O(N^3)
空间复杂度:		O(N^2)

代码改进

这道题理论上可以用贪心算法去做
动态规划每一层去求解dp[i][j]的时候都要求分割点,即i,j,k将多边形分为了三部分,然后我们针对i,j,k建立了一个三重循环
我们可以假设每一次只用一条线将多边形分为两部分,那么分割的这个线段上的点就要计算两次
我们期望每次分割带来的代价最小,那就选择乘积最小的一对
通过N^2时间求解每一对的最小乘积
每一次选择后会将原区间分为两部分,再依次选择在这两部分内的最小乘积,可以在O(N^2)时间内解决该问题
理论上应该是正确的,很遗憾我没时间实现

相似扩展

归纳总结

典型区间DP
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值