DP优化——四边形不等式 uva 10304 - Optimal Binary Search Tree

// 原文地址  http://www.cnblogs.com/zxndgv/archive/2011/08/02/2125242.html

今天学习了一下四边形不等式,这个东西很早以前就看过,但是始终觉得很难,因为对于题目来说去证明的话总觉得有些麻烦撒~
今早看了看,把由w(i,j)满足四边形不等式能推出m(i,j)也满足四边形不等式的那一部分看明白了。决策单调性(也就是s(i,j)那一部分)没找的好的证明,便记住结论了。
个人感觉黑书上对于四边形不等式的讲解性价比还是比较高的,讲的都是重点,很好。
引用一下:
 当函数w(i,j)满足 w(a,c)+w(b,d) <= w(b,c)+w(a,d) 且a<=b< c <=d 时,我们称w(i,j)满足四边形不等式。。
当函数w(i, j)满足w(i', j) <= w(i, j'); i <= i' < j <= j' 时,称w关于关于区间包含关系单 
调。

s(i, j)=k是指m(i, j)这个状态的最优决策
以上定理的证明自己去查些资料
今天看得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'

于是有以下三个定理

定理一: 如果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) 







//我的代码  10304 - Optimal Binary Search Tree
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#include <cctype>

#include <bitset>
#include <utility>
#include <map>
#include <set>

#define INF 16843009
#define IM 253

#define FU(i,a,b) for (int _n(b), i(a); i < _n; i++)
#define FD(i,a,b) for(int i=(a),_b=(b);i>=_b;--i)
#define CL(a,v) memset((a),(v),sizeof(a))

using namespace std;

int n;
int sum[IM];
int w[IM][IM];

int dp[IM][IM];
int s[IM][IM];

void Init(){	
	int t;
	sum[0] = 0;
	FU(i,1,n+1){
		cin>>t;
		sum[i] = sum[i-1] + t;
	}
	
	FU(i,0,n+1)
		FU(j,i,n+1)
			w[i][j] = sum[j] - sum[i-1];
	
	CL(dp,1);
}


int DP(){   //main
	FU(i,0,IM) dp[i][i] = 0,s[i][i] = i;
	
	FU(len,2,n+1){
		FU(i,1,n+4){
			int j = i + len - 1;
			if(j > n+2) break;  // index !!!!!!!
			FU(k,s[i][j-1],s[i+1][j]+1){
				if(i > k-1) dp[i][k-1] = w[i][k-1] = 0;
				if(k+1 > j) w[k+1][j] = dp[k+1][j] = 0;
				int tmp = dp[i][k-1]+dp[k+1][j]+w[i][k-1]+w[k+1][j];
				if(tmp < dp[i][j]){
					dp[i][j] = tmp;
					s[i][j] = k;
				}
			}
			
		}
	}
	return dp[1][n];
}

int main()
{
   // freopen("in.in","r",stdin);
    while(cin>>n){
    	Init();
    	cout<<DP()<<endl;
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值