問題描述:
多邊形遊戲是乙個單人玩的遊戲,開始時有乙個由n個頂點構成的多邊形。每個頂點被賦予乙個整數值,每條邊被賦予乙個運算子「+」或「*」。所有邊依次用整數從1到n編號。
遊戲第1步,將一條邊刪除。
隨後n-1步按以下方式操作:
(1)選擇一條邊e以及由e連線著的2個頂點v1和v2;
(2)用乙個新的頂點取代邊e以及由e連線著的2個頂點v1和v2。將由頂點v1和v2的整數值通過邊e上的運算得到的結果賦予新頂點。
最後,所有邊都被刪除,遊戲結束。遊戲的得分就是所剩頂點上的整數值。
問題:對於給定的多邊形,計算最高得分。
如下圖:
資料輸入:
第一行是乙個整數n
第二行按照
邊 頂點 邊 頂點 …. 邊 頂點
的順序以此存放了n個頂點和n條邊的標註資訊。
問題求解:
當把一條邊去除除后,再把它拉直,那麼這個問題就可以變成一條鏈。那麼就和以前寫的矩陣連乘有幾分的相似,其實我們最後要求的是這個鏈的表示式算式結果的最大值。於是我們就可以想到可以用陣列p[i][j]來表示從點i開始,鏈長為j的算術表示式的最大值,用v[i]儲存運算元,op[i]儲存操作符。如果這條鏈的最後一次合併運算在op[i+s]處發生(1≤s≤j-1),則可在op[i+s]處將鏈分割為2個子鏈p[i][s]和p[i+s][j-s]。似乎這樣再按照以前解決動態規劃題目時的思路,就可以解決問題了。 但是,我們再來考慮一下,由於有兩種運算子+和x,並且運算元可能存在負數,那麼我們也必須考慮兩個負數相乘的結果可能比兩個正數要打,所以我們同時還需要記錄每個鏈的最大和最小值,然後判斷,如果操作符為+的話,只需要兩個鏈的最大值相加即可,如果操作符是x的話,那麼必須把各種情況考慮進來,然後再求出最大值。分析如下:
設m1是對子鏈p[i][s]的任意一種合併方式得到的值,而a和b分別是在所有可能的合併中得到的最小值和最大值。m2是p[i+s][j-s]的任意一種合併方式得到的值,而c和d分別是在所有可能的合併中得到的最小值和最大值。依此定義有a≤m1≤b,c≤m2≤d
(1)當op[i+s]='+'時,顯然有a+c≤m≤b+d
(2)當op[i+s]='*'時,由於v[i]可取負整數,子鏈的最大值相乘未必能得到主鏈的最大值,但是注意到最大值一定在邊界點取到,有min≤m≤max
換句話說,主鏈的最大值和最小值可由子鏈的最大值和最小值得到。例如,當m=ac時,最大主鏈由它的兩條最小子鏈組成;同理當m=bd時,最大主鏈由它的兩條最大子鏈組成
解決該問題可用動態規劃中的最優子結構性質來解。
設所給的多邊形的頂點和邊的順時針序列為op[1],v[1],op[2],v[2],op[3],…,op[n],v[n] 其中,op[i]表示第i條邊所對應的運算子,v[i]表示第i個頂點上的數值,i=1~n。
在所給的多邊形中,從頂點i(1<=i<=n)開始,長度為j(鏈中有j個頂點)的順時針鏈p(i,j)可表示為v[i],op[i+1],…,v[i+j-1],如果這條鏈的最後一次合併運算在op[i+s]處發生(1<=s<=j-1),則可在op[i+s]處將鏈分割為兩個子鏈p(i,s)和p(i+s,j-s)。
設m[i,j,0]是鏈p(i,j)合併的最小值,而m[i,j,1]是最大值。若最優合併在op[i+s]處將p(i,j)分為兩個長度小於j的子鏈的最大值和最小值均已計算出。即:
a=m[i,i+s,0] b=m[i,i+s,1] c=m[i+s,j-s,0] d=m[i+s,j-s,1]
(1) 當op[i+s]=』+』時
m[i,j,0]=a+c ;m[i,j,1]=b+d
(2) 當op[i+s]=』*』時
m[i,j,0]=min ; m[i,j,1]=max
綜合(1)和(2),將p(i,j)在op[i+s]處斷開的最大值記為maxf(i,j,s)最小值記為minf(i,j,s),則
由於最優斷開位置s有1<=s<=j-1的j-1中情況。 初始邊界值為 m[i,1,0]=v[i] 1<=i<=n m[i,1,1]=v[i] 1<=i<=n
因為多變形式封閉的,在上面的計算中,當i+s>n時,頂點i+s實際編號為(i+s)modn。按上述遞推式計算出的m[i,n,1]記為遊戲首次刪除第i條邊後得到的最大得分。
**實現:
#include#include結果輸出:int v[101
];int
n;char op[101
];int
minf,maxf;
int m[101][101][2
];void minmax(int i,int s,int
j)
else
}}int
main()
for(int j=2; j<=n; j++)//
鏈的長度
for(int i=1; i<=n; i++)//
刪掉第i條邊
for(int s=1; s//
斷開的位置
int temp=m[1][n][1
];
for(int i=2; i<=n; i++)
printf(
"%d\n
",temp);
return0;
}
(由程式輸出可見初始時刪除的邊為序號1)
動態規劃 多邊形遊戲
已知乙個n邊的多邊形,在n個頂點上都有乙個整數,在n條邊上都存在 或 號。遊戲開始時,撤掉一條邊。剩下的就會變成由n個頂點,n 1條邊所組成的鏈條。將其中兩個相鄰的頂點按之間的運算子進行運算,這兩個頂點和這條邊被替換為運算結果,鏈條被削減為n 1個頂點,n 2條邊。如此反覆直到最後只剩下乙個點。多邊...
動態規劃 多邊形遊戲
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 ...