区间dp+四边形优化

luogu:p2858

题意

给出一列数 \(v_i\),每天只能取两端的数,第 j 天取数价值为\(v_i \times j\),最大价值??

转移方程

dp[i][j] :n天卖掉i..j货物的收益

dp[begin][end]=max(dp[begin][end-1]+value[end]*(n-len+1) ,dp[begin+1][end]+value[begin]*(n-len+1));

注意理解

代码

递推形式

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mm1(x) memset(x,-1,sizeof(x))
#define maxn 2010
int dp[maxn][maxn],value[maxn];
int n;
int solve(){
for(int i=1;i<=n;i++){
dp[i][i]=value[i]*n;
//*key:
}
//枚举长度:
for(int len=2;len<=n;len++){
//枚举起点
for(int begin=1;begin<=n-len+1;begin++){
int end=begin+len-1;
dp[begin][end]=max(dp[begin][end-1]+value[end]*(n-len+1)
,dp[begin+1][end]+value[begin]*(n-len+1)); } }
return dp[1][n]; }
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",value+i);
}
mm1(dp);
printf("%d\n",solve());
return 0;
}

记忆化搜索

#include<bits/stdc++.h>
using namespace std;
//记忆化搜素
#define maxn 2010
int dp[maxn][maxn],value[maxn];
#define mm(x) memset(x,-1,sizeof(x));
int dfs(int i,int j,int num){
if(i>j) return 0;
if(dp[i][j]!=-1) return dp[i][j];
else{
dp[i][j]=max(value[i]*num+dfs(i+1,j,num+1),
value[j]*num+dfs(i,j-1,num+1));
}
return dp[i][j];
}
int n;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",value+i);
}
mm(dp);
int ans=dfs(1,n,1);
printf("%d\n",ans);
return 0;
}

记忆化搜索很好理解也方便些,是追求解题速度的很好选择

p1880

题意

石子合并问题:(环形,最小值+最大值)

题解

环形,可用\(2n\)长度,将元素复制一份

转移方程

dpmin[i][j]=min(dpmin[i][j],dpmin[i][k]+dpmin[k+1][j]+sum[j]-sum[i-1]);

对于最小值可用四边形不等式优化

dpmax[i][j]=min(dpmax[i][j],dpmax[i][k]+dpmax[k+1][j]+sum[j]-sum[i-1]);

对于最大值,某大佬题解中提到可优化之讨论端点情况(但本渣没有弄清楚)

dpmax[i][j]=max(dpmax[i][j-1]+sum[j]-sum[i-1],dpmax[i+1][j]+sum[j]-sum[i-1]);

四边形不等式优化

四边形不等式优化核心满足条件:

记决策点为\(k=s[i][j]\)

如果\(s[i][j-1]<=k<=s[i+1][j]\),则枚举k时,只需从s[i][j-1]枚举到s[i+1][j]$(因为这两者区间长度较短,已经被求出)

下面是重要的定理(不加证明的使用):

对于dp[i][j]=min(dp[i][k]+dp[k+1][j]+cost[i][j])

区间包含的单调性:如果小区间包含于大区间中,那么小区间的cost值不超过大区间的cost值

四边形不等式:两个交错区间的cost的和不超过小区间与大区间的cost的和

满足上述性质的cost,能够推出dp[i][j]满足四边形不等式,s[i][j]=k也满足上述性质。

综上,能够优化的关键在于cost[i][j]满足上述两个性质。*

代码

未优化代码:

#include<bits/stdc++.h>
using namespace std;
#define maxn 205
int dp1[maxn][maxn],dp2[maxn][maxn],value[maxn];
int sum[maxn];
//value[i]=value[i+n]
//区间dp
//dp[i][j]表示i..j最优得分
//O(N^3)
int n;
int min_ans=0x3f3f3f3f,max_ans=-1;
#define mm1(x) memset(x,-1,sizeof(x));
#define mm2(x) memset(x,0x3f,sizeof(x));
void init(){
mm1(dp1);
mm2(dp2);
for(int i=1;i<=2*n;i++){
sum[i]=sum[i-1]+value[i];
}
}
void solve(){
for(int i=1;i<=2*n;i++){
dp1[i][i]=dp2[i][i]=0; }
for(int len=2;len<=n;len++){
for(int begin=1;begin<=(2*n-len+1);begin++){
int end=begin+len-1;
for(int j=begin;j<=end-1;j++){
dp1[begin][end]=max(dp1[begin][end],dp1[begin][j]+dp1[j+1][end]+sum[end]-sum[begin-1]);
dp2[begin][end]=min(dp2[begin][end],dp2[begin][j]+dp2[j+1][end]+sum[end]-sum[begin-1]);
}
}
}
for(int i=1;i<=n;i++){
//printf("db max:%d min:%d\n",dp1[i][i+n-1],dp2[i][i+n-1]);
max_ans=max(max_ans,dp1[i][i+n-1]);
min_ans=min(min_ans,dp2[i][i+n-1]);
} }
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",value+i);
value[i+n]=value[i];
}
init();
solve();
printf("%d\n%d\n",min_ans,max_ans);
return 0; }

四边形不等式优化代码:

#include<bits/stdc++.h>
using namespace std;
//区间dp上的四边形优化
#define inf 0x3f3f3f3f
#define maxn 210
int sum[maxn],value[maxn];
int dpmax[maxn][maxn],dpmin[maxn][maxn];
int s[maxn][maxn];// min最优决策点
int n;
#define mm0(x) memset(x,0x3f,sizeof(x))
#define mm1(x) memset(x,-1,sizeof(x))
void init(){
mm1(dpmax);
mm0(dpmin);
for(int i=1;i<=2*n;i++){
sum[i]=sum[i-1]+value[i];
//printf("db i:%d sum[i] %d\n",i,sum[i]);
} }
int minv=inf,maxv=0;
void solve(){
for(int i=1;i<=2*n;i++){
dpmax[i][i]=dpmin[i][i]=0;
s[i][i]=i;
} for(int len=2;len<=n;len++){
for(int i=1;i+len-1<=2*n;i++){
int j=i+len-1;
dpmax[i][j]=max(dpmax[i][j-1]+sum[j]-sum[i-1],dpmax[i+1][j]+sum[j]-sum[i-1]);
//某大佬认为最大值取得必然最后一次合并在左右两端
//目前自己没有想通和证明
int idx;
for(int k=s[i][j-1];k<=s[i+1][j];k++){
if((dpmin[i][k]+dpmin[k+1][j]+sum[j]-sum[i-1])<dpmin[i][j]){
dpmin[i][j]=dpmin[i][k]+dpmin[k+1][j]+sum[j]-sum[i-1];
idx=k;
}
s[i][j]=idx;
}
// printf("db min: %d k:%d i:%d j: %d\n",dpmin[i][j],s[i][j],i,j);
}
}
for(int i=1;i<=n;i++){
//printf("db i:%d %d\n",i,dpmin[i][i+n-1]);
minv=min(dpmin[i][i+n-1],minv);
maxv=max(dpmax[i][i+n-1],maxv);
} }
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",value+i);
value[i+n]=value[i];
}
init();
solve();
printf("%d\n%d\n",minv,maxv);
return 0;
}

区间dp+四边形不等式优化的更多相关文章

  1. CSP 201612-4 压缩编码 【区间DP+四边形不等式优化】

    问题描述 试题编号: 201612-4 试题名称: 压缩编码 时间限制: 3.0s 内存限制: 256.0MB 问题描述: 问题描述 给定一段文字,已知单词a1, a2, …, an出现的频率分别t1 ...

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

    http://acm.hdu.edu.cn/showproblem.php?pid=3506 四边行不等式:http://baike.baidu.com/link?url=lHOFq_58V-Qpz_ ...

  3. hdu3506 Monkey Party (区间dp+四边形不等式优化)

    题意:给n堆石子,每次合并相邻两堆,花费是这两堆的石子个数之和(1和n相邻),求全部合并,最小总花费 若不要求相邻,可以贪心地合并最小的两堆.然而要求相邻就有反例 为了方便,我们可以把n个数再复制一遍 ...

  4. P1880 [NOI1995]石子合并[区间dp+四边形不等式优化]

    P1880 [NOI1995]石子合并 丢个地址就跑(关于四边形不等式复杂度是n方的证明) 嗯所以这题利用决策的单调性来减少k断点的枚举次数.具体看lyd书.这部分很生疏,但是我还是选择先不管了. # ...

  5. Codevs 3002 石子归并 3(DP四边形不等式优化)

    3002 石子归并 3 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题目描述 Description 有n堆石子排成一列,每堆石子有一个重量w[i], 每次 ...

  6. [51nod 1022] 石子归并v2 [dp+四边形不等式优化]

    题面: 传送门 思路: 加强版的石子归并,现在朴素的区间dp无法解决问题了 首先我们破环成链,复制一条一样的链并粘贴到原来的链后面,变成一个2n长度的序列,在它上面dp,效率O(8n^3) 显然是过不 ...

  7. 51nod 1022 石子归并 V2 —— DP四边形不等式优化

    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1022 1022 石子归并 V2  基准时间限制:1 秒 空间限 ...

  8. HDU 3516 DP 四边形不等式优化 Tree Construction

    设d(i, j)为连通第i个点到第j个点的树的最小长度,则有状态转移方程: d(i, j) = min{ d(i, k) + d(k + 1, j) + p[k].y - p[j].y + p[k+1 ...

  9. HDU-2829 Lawrence (DP+四边形不等式优化)

    题目大意:有n个敌方军火库呈直线排列,每个军火库有一个值vi,并且任意相邻的两个库之间都有通道相连.对于任意一条连起来的军火库链,它对我方的威胁可以用函数w(i,j)表示为:w(i,j)=vi*sum ...

随机推荐

  1. Python数据结构1-----基本数据结构和collections系列

    1.基本数据结构 整型.浮点型.字符串.元祖.列表.字典.集合 2.高级数据结构 (collections模块) (1)计数器(counter):对字典的补充,用于追踪值的出现次数. [具备字典所有的 ...

  2. BA-siemens-insight-event builder使用

    event builder功能主要是用来给report使用的,作为一个独立的对象,这个对象的功能就是收集点位的信息,如果再使用report功能就可以显示或输出点位的信息.

  3. cogs 306. [SGOI] 糊涂的记者

    306. [SGOI] 糊涂的记者 ★★★   输入文件:sign.in   输出文件:sign.out   评测插件时间限制:1 s   内存限制:128 MB [问题描述] 在如今的信息社会中,时 ...

  4. oracle schema彻底理解

    oracle中的Schema简析 在一个数据库中可以有多个应用的数据表,这些不同应用的表可以放在不同的schema之中,同时,每一个schema对应一个用户,不同的应用可以以不同的用户连接数据库,这样 ...

  5. [SharePoint2010开发入门经典]11、与Office集成

    本章概要: 1.创建office集成解决方案使用代码或非代码形式 2.使用内容类型作为能映射到文档库的文档 3.使用InfoPath管理表单 4.使用工作流管理业务流程 5.使用office2010服 ...

  6. asp.net core 2.1开发环境下配置IIS

    asp.net core 2.1是可以在开发环境下配置到IIS中的,这样就可以在vs中按F5直接运行了 在项目上右键点击属性,然后在Debug中配置如下参数 首先点击New按钮,输入IIS,点击确定 ...

  7. Java Secret: Using an enum to build a State machine(Java秘术:用枚举构建一个状态机)

    近期在读Hadoop#Yarn部分的源代码.读到状态机那一部分的时候,感到enmu的使用方法实在是太灵活了,在给并发编程网翻译一篇文章的时候,正好碰到一篇这种文章.就赶紧翻译下来,涨涨姿势. 原文链接 ...

  8. 通过Gulp流方式处理流程

    http://www.cnblogs.com/gongcheng9990/archive/2014/11/25/4120434.html http://modernweb.com/2014/08/04 ...

  9. 2015.04.21,外语,读书笔记-《Word Power Made Easy》 11 “如何辱骂敌人” SESSION 31

    1.no reverence iconoclast([ai'kɔnәklæst]  n. 毁坏宗教神像的人, 提倡打破旧习的人)藐视传统.在青年的反叛期很容易出现iconoclasm([ai'kɔnә ...

  10. Android安全攻防战,反编译与混淆技术全然解析(下)

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/50451259 在上一篇文章其中,我们学习了Android程序反编译方面的知识,包括 ...