四边形不等式
来源:互联网 发布:神州律师网网络培训 编辑:程序博客网 时间:2024/04/29 21:08
总结一下最近几天对dp优化中的四边形不等式的学习。
证明什么的似懂非懂,我还是太年轻了。
第一种, n^2 -> nlogn
例题:http://wzoi.cc/s/1370/1304 (由于权限问题 不公开题面)
就是1个体积均为1-300,100000个物品,做一个100000的背包。
发现体积最多只有 300 种,分开做。对于同种体积的物品,显然按照价值从大到小取最优。
我们假设 s=1,设状态 f[i]为大小为 i的背包的最大收益。
转移函数 f[i]=max(f[ i-j ]+sum(a[1..j]))
是一个 f[x]=min{f[i]+w[i,x]}的经典模型
w满足大区间大于等于小区间的性质,
且当 a<b<c<d时,w[a,c]+w[b,d]<=w[a,d]+w[b,c],
于是 决策有单调性 ,假如用 k(x)表示状态x 取到最优值时的决策 , k(x) 是不降的。
注意到给定两个决策点,我们是可以通过二分计算出令他们大小关系反转的时间点 t 的。
于是就可以维护一个单调栈,进行二分。
对于其他的 s,发现只有在状态模 s 同余时单调性才成立,所以对于每一种体积 s,按照剩余类的顺序依次做即可。
时间复杂度 O(MAXS*K+N)
code :
#include<bits/stdc++.h>using namespace std;typedef long long ll;#define rep(i,l,r) for(int i=l;i<=r;++i)#define per(i,r,l) for(int i=r;i>=l;--i)template <typename T> void chmin(T &x,const T &y){if(x>y)x=y;}template <typename T> void chmax(T &x,const T &y){if(x<y)x=y;}const int N=1e6+5,M=1e5+5,S=300+5;ll dp[S][M];int t[S];struct edge{int v,next;}l[N];ll val[N];int q[N],top;int st[N],can[N],head,tail;int s,d,mi,i;ll get(int j,int i){return dp[s-1][j*s+d]+val[i-j];}bool you(int j,int k){return get(i,k)>=get(j,k);}#define mid (l+r>>1)int erfen(){if(head==tail) return i;int j=st[tail-1];int l=can[tail-1],r=mi;while(l+1!=r) if(you(j,mid)) r=mid;else l=mid;return r;}int main(){//freopen("1.in","r",stdin);freopen("1.out","w",stdout);int n,m;cin>>n>>m;rep(i,1,n){int s;scanf("%d%d",&s,&l[i].v);l[i].next=t[s];t[s]=i;}dp[0][0]=0;for(s=1;s<=300;++s){if(!t[s]){memcpy(dp[s],dp[s-1],sizeof(dp[s]));continue;}top=0;for(int i=t[s];i;i=l[i].next) q[++top]=l[i].v;sort(q+1,q+top+1,greater<int>() );rep(i,1,top)val[i]=val[i-1]+q[i];rep(i,top+1,m)val[i]=0;for(d=0;d<s;++d){mi=(m-d)/s;head=1;tail=0;for(i=0;i<=mi;++i){while(head<tail&&can[head+1]<=i)++head;if(can[head]<i)can[head]=i;while(head<=tail&&you(st[tail],can[tail]))--tail;if(head>tail){st[++tail]=i;can[tail]=i;}elseif(you(st[tail],mi)){st[++tail]=i;can[tail]=erfen();}dp[s][i*s+d]=get(st[head],i);}}}rep(i,1,m)printf("%lld ",dp[300][i]);}
第二种:n^3-> n^2
(1)区间包含的单调性:如果对于i≤i'<j≤j',有w(i',j)≤w(i,j'),那么说明w具有区间包含的单调性。(可以形象理解为如果小区间包含于大区间中,那么小区间的w值不超过大区间的w值)
(2)四边形不等式:如果对于i≤i'<j≤j',有w(i,j)+w(i',j')≤w(i',j)+w(i,j'),我们称函数w满足四边形不等式。(可以形象理解为两个交错区间的w的和不超过小区间与大区间的w的和)
下面给出两个定理
定理一:如果上述的w函数同时满足区间包含单调性和四边形不等式性质,那么函数m也满足四边形不等式性质。
我们再定义s(i,j)表示m(i,j)取得最优值时对应的下标(即i≤k≤j时,k处的w值最大,则s(i,j)=k)。此时有如下定理
定理二:假如m(i,j)满足四边形不等式,那么s(i,j)单调,即s(i,j)≤s(i,j+1)≤s(i+1,j+1)。
例题: poj1160
code
#include<stdio.h>#include<string.h>#define MAXD 310#define MAXP 40#define INF 0x3f3f3f3fint N, P, f[MAXD][MAXD], A[MAXD], a[MAXD], K[MAXD][MAXD];void init(){ int i, j, k; A[0] = 0; for(i = 1; i <= N; i ++) { scanf("%d", &a[i]); A[i] = A[i - 1] + a[i]; }}int getw(int x, int y){ int t = (x + y) / 2; return A[y] - A[t] - (y - t) * a[t] + (t - x) * a[t] - (A[t - 1] - A[x - 1]);}void solve(){ int i, j, k, p, t; for(i = 0; i <= N; i ++) { f[i][i] = 0; K[i][i] = i; } for(p = 1; p <= N - P; p ++) { for(i = 0; (j = i + p) <= N; i ++) f[i][j] = INF; for(i = 1; (j = i + p) <= N; i ++) { for(k = K[i][j - 1]; k <= K[i + 1][j]; k ++) if((t = f[i - 1][k - 1] + getw(k, j)) < f[i][j]) { f[i][j] = t; K[i][j] = k; } } } printf("%d\n", f[P][N]);}int main(){ while(scanf("%d%d", &N, &P) == 2) { init(); solve(); } return 0;}
本来无法理解三重循环为何n^2,后来模拟了一遍,
从小区间推向大区间即从dp方阵的每条对角线(好吧不是对角线 就是表达那个意思)从中间向两边转移,
,每条对角线的转移时O(n)的,然后有O(n)条对角线,于是就O(n^2)了,太神了%%%。
- 四边形不等式
- 四边形不等式
- 四边形不等式
- 四边形不等式
- 四边形不等式
- 四边形不等式 hdu
- 四边形不等式优化
- 四边形不等式相关
- POJ1160-四边形不等式优化
- 四边形不等式优化
- 【DP 四边形不等式】
- 四边形不等式优化DP
- hdu3516 --- 四边形不等式优化
- HDU 3516 (四边形不等式)
- 四边形不等式优化
- 四边形不等式优化
- ccfcsp201612-四边形不等式优化
- 四边形不等式优化dp
- HtmlUtils把HTML编码转义,可将HTML标签互相转义
- 检查回文字符串重难点:去除多余标点和空格
- java 大数值
- review..wait
- Windows7下使用VS2015搭建Lua开发环境
- 四边形不等式
- 剑指offer之最小的K个数(Python)
- Windows上pyltp的安装及使用
- 创建登录界面
- 第7章任务1:从键盘输入3个整型数据
- 线索化二叉树(中序)
- 【信息学奥赛】【C++】(一)赋值语句
- 十八、java中的类和对象
- hadoop2.8.2分布式集群实战