[转]四边形不等式优化dp(POJ1160)
四邊形不等式優化動態規劃原理:
1.當決策代價函數w[i][j]滿足w[i][j]+w[i’][j’]<=w[I;][j]+w[i][j’](i<=i’<=j<=j’)時,稱w滿足四邊形不等式.當函數w[i][j]滿足w[i’][j]<=w[i][j’] i<=i’<=j<=j’)時,稱w關于區間包含關系單調.
2.如果狀態轉移方程m為且決策代價w滿足四邊形不等式的單調函數(可以推導出m亦為滿足四邊形不等式的單調函數),則可利用四邊形不等式推出最優決策s的單調函數性,從而減少每個狀態的狀態數,將算法的時間復雜度由原來的O(n^3)降低為O(n^2).方法是通過記錄子區間的最優決策來減少當前的決策量.令:
s[i][j]=max{k | ma[i][j] = m[i][k-1] + m[k][j] + w[i][j]}
由于決策s具有單調性,因此狀態轉移方程可修改為:
?
證明過程: (轉載)
設m[i,j]表示動態規劃的狀態量。
m[i,j]有類似如下的狀態轉移方程:
m[i,j]=opt{m[i,k]+m[k,j]}(i≤k≤j)
如果對于任意的a≤b≤c≤d,有m[a,c]+m[b,d]≤m[a,d]+m[b,c],那么m[i,j]滿足四邊形不等式。
以上是適用這種優化方法的必要條件
對于一道具體的題目,我們首先要證明它滿足這個條件,一般來說用數學歸納法證明,根據題目的不同而不同。
通常的動態規劃的復雜度是O(n3),我們可以優化到O(n2)
設s[i,j]為m[i,j]的決策量,即m[i,j]=m[i,s[i,j]]+m[s[i,j]+j]
我們可以證明,s[i,j-1]≤s[i,j]≤s[i+1,j]??(證明過程見下)
那么改變狀態轉移方程為:
m[i,j]=opt{m[i,k]+m[k,j]}??????(s[i,j-1]≤k≤s[i+1,j])
復雜度分析:不難看出,復雜度決定于s的值,以求m[i,i+L]為例,
(s[2,L+1]-s[1,L])+(s[3,L+2]-s[2,L+1])…+(s[n-L+1,n]-s[n-L,n-1])=s[n-L+1,n]-s[1,L]≤n
所以總復雜度是O(n2)
對s[i,j-1]≤s[i,j]≤s[i+1,j]的證明:
設mk[i,j]=m[i,k]+m[k,j],s[i,j]=d
對于任意k<d,有mk[i,j]≥md[i,j](這里以m[i,j]=min{m[i,k]+m[k,j]}為例,max的類似),接下來只要證明mk[i+1,j]≥md[i+1,j],那么只有當s[i+1,j]≥s[i,j]時才有可能有ms[i+1,j][i+1,j]≤md[i+1,j]
(mk[i+1,j]-md[i+1,j])?-?(mk[i,j]-md[i,j])
=(mk[i+1,j]+md[i,j])?-?(md[i+1,j]+mk[i,j])
=(m[i+1,k]+m[k,j]+m[i,d]+m[d,j])?-?(m[i+1,d]+m[d,j]+m[i,k]+m[k,j])
=(m[i+1,k]+m[i,d])?-?(m[i+1,d]+m[i,k])
∵m滿足四邊形不等式,∴對于i<i+1≤k<d有m[i+1,k]+m[i,d]≥m[i+1,d]+m[i,k]
∴(mk[i+1,j]-md[i+1,j])≥(mk[i,j]-md[i,j])≥0
∴s[i,j]≤s[i+1,j],同理可證s[i,j-1]≤s[i,j]
證畢
擴展:
以上所給出的狀態轉移方程只是一種比較一般的,其實,很多狀態轉移方程都滿足四邊形不等式優化的條件。
解決這類問題的大概步驟是:
0.證明w滿足四邊形不等式,這里w是m的附屬量,形如m[i,j]=opt{m[i,k]+m[k,j]+w[i,j]},此時大多要先證明w滿足條件才能進一步證明m滿足條件
1.證明m滿足四邊形不等式
2.證明s[i,j-1]≤s[i,j]≤s[i+1,j]
pku 1160 Post Office?解題報告
題意:?給出m個村莊及其距離,給出n個郵局,要求怎么建n個郵局使代價最小.
算法:很顯然用到動態規劃,那么假設:
d[i…n],各郵局的坐標
w[i][j]表示在d[i][j]之間建立一個郵局的村莊為k,則k為i與j之和的一半(很顯然在中間建一個郵局距離最小),那么
m[i][j]為在前j個村莊建立i個郵局的最小距離和.
那么狀態轉移方程為:
邊界條件: m[1][j]=w[1][j]??(1<=j<=m)
狀態轉移方程:?
那么思路則為:
for i=2 to p do??????//遞推郵局數
{
?????//m:在前j個村莊建立i個郵局的最小距離和
?????for j=n dwonto i+1 do????//按遞減順序枚舉尾指針
?????m[i][j]=inf;
?????for k=1 to n do
?????{
??????????temp = m[i-1][k]+calcw(k+1,j);
??????????if(temp<m[i][j]) m[i][j]=temp;
?????}
}
這樣時間復雜度顯然為O(n^3),這是不能接受的.?
仔細分析這dp算法,關鍵是決策變量k枚舉數太多,?聯系到四邊形不等式原理,w[i][j]與m[i][j]很明顯符合四邊形不等式,我們假設決策變量s[i][j],如果在1到10的村莊中,建立1個郵局的最佳位置為8,那么在決定見多一個郵局的話,當然是在1到8之間了(根據四邊形不等式原理猜想到),所以就在dp的過程中,用s[i][j]記錄前i-1個郵局的村莊數.?那么我們第三次搜索的時候,就需要根據決策表s[i-1][j]<=k<=s[i][j+1]的范圍內枚舉.而可以證明s[i][j]具有單調性,那么我們就可以利用s[i][j]單調性限制了上下界然后把?O(n^3)弄成了?O(n^2)。?
以sample為例:
狀態方程m:
?
決策表s:
?那么狀態轉移方程為:
邊界條件: m[1][j]=w[1][j]??(1<=j<=m)
邊界條件: m[1][j]=w[1][j]??(1<=j<=m)
狀態轉移方程:?
決策記錄表: s[i][j]=k
?
代碼:
View Code //#pragma comment(linker,"/STACK:327680000,327680000") #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue>#define CL(arr, val) memset(arr, val, sizeof(arr)) #define REP(i, n) for((i) = 0; (i) < (n); ++(i)) #define FOR(i, l, h) for((i) = (l); (i) <= (h); ++(i)) #define FORD(i, h, l) for((i) = (h); (i) >= (l); --(i)) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define Read() freopen("data.in", "r", stdin) #define Write() freopen("data.out", "w", stdout);typedef long long LL; const double eps = 1e-8; const double PI = acos(-1.0); const int inf = ~0u>>2;using namespace std;const int N = 310; const int M = 33;int dp[N][N]; int s[N][N]; int d[N]; int sum[N][N];int dis(int i, int j) {if(i >= j) return 0;if(sum[i][j] != 0) return sum[i][j];int a = i, b = j;while(a < b) {sum[i][j] += (d[b--] - d[a++]);}return sum[i][j]; }int main() {//Read();int i, j, k, V, P, tmp;while(~scanf("%d%d", &V, &P)) {for(i = 1; i <= V; ++i) {scanf("%d", d + i);}CL(sum, 0);CL(dp, 0);for(i = 1; i <= V; ++i) {dp[1][i] = dis(1, i);s[i][i] = i-1;}for(i = 2; i <= P; ++i) {s[i][V+1] = V-1;for(j = V; j >= i; --j) {dp[i][j] = inf;for(k = s[i-1][j]; k <= s[i][j+1]; ++k) {tmp = dp[i-1][k] + dis(k + 1, j);if(tmp < dp[i][j]) {dp[i][j] = tmp;s[i][j] = k;}}}}printf("%d\n", dp[P][V]);}return 0; }?
?
?
?
?
?
?
轉載于:https://www.cnblogs.com/vongang/archive/2013/01/21/2869315.html
總結
以上是生活随笔為你收集整理的[转]四边形不等式优化dp(POJ1160)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于asp.net利用mono部署到Li
- 下一篇: How to: Build a Clie