『Leetcode 5047』多边形三角剖分的最低得分

『题目』:

 给定 N N N,想象一个凸 N N N 边多边形,其顶点按顺时针顺序依次标记为 A [ 0 ] , A [ i ] , . . . , A [ N − 1 ] A[0], A[i], ..., A[N-1] A[0],A[i],...,A[N1]
假设您将多边形剖分为 N − 2 N-2 N2 个三角形。对于每个三角形,该三角形的值是顶点标记的乘积,三角剖分的分数是进行三角剖分后所有 N − 2 N-2 N2 个三角形的值之和。
返回多边形进行三角剖分后可以得到的最低分。

『输入输出』:

输入输出
[1,2,3]6
[3,7,4,5]144
[1,3,1,4,1,5]13

『题解』:

 这道题比较难想象的是这个dp的规则,因为图是一个环,所以dp不好处理,首先要知道 N − 2 N-2 N2 条边能保证某一条边肯定会落在某一个三角形上面,如下面图边 [ 0 , 1 ] [0,1] [0,1]所示,从边 [ 0 , 1 ] [0,1] [0,1]出发选一个顶点 k k k,这里的 k = 3 k=3 k=3,所以就可以将图继续切分成两个子图进行递归求解。从而可以推出公式,其中 d p ( l , r ) dp(l,r) dp(l,r) 代表以从 l l l r r r 的多边形,以 [ l , r ] [l,r] [l,r]为底边。
d p ( l , r ) = { 0 if  ( r − l ) < 2 m i n ( d p ( l , k ) + d p ( k , r ) + V l k r ) if  l < k < r , k = l + 1... r − 1 dp(l,r)= \begin{cases} 0 & \text {if $(r-l) \lt 2$} \\ min(dp(l,k)+dp(k,r)+V_{lkr}) & \text{if $l \lt k \lt r$},k=l+1...r-1 \end{cases} dp(l,r)={0min(dp(l,k)+dp(k,r)+Vlkr)if (rl)<2if l<k<rk=l+1...r1

『实现』:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
/**
 * Author:
 *      Gavinjou大笨象
 * Date:
 *      2019-05-06
 * Description:
 *      三角最优子结构
 */
int N;
//当钱所选的边是a,剩下还要选的条数
int dp[55][55];
int valueA[55];

int flag[55];

int Min(int a , int b)
{
    if(a < b) return a;
    return b;
}

int deep(int *A,int l,int r)
{   
    //答案值为无穷大
    int ans = -1;
    //如果没办法组成三角型,答案返回的值为0
    if(r - l < 2) return 0;
    //返回记忆值
    if(dp[l][r] != -1) return dp[l][r];

    //寻找一个定义与边[l,r]形成一个三角形
    for(int k = l + 1;k < r;k++)
    {   
        //计算这个三角形的权值
        int value = (*(A + l)) * (*(A + k)) * (*(A + r));
        //将当前的多边形切分成两个子多边形
        int tmp = deep(A,l,k) + deep(A,k,r) + value;

        //求出当前的正多边形的最小值
        if( ans == -1)
        {
            ans = tmp;
        }
        else
        {
            ans = Min(tmp,ans);
        }
    }

    dp[l][r] = ans;
    return ans;
}

int minScoreTriangulation(int* A, int ASize)
{

    N = ASize;
    memset(dp,-1,sizeof(dp));
    memset(flag,0,sizeof(flag));

    return deep(A,0,N-1);
}

int main()
{
    int n;
    int a[55];
    scanf("%d",&n);

    for(int i = 0; i < n; i++)
    {
        scanf("%d",&a[i]);
    }
    int ans = minScoreTriangulation(a,n);

    printf("%d\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值