首页 > 代码库 > hdu 3506 Monkey Party 区间dp + 四边形不等式优化

hdu 3506 Monkey Party 区间dp + 四边形不等式优化

http://acm.hdu.edu.cn/showproblem.php?pid=3506

 

四边行不等式:http://baike.baidu.com/link?url=lHOFq_58V-Qpz_nTDz7pP9xCeHnd062vNwVT830z4_aQoZxsCcRtac6CLzbPYLNImi5QAjF2k9ydjqdFf7wlh29GJffeyG8rUh-Y1c3xWRi0AKFNKSrtj3ZY7mtdp9n5W7M6BBjoINA-DdplWWEPSK#1

 

dp[i][j]表示第i--j堆合并成一堆的时候,所需的最小花费。

然后根据以前的,dp[i][j] = dp[i][k] + dp[k + 1][j] + cost

那么我就要去找那个位置k。

能够证明的就是,cost满足四边形不等式。

我们设w[i][j]表示第i--j个数的和。

引用一下:

 技术分享当函数w(i,j)满足 w(a,c)+w(b,d) <= w(b,c)+w(a,d) 且a<=b< c <=d 时,我们称w(i,j)满足四边形不等式。。
 
关于这个,其实是绝对相等的,不是大于。
证明如下。设sum[i]表示1--i的和
那么上面的不等式变成:
左边:sum[c] - sum[a - 1] + sum[d] - sum[b - 1] 
右边:sum[d] - sum[a - 1] + sum[c] - sum[b - 1];
是相等的。所以满足条件
 
当函数w(i, j)满足w(i‘, j) <= w(i, j‘); i <= i‘ < j <= j‘ 时,称w关于关于区间包含关系单调。
这个很容易,画个图,很明显
 
于是有以下三个定理 

定理一: 如果w同时满足四边形不等式 和 决策单调性 ,则d也满足四边形不等式
定理二:当定理一的条件满足时,让d[i,j]取最小值的k为K[i,j],则K[i,j-1]<=K[i,j]<=K[i+1,j] 
定理三:w为凸当且仅当w[i,j]+w[i+1,j+1]<=w[i+1,j]+w[i,j+1] 

由定理三知 判断w是否为凸即判断 w[i,j+1]-w[i,j]的值随着i的增加是否递减 
于是求K值的时候K[i,j]只和K[i+1,j] 和 K[i,j-1]有关,所以 可以以i-j递增为顺序递推各个状态值最终求得结果  将O(n^3)转为O(n^2) 
 
 
 
技术分享
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;


#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
int n;
const int maxn = 2e3 + 20;
int dp[maxn][maxn];
int s[maxn][maxn];
int sum[maxn];
int a[maxn];
void work() {
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
        a[i + n] = a[i];
    }
    n *= 2;
    for (int i = 1; i <= n; ++i) {
        dp[i][i] = 0;
        s[i][i] = i;
        sum[i] = sum[i - 1] + a[i];
    }
    for (int dis = 1; dis <= n - 1; ++dis) {
        for (int be = 1; be + dis <= n; ++be) {
            int en = be + dis;
            int tk = s[be][en];
            dp[be][en] = inf;
            for (int k = s[be][en - 1]; k <= s[be + 1][en]; ++k) {
                if (k + 1 > en) break;
                int add = dp[be][k] + dp[k + 1][en] + sum[en] - sum[be - 1];
                if (dp[be][en] > add) {
                    dp[be][en] = add;
                    tk = k;
                }
            }
            s[be][en] = tk;
        }
    }
    int ans = inf;
    for (int i = 1; i <= n / 2; ++i) {
        ans = min(ans, dp[i][i + n / 2 - 1]);
    }
    cout << ans << endl;
}
int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    while (scanf("%d", &n) != EOF) work();
    return 0;
}
View Code

 

 
 
 
今天看得lrj的书中介绍的 四边形优化  做个笔记,加强理解 

最有代价用d[i,j]表示 
d[i,j]=min{d[i,k-1]+d[k+1,j]}+w[i,j] 
其中w[i,j]=sum[i,j] 
四边形不等式   
     w[a,c]+w[b,d]<=w[b,c]+w[a,d](a<b<c<d) 就称其满足凸四边形不等式 
决策单调性 
     w[i,j]<=w[i‘,j‘]   ([i,j]属于[i‘,j‘]) 既 i‘<=i<j<=j‘

 

 

http://www.cnblogs.com/zxndgv/archive/2011/08/02/2125242.html

 

 

hdu 3506 Monkey Party 区间dp + 四边形不等式优化