1. 程式人生 > >動態規劃-多邊形遊戲問題

動態規劃-多邊形遊戲問題

1.描述:有一個由n個頂點構成的多邊形。每個頂點被賦予一個整數值,每條邊被賦予一個運算子“+”或“*”。所有邊依次用整數從1到n編號。
這裡寫圖片描述

遊戲第1步,將一條邊刪除。
隨後n-1步按以下方式操作:
(1)選擇一條邊E以及由E連線著的2個頂點V1和V2;
(2)用一個新的頂點取代邊E以及由E連線著的2個頂點V1和V2。將由頂點V1和V2的整數值通過邊E上的運算得到的結果賦予新頂點。
最後,所有邊都被刪除,遊戲結束。遊戲的得分就是所剩頂點上的整數值。

輸入:
輸入共兩行,第一行一個整數n表示頂點個數,第二行共2*n個數,分別為數字和字元。

例如:對於上圖中的問題,我們可以這樣按輸入樣例中的例子輸入,數學中的“+”號代表加法,小寫字母“x”代表乘法。

輸出:
一個整數,計算最高得分。

輸入樣例:
5
10 + -1 x -2 x 3 + -8 x

輸出樣例:
486

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]。

設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]=’*’時,有min{ac,ad,bc,bd}≤m≤max{ac,ad,bc,bd}
  
換句話說,主鏈的最大值和最小值可由子鏈的最大值和最小值得到。例如,當m=ac時,最大主鏈由它的兩條最小主鏈組成;同理當m=bd時,最大主鏈由它的兩條最大子鏈組成。無論哪種情形發生,由主鏈的最優性均可推出子鏈的最優性。
綜上可知多邊形遊戲問題滿足最優子結構的性質。

3.遞迴求解

由前面的分析可知,為了求鏈合併的最大值,必須同時求子鏈合併的最大值和最小值。因此,在整個計算過程中,應同時計算最大值和最小值。

設m[i,j,0]是鏈p(i,j)合併的最小值,而m[i,j,1]是最大值。若最優合併在op[i+s]處將p(i,j)分為兩個長度小於j的子鏈p(i,i+s)和p(i+s,j-s),且從頂點i開始的長度小於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{ac,ad,bc,bd}

                    m[i,j,1]=max{ac,ad,bc,bd}

綜合(1)和(2),將p(i,j)在op[i+s]處斷開的最大值記為maxf(i,j,s),最小值記為minf(i,j,s),則

                                           a+c                               op[i+s]='+'

                    minf(i,j,s)={                                         

                                           min{ac,ad,bc,bd}           op[i+s]='*'

                                            b+d                                op[i+s]='+'     

                   maxf(i,j,s)={                                               

                                            max{ac,ad,bc,bd}          op[i+s]='*'

     由於多邊最優斷開位置s有1≤s≤j-1的j-1種情況,由此可知

                        m[i,j,0]=min{minf(i,j,s)}                  1≤i,j≤n  

                         m[i,j,1]=max{maxf(i,j,s)}                  1≤i,j≤n   

     初始邊界顯然為

                          m[i,j,0]=v[i]                  1≤i≤n

                           m[i,j,1]=v[i]                  1≤ i≤n

由於多邊形是封閉的,在上面的計算中,當i+s>n是,頂點i+s實際編號為(i+s)mod n。按上述遞推式計算出的m[i,n,1]即為首次刪去第i條邊後得到的最大得分。

4.演算法描述

基於以上討論可設計解多邊形遊戲問題的動態規劃演算法如下:

       void minMax(int i,int s,int j)
       {          int e[5];

       int a=m[i][s][0],

           b=m[i][s][1],

           r=(i+s-1)%n+1,//妙!

           c=m[r][j-s][0],

           d=m[r][j-s][1];

       if(op[r]=='t')

         {minf=a+c;

          maxf=b+d;

         }

       else

       {

           e[1]=a*c;

           e[2]=a*d;

           e[3]=b*c;

           e[4]=b*d;

           minf=e[1];

           maxf=e[1];

           for(int k=2;k<5 kh>

             {if(minf>e[k]) minf=e[k];

              if(maxf

             }

       }

}

int polyMax(){
for(int j=2;j<=n;j++)

  for(int i=1;i<=n;i++)

    for(int s=1;s

      {minMax(i,s,j);

       m[i][j][0]=100000;

       m[i][j][1]=-100000;

       if(m[i][j][0]>minf) m[i][j][0]=minf;

       if(m[i][j][1]

      }

long int temp=m[1][n][1];

for(int i=2;i<=n;i++)

  if(temp

return temp;

}

【新方法】

本題在處理順時針迴圈時的下標時,有一個很妙的方法。即,

                        r=(i+s-1)%n+1

其實,本題從這樣編純屬巧合。

當i+s 並不需要減一的時候,用這種方法編就很方便。

如果用傳統的方法就是

            if(i==n)       r=n;

             else r=i%n

這樣,以來r=(i+s-1)%n+1就簡單了不少。

【參考程式】



#include

#include

long int minf,maxf,m[51][51][2];

char op[52];

int v[51],n;

void in()

{

     FILE *in=fopen("polygon2.in","r");

     fscanf(in,"%d",&n);

     fgetc(in);

     for(int i=1;i<=n;i++)

       fscanf(in,"%c %d ",&op[i],&v[i]);

     fclose(in);

}    

void iniM()

{

     for(int i=1;i<=n;i++)

       {m[i][1][0]=v[i];

        m[i][1][1]=v[i];

       }

}

void minMax(int i,int s,int j)

{

           int e[5];

           int a=m[i][s][0],

               b=m[i][s][1],

               r=(i+s-1)%n+1,//妙!

               c=m[r][j-s][0],

               d=m[r][j-s][1];

           if(op[r]=='t')

             {minf=a+c;

              maxf=b+d;

             }

           else

           {

               e[1]=a*c;

               e[2]=a*d;

               e[3]=b*c;

               e[4]=b*d;

               minf=e[1];

               maxf=e[1];

               for(int k=2;k<5 kh>

                 {if(minf>e[k]) minf=e[k];

                  if(maxf

                 }

           }

}                                     

int polyMax()

{

    for(int j=2;j<=n;j++)

      for(int i=1;i<=n;i++)

        for(int s=1;s

          {minMax(i,s,j);

           m[i][j][0]=100000;

           m[i][j][1]=-100000;

           if(m[i][j][0]>minf) m[i][j][0]=minf;

           if(m[i][j][1]

          }

    long int temp=m[1][n][1];

    for(int i=2;i<=n;i++)

      if(temp

    return temp;

}

int main()

{

    in();

    iniM();

    long int max=polyMax();

    printf("%ld\n",max);

    system("pause");

    return 0;

}  

相關推薦

動態規劃-多邊形遊戲問題

1.描述:有一個由n個頂點構成的多邊形。每個頂點被賦予一個整數值,每條邊被賦予一個運算子“+”或“*”。所有邊依次用整數從1到n編號。 遊戲第1步,將一條邊刪除。 隨後n-1步按以下方式操作: (1)選擇一條邊E以及由E連線著的2個頂點V1和V2;

a simple stone game--k倍動態規劃減法遊戲

要求b[j],表示a[0]……a[i]組成,那麼顯然是要用到a[i]的,不然不就成了b[i-1],既然用了a[i],但是又要使相鄰的倍數在K以上。則找到最大的j,使a[j]*k<a[i]那麼滿足條件,便是a[0]……a[j]能組成的最大的數,加上a[i],那麼後者表示當前項不能和之前項組合,那麼最大的數

bzoj 3875 騎士遊戲 - spfa - 動態規劃

全部 用法 += add 生活 win32 text als auto Description 【故事背景】 長期的宅男生活中,JYY又挖掘出了一款RPG遊戲。在這個遊戲中JYY會 扮演一個英勇的騎士,用他手中的長劍去殺死入侵村莊的怪獸。 【問題描述】

跳一跳遊戲。《動態規劃

ann 遞歸 follow ont BE als num width maximum 動態規劃的題型中要抽象出遞歸相類似的表達式。動態規劃,給我的感覺就是一個存表和查表操作,而且這兩個操作在物理和邏輯上是連續的。 Nowadays, a kind of chess ga

【BZOJ3991】尋寶遊戲動態規劃

維護 inline printf insert struct print clu getch map 【BZOJ3991】尋寶遊戲(動態規劃) 題面 BZOJ 題解 很明顯,從任意一個有寶藏的點開始,每次走到相鄰的\(dfs\)的節點就行了。 證明? 類似把一棵樹上的關鍵點

[leetcode] 45. 跳躍遊戲 II(Java)(動態規劃)

com max https 重疊 http findmi 條件 leetcode scrip 45. 跳躍遊戲 II 動態規劃 此題可以倒著想。 看示例: [2,3,1,1,4] 我們從後往前推,對於第4個數1,跳一次 對於第3個數1,顯然只能跳到第4個數上,那麽從第3個數

BZOJ3875 AHOI2014/JSOI2014騎士遊戲動態規劃

老師 con ack 有意思 mes cstring cto -s bzoj3875   容易想到設f[i]為殺死i號怪物所消耗的最小體力值,由後繼節點更新。然而這顯然是有後效性的,正常的dp沒法做。   雖然spfa已經死了,但確實還是挺有意思的。只需要用spfa來更新d

多邊形最優三角剖分(演算法設計:動態規劃

一、動態規劃       和分治法類似,把原問題劃分成若干個子問題,不同的是,分治法(子問題間互相獨立),動態規劃(子問題不獨立)       動態規劃: (1)找出最優解的性質,刻畫其結構特徵 (2)遞迴地定義最優值

The King’s Ups and Downs(HDU 4489,動態規劃遞推,組合數,國王的遊戲)

        題意: 給一個數字n,讓1到n的所有數都以波浪形排序,即任意兩個相鄰的數都是一高一低或者一低一高 比如:1324   4231,再比如4213就是錯的,因為4高,2低,接下來1就應該比2高,但是它沒有 點選開啟題目連結 接下來思

計蒜客oj 跳躍遊戲 動態規劃 dfs

計蒜客oj 跳躍遊戲 給定一個非負整數陣列,假定你的初始位置為陣列第一個下標。 陣列中的每個元素代表你在那個位置能夠跳躍的最大長度。 請確認你是否能夠跳躍到陣列的最後一個下標。 例如: A = [2,3,1,1,4], return true. A = [3,2,1,0,4]

BZOJ4881 線段遊戲(二分圖+樹狀陣列/動態規劃+線段樹)

  相當於將線段劃分成兩個集合使集合內線段不相交,並且可以發現線段相交等價於逆序對。也即要將原序列劃分成兩個單增序列。由dilworth定理,如果存在長度>=3的單減子序列,無解,可以先判掉。   這個時候有兩種顯然的暴力。   將點集劃分成兩部分使內部無邊顯然就是二分圖,於是第一種暴力是在逆序對之

自殺遊戲【牛客小白月賽7 B】【DP動態規劃】【詳解、對於WA細節上的分析】

題目連結   思路: 細節的處理尤為重要,後面會提點一下。 這道題,我的想法是從0這個必死局開始往後找最優解下Alice或者Bob的生死,初始化dp[]是全Bob活,也就是Alice死,dp【i】是指以最優解往下走,到達i時刻死的人到底會是誰,然後從1號節點開始遍歷,由

帶延遲的動態規劃--51nod1327棋盤遊戲

傳送門 看到資料範圍就覺得這一定是一個n2∗mn^2*mn2∗m或者n∗m2n*m^2n∗m2的dpqwqdp\ qwqdpqwq 果然是這樣,因為每一列都是填一個或者不填,所以一定是按列dpdpdp

【習題詳解】動態規劃DP:硬幣遊戲 蛋糕

動態規劃DP硬幣蛋糕塔 硬幣 題目描述 農夫約翰的奶牛喜歡玩硬幣遊戲,因此他發明了一種稱為“Xoinc”的兩人硬幣遊戲。 初始時,一個有N(5 <= N <= 2,000)枚硬幣的堆疊放在地

動態規劃之凸多邊形最優三角剖分”

 問題描述 多邊形是平面上一條分段線性的閉曲線。也就是說,多邊形是由一系列首尾相接的直線段組成的。組成多邊形的各直線段稱為該多邊形的邊。多邊形相接兩條邊的連線點稱為多邊形的頂點。若多邊形的邊之間除了連線頂點外沒有別的公共點,則稱該多邊形為簡單多邊形。一個簡單多邊形將平面分為3個部分:被包圍

sincerit 跳躍遊戲二(動態規劃問題)

給定一個非負整數陣列,假定你的初始位置為陣列第一個下標。 陣列中的每個元素代表你在那個位置能夠跳躍的最大長度。 你的目標是到達最後一個下標,並且使用最少的跳躍次數。 例如: A = [2,3,1,1,4]A=[2,3,1,1,4],到達最後一個下標的最少跳躍次數為 22。(先跳躍 11 步,

NOIp2008傳球遊戲(普及組T3)————動態規劃

題解:本題主要考查動態規劃。因為球只能左右傳,所以i同學只能來自於的左邊一個同學(i-1)和右邊一個同學(i+1)。傳j次球的方案數就是j-1次傳到左邊和右邊的方案數之和。 f[i][k]=f[i-1][k-1]+f[i+1][k-1],(i=1或n時,需單獨處理)。 程式碼如下: #i

動態規劃】【tyvj】乘法遊戲

用記憶化搜尋出現點小問題。以後還是改用for了。 #include <stdio.h> #define MAXINT 1000000 #define maxn 110 int f[maxn][maxn]; int a[maxn]; int n; int main

SOJ2113: 數字遊戲題解動態規劃DP

2113: 數字遊戲 Description 【問題描述】 丁丁最近沉迷於一個數字遊戲之中。這個遊戲看似簡單,但丁丁在研究了許多天之後卻發覺原來在簡單的規則下想要贏得這個遊戲並不那麼容易。遊戲是這樣的,在你面前有一圈整數(一共n個),你要按順序將其分為m個部分,各部分內的

Vijos P1218 數字遊戲動態規劃,環形DP)

丁丁最近沉迷於一個數字遊戲之中。這個遊戲看似簡單,但丁丁在研究了許多天之後卻發覺原來在簡單的規則下想要贏得這個遊戲並不那麼容易。遊戲是這樣的,在你面前有一圈整數(一共n個),你要按順序將其分為m個部分,各部分內的數字相加,相加所得的m個結果對10取模後再相乘,最終得到一個數k。遊戲的要求是使你所得的k最大或