1. 程式人生 > >決策單調性&四邊形不等式

決策單調性&四邊形不等式

#include<bits/stdc++.h>
#define MAXN 10000+10
using namespace std;
int dp[MAXN][MAXN],s[MAXN][MAXN],cnt[MAXN];
int main(){
    int n;scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&cnt[i]),cnt[i]=cnt[i-1]+cnt[i];
    for(int i=1;i<=n;i++)
        dp[i][i]=0,s[i][i]=i;
    for(int i=n;i>=1;i--){
        for(int j=i+1;j<=n;j++){
            int temp=0x7fffffff;
            int te;
            for(int k=s[i][j-1];k<=s[i+1][j];k++){
                if(temp>dp[i][k]+dp[k+1][j]+cnt[j]-cnt[i-1]){
                    temp=dp[i][k]+dp[k+1][j]+cnt[j]-cnt[i-1];
                    te=k;
                }
            }
            dp[i][j]=temp;
            s[i][j]=te;
        }
    }
    cout<<dp[1][n]<<endl;
}

題目:
n 堆石子。現要將石子有次序地合併成一堆,規定每次只能選相鄰的2 堆石子合併成新的一堆,並將新的一堆石子數記為該次合併得分。設計一個演算法,計算出將n堆石子合併成一堆的最小得分和最大得分

演算法:(注:程式碼石子首尾不連線)
設dp(i,j)定義為第i堆石子到第j堆石子合併後的最少總分數,想到這樣dp轉移 
dp[i][j]=min{dp[i][k]+dp[k+1][j]}+cost[i][j] 
cost[i][j]表示把第i堆到第j堆的石子和到一起的最後一步的代價,顯然之前無論怎麼合併,最後一步的代價都是一樣的,所以我們可以先預處理出這個cost陣列,他等於cnt[j]-cnt[i-1],其中cnt陣列是字首和,然後用四邊形不等式優化

合併石子問題

現在有n堆石子,要將石子按一定順序地合成一堆,規定如下,每次只能移動相鄰的兩堆石子,合併費用為新和成一堆石子的數量,求把n堆石子全部合併到一起所花的最少或者最大花費

很容易想到這樣一個dp轉移 
dp[i][j]=min{dp[i][k]+dp[k+1][j]}+cost[i][j] 
震驚!這不就是之前所講的模型嘛?原來之前O(n^3)方的合併石子問題還可以優化(我太弱了) 
首先明確一點,cost[i][j]表示把第i堆到第j堆的石子和到一起的最後一步的代價,顯然,之前無論怎麼合併,最後一步的代價都是一樣的,所以我們可以先預處理出這個cost陣列,他等於cnt[j]-cnt[i-1],其中cnt陣列是字首和 
for一遍i,for一遍j,每算一次dp[i][j]還要for一遍k,自然是O(n^3)方,現在我們來按照規則判斷是否可以用四邊形優化

第一步(壹)證明cost為凸

對於所有的i,j,令其滿足i< i+1<=j< j+1 
我們需要證明 
cost[i][j]+cost[i+1][j+1]<=cost[i+1][j]+cost[i][j+1] 
移項 
cost[i][j]-cost[i+1][j]<=cost[i][j+1]-cost[i+1][j+1] 
令f(j)=cost[i][j]-cost[i+1][j] 
f(j)=cnt[j]-cnt[i-1]-(cnt[j]-cnt[i]) 
f(j)=cnt[i]-cnt[i-1] 
都跟j無關了,自然一定滿足四邊形不等式(這個時候是直接等於了,但沒有違反四邊形不等式)

第二步(貳)證明dp為凸

要推導dp[i][j]的凸性,自然要滿足對任意的i,j,令i< i+1<=j< j+1 
有如下結論 
dp[i][j]+dp[i+1][j+1]<=dp[i+1][j]+dp[i][j+1] 
令dp[i+1][j]取得最優值的時候k=x 
令dp[i][j+1]取得最優值的時候k=y 
令x < =y(之後還要令x > y,這裡不再贅述,讀者如有興趣可以自行推導,方式相似) 
將k=x代入dp[i][j],k=y代入dp[i+1][j+1] 
左式=dp[i][x]+dp[x+1][j]+cost[i][j]+dp[i+1][y]+dp[y+1][j+1]+cost[i+1][j+1]① 
而對於i< i+1<=j< j+1 
由於已經在壹中證明了cost的凸性,所以 
cost[i][j]+cost[i+1][j+1]<=cost[i+1][j]+cost[i][j+1]② 
我們會發現這個不等式的左邊在①式中出現過,所以把②式中的左式和右式替換一下可以得到如下結論 
dp[i][x]+dp[x+1][j]+cost[i][j]+dp[i+1][y]+dp[y+1][j+1]+cost[i+1][j+1] 
<=

dp[i][x]+dp[x+1][j+1]+cost[i][j+1]+dp[i+1][y]+dp[y+1][j]+cost[i+1][j]

即dp[i][j]+dp[i+1][j+1]<=dp[i][j+1]+dp[i+1][j] 
證畢

第三步(叄)證明決策單調

現在我們已經證明了cost陣列和dp陣列的凸性,要證明決策單調以證明優化的正確性 
即要證明s[i][j-1]<=s[i][j]<=s[i+1][j] 
對於s[i][j-1]<=s[i][j] 
令dp[i][j-1]取得最小值時的k=y,對於所有x≠y,令x<=y 
可以有如下推導 
∵x+1<=y+1<=j-1< j 
四邊形不等式有: 
dp[x+1][j-1]+dp[y+1][j]<=dp[y+1][j-1]+dp[x+1][j]

在式子兩邊同時加上dp[i][x]+cost[i][j-1]+dp[i][y]+cost[i][j] 可以得到

dp[i][x]+dp[x+1][j-1]+cost[i][j-1]+dp[i][y]+dp[y+1][j]+cost[i][j] 
<= 
dp[i][x]+dp[x+1][j]+cost[i][j]+dp[i][y]+dp[y+1][j-1]+cost[i][j-1]

dp[i][j-1]+dp[i][j]<=dp[i][j]+dp[i][j-1] 
(k=x)…………(k=y)……(k=x)……(k=y) 
移項

dp[i][j-1]-dp[i][j-1]<=dp[i][j]-dp[i][j] 
(k=x)…………(k=y)……(k=x)……(k=y)

由於我們是令k=y時dp[i][j-1]取得最小值,那麼dp[i][j-1] (k=x)一定大於等於dp[i][j-1] (k=y),所以左式大於零,所以右式也大於零,所以對於dp[i][j-1]可以取到最優值的y,所有小於它的值,對於dp[i][j]來說,都沒有y優,所以最優決策一定不是小於y的,如果令s[i][j]表示dp[i][j]取得最優值的時候的k值,那麼一定有 
s[i][j-1]<=s[i][j] 
證畢