動態規劃 多邊形遊戲

2021-10-02 18:32:58 字數 3681 閱讀 6561

已知乙個n邊的多邊形,在n個頂點上都有乙個整數,在n條邊上都存在『+』或『*』號。

遊戲開始時,撤掉一條邊。剩下的就會變成由n個頂點,n-1條邊所組成的鏈條。

將其中兩個相鄰的頂點按之間的運算子進行運算,這兩個頂點和這條邊被替換為運算結果,鏈條被削減為n-1個頂點,n-2條邊。如此反覆直到最後只剩下乙個點。

多邊形遊戲的目的是找到最大的最後乙個點。

我們首先來分析鏈條,假設這是一條頂點數為n,邊數為n-1的鏈條。取位置為s的邊。這條邊將鏈條分為了[0:s]和[s+1:n-1]兩條鏈條。

鏈條最小值

最大值[0:s]ab

[s+1:n-1]cd

如果這條邊是『+』,那麼問題就簡單了,[0:n-1]的值一定在a+c到b+d之間。

如果這條邊是『*』,因為涉及到頂點含有負數的關係,所以只能將abcd兩兩

相乘,[0:n-1]的值是在min和max之間。

根據上面的分析,我們可以得知,多邊形遊戲也是有最優子結構的。

傳統的做法是建立乙個兩層的二維陣列m[ i ][ j ][ k ],代表以第i個點開頭並且長為j的鏈條的最大值(k=1)和最小值(k=0)。

在最後尋找結果的時候只需要找m[ i ][ n ][ 1 ]中的最大值就可以了。

但是我不喜歡,寫**的時候太折騰人而且不易於維護。

***採用的這種在空間消耗上是略遜於傳統做法的(多申請了兩個長度為n的陣列)。但是好懂啊。

將鏈條重新「擺直」,頂點從0計數到n-1,邊從0計數到n-2。

在我的m[ i ][ j ]中,指代就不一樣了。他的意思是位置從 i 到 j 的鏈條。因此最後的結果在m[0][n-1][1]裡。

同樣的,我們把老朋友擺上來,本次的方向接著按這種方向走。

m[ i ][ i ]就是自身,所以對角線直接寫入對應值。

對於m[ i ][ j ],需要用s∈[i , j)進行遍歷,找到最大值和最小值。

def

min_max

(i, s, j, m, edge)

: a = m[i]

[s][0]

b = m[i]

[s][1]

c = m[s+1]

[j][0]

d = m[s+1]

[j][1]

if edge ==

'+':

return a+c, b+d

else

: e =

[a*c, a*d, b*c, b*d]

minf = e[0]

maxf = e[0]

for k in

range(1

,4):

if minf > e[k]

: minf = e[k]

if maxf < e[k]

: maxf = e[k]

return minf, maxf

defpoly_max

(n, m, edge)

:for r in

range(1

, n)

:for i in

range(0

, n - r)

: j = i + r

for s in

range

(i, j)

: minf, maxf = min_max(i, s, j, m, edge[s]

)if m[i]

[j][0]

> minf:

m[i]

[j][0]

= minf

if m[i]

[j][1]

< maxf:

m[i]

[j][1]

= maxf

return m[0]

[n-1][

1]if __name__ ==

'__main__'

: n =

int(

input

("一共有幾條邊:"))

edge =

vertex =

for i in

range(0

, n)

: v =

int(

input

("第"

+str

(i)+

"個點值為:"))

e =input

("第"

+str

(i)+

"個運算子為:"

) interrupt =

int(

input

("刪掉邊的序號:"))

new_vertex = vertex[interrupt+

1:n]

+ vertex[

0:interrupt+1]

new_edge = edge[interrupt+

1:n]

+ edge[

0:interrupt]

m =for i in

range(0

, n):[

])for j in

range(0

, n)

:if i == j:

m[i]

[new_vertex[i]

, new_vertex[i]])

else

: m[i][0

,0])

print

(poly_max(n, m, new_edge)

)print

(vertex)

print

(new_vertex)

print

(edge)

print

(new_edge)

for i in

range(0

, n)

:for j in

range(0

, n)

:print

(m[i]

[j][0]

, end=

'\t'

)print()

print()

for i in

range(0

, n)

:for j in

range(0

, n)

:print

(m[i]

[j][1]

, end=

'\t'

)print

()

動態規劃 多邊形遊戲

1 問題描述 給定n個頂點的多邊形,每個頂點標有乙個整數,每條邊上標有 加 或是 乘 號,並且n條邊按照順時針 依次編號為1 n。下圖給出了乙個n 4個頂點的多邊形。遊戲規則 1 首先,移走一條邊。2 然後進行下面的操作 選中一條邊e,該邊有兩個相鄰的頂點,不妨稱為v1和v2。對v1和v2頂點所標的...

多邊形遊戲(區間動態規劃)

就是乙個區間動態規劃,為了處理環狀結構,乙個好的想法是把整個頂點和邊的序列在後面再複製一遍。可以比較簡化 實現的複雜度。include using namespace std const int maxn 105 struct calseq bool operator const calseq l ...

動態規劃(DP)之多邊形遊戲問題

問題描述 多邊形遊戲是乙個單人玩的遊戲,開始時有乙個由n個頂點構成的多邊形。每個頂點被賦予乙個整數值,每條邊被賦予乙個運算子 或 所有邊依次用整數從1到n編號。遊戲第1步,將一條邊刪除。隨後n 1步按以下方式操作 1 選擇一條邊e以及由e連線著的2個頂點v1和v2 2 用乙個新的頂點取代邊e以及由e...