決策單調性&四邊形不等式
#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]
證畢