已知乙個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...