1039. 多邊形三角剖分的最低得分(Python)

難度:★★★★☆
類型:幾何,數(shù)組
方法:動(dòng)態(tài)規(guī)劃

題目

力扣鏈接請(qǐng)移步本題傳送門
更多力扣中等題的解決方案請(qǐng)移步力扣中等題目錄

給定 N,想象一個(gè)凸 N 邊多邊形,其頂點(diǎn)按順時(shí)針順序依次標(biāo)記為 A[0], A[i], ..., A[N-1]。

假設(shè)您將多邊形剖分為 N-2 個(gè)三角形。對(duì)于每個(gè)三角形,該三角形的值是頂點(diǎn)標(biāo)記的乘積,三角剖分的分?jǐn)?shù)是進(jìn)行三角剖分后所有 N-2 個(gè)三角形的值之和。

返回多邊形進(jìn)行三角剖分后可以得到的最低分。

示例 1:

輸入:[1,2,3]
輸出:6
解釋:多邊形已經(jīng)三角化,唯一三角形的分?jǐn)?shù)為 6。

示例 2:

輸入:[3,7,4,5]
輸出:144
解釋:有兩種三角剖分,可能得分分別為:375 + 457 = 245,或 345 + 347 = 144。最低分?jǐn)?shù)為 144。

示例 3:

輸入:[1,3,1,4,1,5]
輸出:13
解釋:最低分?jǐn)?shù)三角剖分的得分情況為 113 + 114 + 115 + 111 = 13。

提示:

3 <= A.length <= 50
1 <= A[i] <= 100

解答

我們先來理解一下什么是三角剖分。首先,多邊形每個(gè)頂點(diǎn)都是一個(gè)數(shù)字,三個(gè)頂點(diǎn)組成一個(gè)三角形,這個(gè)三角形的分?jǐn)?shù)就是三個(gè)頂點(diǎn)的乘積,多邊形有很多個(gè)頂點(diǎn),需要把這些頂點(diǎn)連線,這些線不能交叉,而且所有頂點(diǎn)都需要作為至少一個(gè)連線的端點(diǎn)。這樣多邊形就變成了只由三角形組成的一個(gè)狀態(tài)。多邊形的三角剖分就是拆好的三角形的分?jǐn)?shù)之和。

我們用動(dòng)態(tài)規(guī)劃解決。

【數(shù)組定義】

多邊形各個(gè)頂點(diǎn)是按順序編了號(hào)的,一個(gè)n邊形各個(gè)頂點(diǎn)是0,1,2,...,n-1。我們從中選兩個(gè)頂點(diǎn)i和j,且j>i+1,這樣從編號(hào)i到j(luò)的所有點(diǎn)就可以組成新的多邊形了(包括三角形)。

定義數(shù)組dp,維度為n×n,dp[i][j]表示由i,i+1,i+2,...j-1,j這些點(diǎn)組成的多邊形的三角剖分最小值。

【初始狀態(tài)】

因?yàn)樽詈笠笞钚≈?,我們就把dp數(shù)組中每個(gè)點(diǎn)填充為正無窮。

【遞推公式】

這里要解決dp[i][j]怎么求的問題。對(duì)于從i到j(luò)的所有點(diǎn)(不包括i和j),任選一點(diǎn)k(i<k<j),我們實(shí)際上就把從點(diǎn)i到點(diǎn)j的多邊形劃分成了三個(gè)小塊,分別是從i到k的小多邊形,從k到j(luò)的小多邊形以及三角形ikj。這時(shí),整體的分?jǐn)?shù)就很好計(jì)算了:

dp[k][j]+dp[i][k]+A[i]A[j]A[k]

根據(jù)題意,我們需要研究從i與j之間所有點(diǎn)k的情況,取其中最小的剖分?jǐn)?shù),作為dp[i][j]的值。

【返回值】

根據(jù)dp數(shù)組的含義,我們需要在遍歷完成后返回dp[0][-1]即可。

【注意事項(xiàng)】

遍歷順序需要留意,因?yàn)槲覀冊(cè)谶f推公式中提到,dp[k][j]和dp[i][k]是要先于dp[i][j]計(jì)算出來的,所以j正向遍歷時(shí),為了避免找不到緩存結(jié)果dp[k][j]和dp[i][k]的尷尬情況,我們需要將i逆序遍歷。保證遍歷過程以及dp數(shù)組更新的連續(xù)性。

最后得到dp數(shù)組實(shí)際上只有右上角半個(gè)三角形。

from typing import List


class Solution:
    def minScoreTriangulation(self, A: List[int]) -> int:
        n = len(A)
        dp = [[float('inf')] * n for _ in range(n)]
        for j in range(n):
            for i in reversed(range(j)):
                if j - i < 2:
                    dp[i][j] = 0
                else:
                    for k in range(i+1, j):
                        dp[i][j] = min(dp[i][j], A[i]*A[j]*A[k]+dp[i][k]+dp[k][j])
        return dp[0][n-1]

如有疑問或建議,歡迎評(píng)論區(qū)留言~

有關(guān)更多力扣中等題的python解決方案,請(qǐng)移步力扣中等題解析

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容