[LeetCode刷题笔记]1039. 多边形三角剖分的最低得分 - 动态规划问题

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

1 问题描述

题目描述

注意:3≤顶点个数≤50

2 问题分析

1.利用动态规划解题如何存储中间结果?
题目中是让求解三角形三顶点乘积的最小值,对于多边形中的三个不同的顶点,我们分别记作A,B,C.那么我们可以固定其中的两个顶点A,B,然后遍历A,B间的所有顶点,去获取最小的乘积值.所以我们使用二维数组来存储动态规划子问题的解.
2.我们需要实现一个什么样的函数?
我们实现的函数需要能够保证对于传递给它的数组(即多边形),能过正确返回得分的最小值.同时我们需要确定多边形中找到的分析1中的那两个点.
确定函数的参数为(数组,数组大小,起点,终点)
3.如何获得最小的结果值?
对于起点和终点,我们需要从起点后的一个点,遍历到终点前的一个点,如果满足 n u m s [ s t a r t ] ∗ n u m s [ i ] ∗ n u m [ e n d ] < n u m s [ n o w ] nums[start] * nums[i] * num[end] < nums[now] nums[start]nums[i]num[end]<nums[now],那么,我们就把这个最小值存入到二位数组中. n u m s [ n o w ] nums[now] nums[now]我们可以建立一个变量来记录.
4.二维数组的初始值?
最开始的时候时候还没有开始计算,所以二维数组中的所有值都是0.

3 变量设计

二维数组:我们用A[51][51]来存储所有的子问题的结果.

n u m s [ n o w ] nums[now] nums[now]:我们直接用变量result来记录这个最终结果.

中间结果:我们使用临时变量tmp来存储每次计算结果
-------------即 n u m s [ s t a r t ] ∗ n u m s [ i ] ∗ n u m [ e n d ] nums[start] * nums[i] * num[end] nums[start]nums[i]num[end]

循环变量:由于函数参数传入的是起点和终点,那我们需要计算位于起点和终点之间的点的个数 n n n.同时我们用 i i i来作为遍历时候的标识.

函数: d p ( i n t − ∗ A , i n t − A S i z e , i n t − s t a r t , i n t − e n d ) dp(int-*A, int-ASize, int-start, int-end) dp(intA,intASize,intstart,intend),这里取动态规划的缩写来作为函数名.每次调用这个函数我们就实现了求得起点为start终点为end的最小值.函数内部的细节将会写在代码的注释中.

3 代码实现

unsigned int res_cache[51][51] = {0};

unsigned int dp(int *A, int Asize, int start, int end)
{
    int i;
    // 这个记录每次传递进函数内部的点的个数
    int n = end - start;
    // 这个变量用来记录结果值result
    unsigned int res;
    // 这个用来充当临时变量
    unsigned int tmp;
    // 两个点不能组成三角形
    if(n<2) return 0;
    // 如果已经有了计算结果,那么直接返回就行
    if(res_cache[start][end]>0) return res_cache[start][end];
    // 当n==2的时候,说明一共有三个点,0-1-2
    if(n==2)
    {	// 这个计算结果一定就是这三个点的计算结果了,因为没得选
        res = A[start] * A[start+1] * A[end];
        // 将结果值赋给数组
        res_cache[start][end] = res;
        return res;
    }
    // 这里一定要写-1,因为二位函数的赋值为0,如果不写-1的话
    //就无法进行了. ( 0 == 0 ) //这里不是颜文字!!
    res = -1;
    // 注意 i 从start 的下一个顶点开始
    for(i=start+1; i<end; i++)
    {
    	// 先计算乘积值
        tmp = A[start] * A[i] * A[end];
        // 如果i等于最后一个顶点的前一个顶点
        if(i == end-1)
        {   // 那么我们进行划分后,就形成了一条新的边start-i
            // 为什么没有形成 i - end 边呢?
            // 因为 i - end - start 形成了闭循环.
            // 这条边也需要去寻找属于它的最小值
            tmp += dp(A, Asize, start, i);
        }
        else
        {
            // 这个情况下
            // 我们的划分形成了两条新的边 start-i 和 i - end
            // 我们还要去寻找这两条边的最小值
            tmp += dp(A, Asize, start, i) + dp(A, Asize, i ,end);
        }
        if(res > tmp)
        {
            res = tmp;
        }
    }
    // 最后将记录的最小res返回给二维数组
    res_cache[start][end] = res;
    return res;
}

int minScoreTriangulation(int* A, int ASize)
{
    // memset函数简介
    // 对[参数1]位置后面[参数3]个字节的空间置成[参数2]
    memset(res_cache, 0, sizeof(res_cache));
    return dp(A, ASize, 0, ASize-1);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值