【leetcode_week135】移动石子直到连续II_多边形三角剖分的最低得分

博客围绕LeetCode题目展开,包括“移动石子直到连续II”和“多边形三角剖分的最低得分”。前者需计算使石子位置连续的最小和最大移动次数;后者要得到多边形三角剖分的最低分。文中给出题目描述、解题思路及部分代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


https://leetcode-cn.com/contest/weekly-contest-135


移动石子直到连续II

描述

在一个长度无限的数轴上,第 i 颗石子的位置为 stones[i]。如果一颗石子的位置最小/最大,那么该石子被称作端点石子。
每个回合,你可以将一颗端点石子拿起并移动到一个未占用的位置,使得该石子不再是一颗端点石子。
值得注意的是,如果石子像 stones = [1,2,5] 这样,你将无法移动位于位置 5 的端点石子,因为无论将它移动到任何位置(例如 0 或 3),该石子都仍然会是端点石子。
当你无法进行任何移动时,即,这些石子的位置连续时,游戏结束。
要使游戏结束,你可以执行的最小和最大移动次数分别是多少? 以长度为 2 的数组形式返回答案:answer = [minimum_moves, maximum_moves] 。

示例 :
输入:[7,4,9]
输出:[1,2]
解释:
我们可以移动一次,4 -> 8,游戏结束。
或者,我们可以移动两次 9 -> 5,4 -> 6,游戏结束。

思路

这题比之前的难,但是最大值方面 跟之前差不多,也是看中间的空位数,只是多了端点石子移动之后不能还是端点这个要求,需要对两边端点都邻近空位的情况做一些不同的处理。
最小值,虽然代码能通过,但感觉怪怪的,逻辑上好像不对。。。

代码

class Solution {
public:
    vector<int> numMovesStonesII(vector<int>& stones) {
        int MAXSTONE = 1e9;
        // 给石子位置排序
        sort(stones.begin(), stones.end());
        // 获取石子总数量
        int n = stones.size();
        int minstep = MAXSTONE, maxstep = -MAXSTONE;

        // 最小
        for (int i = 0, j = 0; i < n; i++) {
            // 找一段能放下n个石子的区域
            while (j + 1 < n && stones[j + 1] - stones[i] < n)
                j++;
            // 看还有多少个石子在区域之外,那么至少要移动那么多次才能将石子都移动到这个区域
            int res = n - (j - i + 1);

            // 如果这段区域本身就连续并且还剩一个在外面,并且这个落单的和连续的隔着不止一个空位,则需要再动一次
            if (res==1 && stones[j] - stones[i] == j - i && ((j+1<n && (stones[j+1] - stones[j])>2) || ((i>0 && (stones[i] - stones[i-1])>2))))
                res++;

            minstep = min(minstep, res);
        }
        
        // 最大
        maxstep = max(stones[n - 1] - stones[1], stones[n - 2] - stones[0]) - (n - 2);
        return {minstep, maxstep};
    }
};

多边形三角剖分的最低得分

描述

给定 N,想象一个凸 N 边多边形,其顶点按顺时针顺序依次标记为 A[0], A[i], …, A[N-1]。
假设您将多边形剖分为 N-2 个三角形。对于每个三角形,该三角形的值是顶点标记的乘积,三角剖分的分数是进行三角剖分后所有 N-2 个三角形的值之和。
返回多边形进行三角剖分后可以得到的最低分。
示例 :
输入:[3,7,4,5]
输出:144
解释:有两种三角剖分,可能得分分别为:375 + 457 = 245,或 345 + 347 = 144。最低分数为 144。

思路

本来是想用贪心来解的,尝试了几次,发现好像没办法做到。动态规划依旧不熟悉,先看别人的学习一下。

看了别人解答之后的代码

class Solution {
public:
    void mst(int i, int j, vector<int>& A, int dp[51][51]) {
        // 如果只剩两个点,则值为0
        if (j - i == 1) {
            dp[i][j] = 0;
            return;
        }
        // 剩三个点,直接相乘
        if (j - i == 2) {
            dp[i][j] = A[i]*A[i+1]*A[j];
            return;
          
        }
        int min = 1e9;
        //开始以A[start] A[end]为底边分割
        for(int top = i+1;top<j;++top){
            if(dp[i][top] == -1){
                mst(i,top,A,dp);
            }
            int mid = A[i]*A[top]*A[j];
            if(dp[top][j] == -1){
                mst(top,j,A,dp);
            }
            min = min<(dp[i][top]+mid+dp[top][j])?min:(dp[i][top]+mid+dp[top][j]);
        }
        dp[i][j] = min;
    }
    
    int minScoreTriangulation(vector<int>& A) {
        int dp[51][51];
        memset(dp, -1, sizeof(dp));
        int n = A.size();
        mst(0, n-1, A, dp);
        return dp[0][n-1];
    }
};

PS.参考的java版解答原文见 https://blog.youkuaiyun.com/weixin_36451489/article/details/89950753


题目

描述

思路

代码


题目

描述

思路

代码


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值