POJ 1180 斜率优化DP(单调队列)
| Time Limit: 1000MS | Memory Limit: 10000K | |
| Total Submissions: 4347 | Accepted: 1992 |
Description
A setup time S is needed to set up the machine for each batch. For each job i, we know its cost factor Fi and the time Ti required to process it. If a batch contains the jobs x, x+1,... , x+k, and starts at time t, then the output time of every job in that batch is t + S + (Tx + Tx+1 + ... + Tx+k). Note that the machine outputs the results of all jobs in a batch at the same time. If the output time of job i is Oi, its cost is Oi * Fi. For example, assume that there are 5 jobs, the setup time S = 1, (T1, T2, T3, T4, T5) = (1, 3, 4, 2, 1), and (F1, F2, F3, F4, F5) = (3, 2, 3, 3, 4). If the jobs are partitioned into three batches {1, 2}, {3}, {4, 5}, then the output times (O1, O2, O3, O4, O5) = (5, 5, 10, 14, 14) and the costs of the jobs are (15, 10, 30, 42, 56), respectively. The total cost for a partitioning is the sum of the costs of all jobs. The total cost for the example partitioning above is 153.
You are to write a program which, given the batch setup time and a sequence of jobs with their processing times and cost factors, computes the minimum possible total cost.
Input
Output
Sample Input
5
1
1 3
3 2
4 3
2 3
1 4
Sample Output
153
Source
dp[i]=min(dp[j]+(sunT[i]-sumT[j]+s)*sumF[i]) (1<=i<=n+1;i<j<=n+1)
我们考虑在计算dp[i]时,对于i < j < k来说, 如果保证决策k比决策j大的条件是:dp[j] + (S + sumT[i] - sumT[j]) * sumF[i] < dp[k] + (S + sumT[i] -sumT[k]) * sumF[i]
通过移项整理,可以化简为:(dp[j] - dp[k]) / (sumT[j] - sumT[k]) < sumF[i]
可知当我们计算dp[i]时,若(dp[j] - dp[k]) / (sumT[j] - sumT[k]) >=sumF[i]时我们可以舍弃j(决策K优于决策J);
因此我们可以用一个单调队列,对于元素i需要入对时,(i<j<k),我们如何维护呢,不妨设函数Q(j,k)=(dp[j] - dp[k]) / (sumT[j] - sumT[k]);
因为i需要入对,我们需要讨论的即是对于决策j,我们是否需要保留,(下面我们来讨论J需要舍弃的条件);
如果j需要舍弃,即对于决策i,j,i优于j;对于决策j,k,k优于j;故此我们有Q(i,j)<sumF[i],sumF[i]<=Q(j,k); 即推出 Qi,j)<Q(j,k);
综上:可以考虑维护一个斜率的队列来优化整个DP过程:
(1)假设i(马上要入队的元素)<j< k依次是队列尾部的元素,那么我们就要考虑Q(i,j)是否大于Q(j,k),如果Q(i,j) < Q(j,k),那么可以肯定j一定不会是决策点,可以从队列中将j去掉,依次向前推,直到找到一个队列元素少于2个或者Q(i,j)>= Q(j,k)的点才停止。
(2)假设k>j(k是头元素)是依次是队列头部的元素,如果g(j,k) < sumF[i]的话,那么对于i来说决策点j肯定优于决策点k,又由于sumF[i]是随着i减少而递增的,
所以当Q(j,k) < sumF[i]时,就一定有Q(j,k) < sumF[i-1],因此当前的决策点k不仅仅在考虑dp[i]时不会是最佳决策点,而且在后面的DP中也一定不会是最佳决策点,所以我们可以把k从队列 的头部删除,依次往后如此操作,直到队列元素小于2或者Q(j,k)>= sumF[i]。
代码:
#include<sstream>
#include<iomanip>
#include"cstdio"
#include"map"
#include"set"
#include"cmath"
#include"queue"
#include"vector"
#include"string"
#include"cstring"
#include"time.h"
#include"iostream"
#include"stdlib.h"
#include"algorithm"
#define db double
#define ll long long
#define vec vectr<ll>
#define mt vectr<vec>
#define ci(x) scanf("%d",&x)
#define cd(x) scanf("%lf",&x)
#define cl(x) scanf("%lld",&x)
#define pi(x) printf("%d\n",x)
#define pd(x) printf("%f\n",x)
#define pl(x) printf("%lld\n",x)
//#define rep(i, x, y) for(int i=x;i<=y;i++)
#define rep(i, n) for(int i=0;i<n;i++)
const int N = 1e4+ ;
const int mod = 1e9 + ;
const int MOD = mod - 1;
const int inf = 0x3f3f3f3f;
const db PI = acos(-1.0);
const db eps = 1e-;
using namespace std;
ll dp[N];
int st[N],sf[N],deq[N];
int t[N],f[N];
int n,s;
db cal(int x,int y){
return db(dp[x]-dp[y])/db(st[x]-st[y]);
}
int main()
{
ci(n),ci(s);
for(int i=;i<=n;i++) ci(t[i]),ci(f[i]);
for(int i=n;i;i--) st[i]=st[i+]+t[i],sf[i]=sf[i+]+f[i];
int l=,r=;
dp[n]=(s+st[n])*sf[n];
deq[++r]=n;
for(int i=n-;i;i--)
{
while(r-l>= && cal(deq[l],deq[l+])<sf[i]) l++;
int tt=s+st[i];
tt*=sf[i];
dp[i]=tt;
int j=deq[l];
tt=s+st[i]-st[j];
tt*=sf[i];
dp[i]=min(dp[i],dp[j]+tt);
while(r-l>= && cal(deq[r-],deq[r])>cal(deq[r],i)) r--;
deq[++r]=i;
}
pl(dp[]);
return ;
}
POJ 1180 斜率优化DP(单调队列)的更多相关文章
- poj 1180 斜率优化dp
这个题目要是顺着dp的话很难做,但是倒着推就很容易退出比较简单的关系式了. dp[i]=min(dp[u]+(sum[u-1]-sum[i-1]+s)*f[i]);dp[i]代表从i到结尾需要花费的代 ...
- 洛谷P3195 [HNOI2008] 玩具装箱 [DP,斜率优化,单调队列优化]
题目传送门 题目描述 P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N ...
- BZOJ_1096_[ZJOI2007]_仓库建设_(斜率优化动态规划+单调队列+特殊的前缀和技巧)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1096 有\(n\)个工厂,给出第\(i\)个工厂的到1号工厂的距离\(x[i]\),货物数量\ ...
- BZOJ_1010_[HNOI2008]_玩具装箱toy_(斜率优化动态规划+单调队列)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1010 给出\(n\)和\(l\).有\(n\)个玩具,第\(i\)个玩具的长度是\(c[i]\ ...
- 洛谷P3628 [APIO2010]特别行动队(动态规划,斜率优化,单调队列)
洛谷题目传送门 安利蒟蒻斜率优化总结 由于人是每次都是连续一段一段地选,所以考虑直接对\(x\)记前缀和,设现在的\(x_i=\)原来的\(\sum\limits_{j=1}^ix_i\). 设\(f ...
- 【BZOJ 4709】柠檬 斜率优化dp+单调栈
题意 给$n$个贝壳,可以将贝壳分成若干段,每段选取一个贝壳$s_i$,这一段$s_i$的数目为$num$,可以得到$num^2\times s_i$个柠檬,求最多能得到几个柠檬 可以发现只有在一段中 ...
- 算法笔记--斜率优化dp
斜率优化是单调队列优化的推广 用单调队列维护递增的斜率 参考:https://www.cnblogs.com/ka200812/archive/2012/08/03/2621345.html 以例1举 ...
- [poj3017] Cut the Sequence (DP + 单调队列优化 + 平衡树优化)
DP + 单调队列优化 + 平衡树 好题 Description Given an integer sequence { an } of length N, you are to cut the se ...
- POJ 3017 DP + 单调队列 + 堆
题意:给你一个长度为n的数列,你需要把这个数列分成几段,每段的和不超过m,问各段的最大值之和的最小值是多少? 思路:dp方程如下:设dp[i]为把前i个数分成合法的若干段最大值的最小值是多少.dp转移 ...
随机推荐
- 菜鸟 学注册机编写之 Android app
0x00前言 环境及工具: 手机 Nexus 4(己root) 系统版本 Android 5.01 工具 AndroidKiller_V1.2 关于Android平台app注册机的编 ...
- RabbitMQ基本用法、消息分发模式、消息持久化、广播模式
RabbitMQ基本用法 进程queue用于同一父进程创建的子进程间的通信 而RabbitMQ可以在不同父进程间通信(例如在word和QQ间通信) 示例代码 生产端(发送) import pika c ...
- lrzsz的使用
可以方便的在本地PC机和远程服务器之间传输文件. 1.下载 直接在centos上执行命令yum -y install lrzsz 2.上传文件 rz // 上传文件,执行命令rz,会跳出文件选择窗口, ...
- TP5.1:数据库的增删改查操作(基于数据库操作)
1.在app/index/controller文件夹下创建一个文件,名为:Operation 注意:起名一定要避开关键字,例如:mysql,curd等等,如果使用关键字起名,会造成报错! 在Opera ...
- 《孵化Twitter》:Twitter创始人勾心斗角史,细节披露程度令人吃惊
本书详细讲述twitter的发展史.感觉基本上是一部创始人从朋友变敌人,勾心斗角的历史.Twitter本身的产品发展反而相对比较简单. 书中披露了许多email.谈话.会议的细节,作者说这些是数百个小 ...
- Selenium入门11 滚动条控制(通过js)
这一节要有js基础.做web端的UI自动化必须要有html,css,javascript前端基础. 滚动条控制: 1 移动垂直滚动条 document.documentElement.scrollTo ...
- bzoj4836 [Lydsy2017年4月月赛]二元运算
Description 定义二元运算 opt 满足 现在给定一个长为 n 的数列 a 和一个长为 m 的数列 b ,接下来有 q 次询问.每次询问给定一个数字 c 你需要求出有多少对 (i, j) ...
- bzoj1801 [Ahoi2009]中国象棋
Description 在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮. 请问有多少种放置方法,中国像棋中炮的行走方式大家应该很清楚吧. Input 一行包含两个整数N, ...
- 【BZOJ4487】[JSOI2015] 染色问题(高维容斥)
点此看题面 大致题意: 有一个\(n*m\)的矩形,先让你用\(C\)种颜色给它染色.每个格子可染色可不染色,但要求每行每列至少有一个小方格被染色,且每种颜色至少出现一次.求方案数. 高维容斥 显然题 ...
- python 删除空白
Python能够找出字符串开头和末尾多余的空白.要确保字符串末尾没有空白,可使用方法rstrip() . >>> favorite_language = 'python ' > ...