http://www.lydsy.com/JudgeOnline/problem.php?id=1096

首先得到dp方程(我竟然自己都每推出了QAQ)$$d[i]=min\{d[j]+cost(j+1,i)\}+c[i]$$其中$d[i]$是前i个且在i建仓库的最小费用,$cost(j+1,i)$是将j+1~i的东西全都运到i的费用

而我们先考虑cost怎么求,orz,好神的前缀和,首先维护sum[i]表示1~i的物品,则j~i的东西从j全都运到i需要$$(sum[i]-sum[j]) \times x[i]$$,然后再设前缀和b[i]表示1~i的物品每一个i从1运到i的费用,则$$cost[j+1,i]=(sum[i]-sum[j]) \times x[i]-(b[i]-b[j])$$其中$$sum[i]=sum[i-1]+p[i], b[i]=b[i-1]+p[i] \times x[i]$$

然后方程变成$$d[i]=min\{d[j]+(sum[i]-sum[j]) \times x[i]-(b[i]-b[j])\}+c[i]$$化简一下可得$$d[i]=min\{d[j]+b[j]-x[i] \times sum[j])\}+c[i]+sum[i] \times x[i]-b[i]$$

而对于这种方程,显然斜率优化。

而斜率优化有几个技巧:

1、不用1D1D直接上斜率,用通俗易懂的方法:

假设决策j<k且k比j优,即:

$$d[k]+b[k]-x[i] \times sum[k]<d[j]+b[j]-x[i] \times sum[j]$$

化简成:

$$\frac{d[k]+b[k]-d[j]-b[j]}{sum[k]-sum[j]}<x[i]$$

因为x[i]单调递增,所以当任意i<L,满足上边不等式,即决策k比j优(在i情况下k比j优的情况时),任意i<L的决策总是大于等于k的,所以当i取最优决策时,i<L的决策单调不降

接下来就是坐标轴的x单调递增,即根据上式,我们可以将点看做(sum[k], d[k]-b[k]),所以可以得到那个斜率方程,这样显然作为坐标轴x的sum[k]是单调不降的,所以得证。

因此这些决策就是二维平面上的点集,想象斜率为x[i]的直线从负无穷向正无穷扫,碰到的第一个点就是最优点(及凸包上的点),理由很简单,因为我们有上边那个不等式,凸包上的点k到任意点j<k的斜率总小于其它不在凸包上的点到任意点的斜率,即k为最优。

那么就维护一个单调队列,斜率递增,然后向求凸包的算法一样在队尾维护凸包即可。

2、论文《1D1D动态规划优化初步》上的做法(其实1的做法是这种做法的简便形式)

而之前的某题:【BZOJ】1010: [HNOI2008]玩具装箱toy(dp+斜率优化)

#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
#define mkpii make_pair<int, int>
#define pdi pair<double, int>
#define mkpdi make_pair<double, int>
#define pli pair<ll, int>
#define mkpli make_pair<ll, int>
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define read(a) a=getint()
#define print(a) printf("%d", a)
#define dbg(x) cout << (#x) << " = " << (x) << endl
#define error(x) (!(x)?puts("error"):0)
#define printarr2(a, b, c) for1(_, 1, b) { for1(__, 1, c) cout << a[_][__]; cout << endl; }
#define printarr1(a, b) for1(_, 1, b) cout << a[_] << '\t'; cout << endl
inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
inline const int max(const int &a, const int &b) { return a>b?a:b; }
inline const int min(const int &a, const int &b) { return a<b?a:b; } const int N=1000005;
int n, q[N], front, tail;
ll x[N], p[N], c[N], sum[N], b[N], f[N];
#define F(x) (f[x]+b[x])
#define E(k,j) (F(k)-F(j))
#define S(k,j) (sum[k]-sum[j]) int main() {
read(n);
for1(i, 1, n) read(x[i]), read(p[i]), read(c[i]);
for1(i, 1, n) sum[i]=sum[i-1]+p[i];
for1(i, 1, n) b[i]=b[i-1]+p[i]*x[i];
tail=1;
for1(i, 1, n) {
while(front<tail-1 && E(q[front+1], q[front])<x[i]*S(q[front+1], q[front])) ++front;
int j=q[front];
f[i]=f[j]+(sum[i]-sum[j])*x[i]-(b[i]-b[j])+c[i];
while(front<tail-1 && E(q[tail-1], q[tail-2])*S(i, q[tail-1])>E(i, q[tail-1])*S(q[tail-1], q[tail-2])) --tail;
q[tail++]=i;
}
printf("%lld", f[n]);
return 0;
}

  


Description

L公司有N个工厂,由高到底分布在一座山上。如图所示,工厂1在山顶,工厂N在山脚。 由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品直接堆放在露天,以节省费用。突然有一天,L公司的总裁L先生接到气象部门的电话,被告知三天之后将有一场暴雨,于是L先生决定紧急在某些工厂建立一些仓库以免产品被淋坏。由于地形的不同,在不同工厂建立仓库的费用可能是不同的。第i个工厂目前已有成品Pi件,在第i个工厂位置建立仓库的费用是Ci。对于没有建立仓库的工厂,其产品应被运往其他的仓库进行储藏,而由于L公司产品的对外销售处设置在山脚的工厂N,故产品只能往山下运(即只能运往编号更大的工厂的仓库),当然运送产品也是需要费用的,假设一件产品运送1个单位距离的费用是1。假设建立的仓库容量都都是足够大的,可以容下所有的产品。你将得到以下数据: 工厂i距离工厂1的距离Xi(其中X1=0);  工厂i目前已有成品数量Pi;  在工厂i建立仓库的费用Ci; 请你帮助L公司寻找一个仓库建设的方案,使得总的费用(建造费用+运输费用)最小。

Input

第一行包含一个整数N,表示工厂的个数。接下来N行每行包含两个整数Xi, Pi, Ci, 意义如题中所述。

Output

仅包含一个整数,为可以找到最优方案的费用。

Sample Input

3
0 5 10
5 3 100
9 6 10

Sample Output

32

HINT

在工厂1和工厂3建立仓库,建立费用为10+10=20,运输费用为(9-5)*3 = 12,总费用32。如果仅在工厂3建立仓库,建立费用为10,运输费用为(9-0)*5+(9-5)*3=57,总费用67,不如前者优。

【数据规模】

对于100%的数据, N ≤1000000。 所有的Xi, Pi, Ci均在32位带符号整数以内,保证中间计算结果不超过64位带符号整数。

Source

【BZOJ】1096: [ZJOI2007]仓库建设(dp+斜率优化)的更多相关文章

  1. BZOJ 1096: [ZJOI2007]仓库建设( dp + 斜率优化 )

    dp(v) = min(dp(p)+cost(p,v))+C(v) 设sum(v) = ∑pi(1≤i≤v), cnt(v) = ∑pi*xi(1≤i≤v), 则cost(p,v) = x(v)*(s ...

  2. BZOJ 1096 [ZJOI2007]仓库建设(斜率优化DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1096 [题目大意] 有个斜坡,有n个仓库,每个仓库里面都有一些物品,物品数目为p,仓库 ...

  3. BZOJ 1096 [ZJOI2007]仓库建设:斜率优化dp

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1096 题意: 有n个工厂,从左往右排成一排,分别编号1到n. 每个工厂里有p[i]件产品, ...

  4. bzoj 1096: [ZJOI2007]仓库建设【斜率优化】

    好眼熟啊 直接dp显然很难算,所以设val为只在n点建一个仓库的费用,然后设f[i]为在i~n点建若干仓库并且i点一定建一个仓库的最大省钱数 转移很显然,设s为p的前缀和,f[i]=max{f[j]+ ...

  5. BZOJ 1096: [ZJOI2007]仓库建设 动态规划 + 斜率优化

      #include<bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) #defi ...

  6. BZOJ1096: [ZJOI2007]仓库建设(dp+斜率优化)

    Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 5790  Solved: 2597[Submit][Status][Discuss] Descript ...

  7. BZOJ 1096: [ZJOI2007]仓库建设 [斜率优化DP]

    1096: [ZJOI2007]仓库建设 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4201  Solved: 1851[Submit][Stat ...

  8. 【BZOJ 1096】 [ZJOI2007]仓库建设 (斜率优化)

    1096: [ZJOI2007]仓库建设 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3940  Solved: 1736 Description ...

  9. bzoj 1096 [ZJOI2007]仓库建设(关于斜率优化问题的总结)

    1096: [ZJOI2007]仓库建设 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3234  Solved: 1388[Submit][Stat ...

  10. bzoj 1096: [ZJOI2007]仓库建设 斜率優化

    1096: [ZJOI2007]仓库建设 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2242  Solved: 925[Submit][Statu ...

随机推荐

  1. Simple drag and drop

    In computer graphical user interfaces, drag-and-drop is the action of (or support for the action of) ...

  2. Jquery重新学习之一[加载与属性html(),text(),val()]

    一:Jquery加载方式: 1:首先页面加载时马上响应JS代码如下运行(不一定要等所有的JS和图片加载完毕,就可以执行方法): $(document).ready(function(){ }); 另一 ...

  3. [转]K近邻算法

    什么是K近邻算法 何谓K近邻算法,即K-Nearest Neighbor algorithm,简称KNN算法,单从名字来猜想,可以简单粗暴的认为是:K个最近的邻居,当K=1时,算法便成了最近邻算法,即 ...

  4. 对固态硬盘ssd进行4k对齐

    别让SSD成半吊子!你真的4K对齐了吗? http://ssd.zol.com.cn/537/5374950_all.html SSD固态硬盘一键分区后如何检测4K对齐? http://pcedu.p ...

  5. 优化技术之Android高效开发

    基于Android平台的设备一定是嵌入式设备. 两个原则判断一个系统是否合理:不要做不必要做的事情:尽可能地节省内存的使用. 1. 尽量避免创建对象Object 2. 使用自身方法 3. 使用虚拟优于 ...

  6. xtrabackup备份方式搭建一个mysql slave

    以前mysql搭建新备库都是在现在业务较小的备库上停止同步或停止数据库,然后拷贝数据库到新备库,配置好新备库后,再开启同步或数据库.然而,这次没有空闲备库用来搭新备库.需要从一个业务繁忙的数据库中搭建 ...

  7. Python-类属性与对象属性之间的关系

    只要对象的属性未被指定赋值过, 不论类的属性怎么改变, 对象的属性都会跟随改变, 若对象属性被赋值过, 则不跟随类的属性而改变

  8. Linux下挂载硬盘分区的几种方法

    1.使用Autofs自动挂载分区 2.修改/etc/fstab 3.编写shell脚本,开机自动运行mount命令  方法一.使用Autofs  1.Autofs的特点:Autofs与Mount/Um ...

  9. Linux-软件包管理-rpm命令管理-安装-卸载

    mount 确认光盘是否挂载 mount /dev/cdrom /mnt/cdrom 将设备名称/dev/cdrom安装到/mnt/cdrom挂载点下面 mount 查看光盘是否已经挂载 (ro表示只 ...

  10. map 类简介和例程

    一.标准库的map类型 使用map得包含map类所在的头文件 template < class Key, class Type, class Traits = less<Key>, ...