程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 0015算法筆記——多邊形游戲問題

0015算法筆記——多邊形游戲問題

編輯:C++入門知識

         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;   }         程序運行結果如下:

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved