1、問題描述: 給定N個頂點的多邊形,每個頂點標有一個整數,每條邊上標有+(加)或是×(乘)號,並且N條邊按照順時針 依次編號為1~N。下圖給出了一個N=4個頂點的多邊形。 游戲規則 :(1) 首先,移走一條邊。 (2) 然後進行下面的操作: 選中一條邊E,該邊有兩個相鄰的頂點,不妨稱為V1和V2。對V1和V2頂點所標的整數按照E上所標運算符號(+或是×)進行運算,得到一個整數;用該整數標注一個新頂點,該頂點代替V1和V2 。 持續進行此操作,直到最後沒有邊存在,即只剩下一個頂點。該頂點的整數稱為此次游戲的得分(Score)。 2、問題分析: 解決該問題可用動態規劃中的最優子結構性質來解。 設所給的多邊形的頂點和邊的順時針序列為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)。www.2cto.com 設m[i,j,0]是鏈p(i,j)合並的最小值,而m[i,j,1]是最大值。若最優合並在op[i+s]處將p(i,j)分為兩個長度小於j的子鏈的最大值和最小值均已計算出。即: a=m[i,s,0] b=m[i,s,1] c=m[i,s,0] d=m[i,s,1] (1) 當op[i+s]=’+’時 m[i,j,0]=a+c ;m[i,j,1]=b+d (2) 當op[i+s]=’*’時 www.2cto.com m[i,j,0]=min{ac,ad,bc,bd} ; m[i,j,1]=max{ac,ad,bc,bd} 由於最優斷開位置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條邊後得到的最大得分。 算法具體代碼如下: [cpp] //3d6 多邊形游戲 #include "stdafx.h" #include <iostream> using namespace std; #define NMAX 100 int N,m[NMAX+1][NMAX+1][2],v[NMAX+1]; char op[NMAX+1]; void MinMax(int n,int i,int s,int j,int &minf,int &maxf); int PloyMax(int n,int& p); int main() { int p; cout<<"請輸入多邊形頂點數:"<<endl; cin>>N; for(int i=1; i<=N; i++) { cout<<"請輸入多邊形頂點"<<i<<"數值:"<<endl; cin>>v[i]; m[i][1][0]=v[i]; m[i][1][1]=v[i]; cout<<"請輸入多邊形邊"<<i<<"運算符:"<<endl; cin>>op[i]; } cout<<"多邊形游戲首次刪除第"<<p<<"條邊,結果為:"<<PloyMax(N,p)<<endl; return 0; } void MinMax(int n,int i,int s,int j,int &minf,int &maxf) { int e[5]; int a=m[i][s][0],b=m[i][s][1]; int r=(i+s-1)%n+1;//多邊形的實際頂點編號 int c=m[r][j-s][0],d=m[r][j-s][1]; if(op[r-1]=='+') { minf=a+c; maxf=b+d; } else { e[1]=a*c; e[2]=a*d; e[3]=b*c; e[4]=d*b; minf=e[1]; maxf=e[1]; for(int r=2;r<N;r++) { if(minf>e[r])minf=e[r]; if(maxf<e[r])maxf=e[r]; } } } int PloyMax(int n,int& p) { int minf,maxf; for(int j=2;j<=n;j++) //迭代鏈的長度 { for(int i=1;i<=n;i++)//迭代首次刪掉第i條邊 { for(int s=1 ;s<j;s++) //迭代斷開位置 { MinMax(n,i,s,j,minf,maxf); if(m[i][j][0]>minf) m[i][j][0]=minf; if(m[i][j][1]<maxf) m[i][j][1]=maxf; } } } int temp=m[1][n][1]; p=1; for(int i=2 ;i<=n; i++) { if(temp<m[i][n][1]) { temp=m[i][n][1]; p=i; } } return temp; } 程序運行結果如下: