题目链接:http://poj.org/problem?id=1180

题目描述:

There is a sequence of N jobs to be processed on one machine. The jobs are numbered from 1 to N, so that the sequence is 1,2,..., N. The sequence of jobs must be partitioned into one or more batches, where each batch consists of consecutive jobs in the sequence. The processing starts at time 0. The batches are handled one by one starting from the first batch as follows. If a batch b contains jobs with smaller numbers than batch c, then batch b is handled before batch c. The jobs in a batch are processed successively on the machine. Immediately after all the jobs in a batch are processed, the machine outputs the results of all the jobs in that batch. The output time of a job j is the time when the batch containing j finishes.

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

Your program reads from standard input. The first line contains the number of jobs N, 1 <= N <= 10000. The second line contains the batch setup time S which is an integer, 0 <= S <= 50. The following N lines contain information about the jobs 1, 2,..., N in that order as follows. First on each of these lines is an integer Ti, 1 <= Ti <= 100, the processing time of the job. Following that, there is an integer Fi, 1 <= Fi <= 100, the cost factor of the job.

Output

Your program writes to standard output. The output contains one line, which contains one integer: the minimum possible total cost.

Sample Input

5
1
1 3
3 2
4 3
2 3
1 4

Sample Output

153

Source

 
看不懂题面的随便找一个翻译软件翻译一下效果都还是不错的,至少看得懂题
 
下面直接解题:
解法一:求出T,C的前缀和sumT和sumC,设f(i,j)表示把前i个任务分成j批去执行的最小费用,状态转移方程为
f(i,j)=min(0<=k<i){f(k,j-1)+(s*j+sumT[i])*(sumC[i]-sumC[k])}
时间复杂度为O(N3)
解法二:
本题其实没有规定把任务分成多少批,也就是说解法一其实有无用的状态
现在我们设f(i)表示把前i个任务分成若干批处理的最小费用,状态转移方程为
f[i]=min(0<=j<i){f[j]+sumT[i]*(sumC[i]-sumC[j])+s*(sumC[N]-sumC[j])}
这种思想叫做“费用提前计算”,先把每次s的贡献直接加起来
时间复杂度O(N2)
解法三:
我们考虑到这题的数据,对解法二的状态转移方程进行斜率优化。
去掉min,通过移项我们可以得到f[j]=(s+sumT[i])*sumC[j]+f[i]-sumT[i]*sumC[i]-s*sumC[N]
我们发现,在以sumC[j]为横坐标,f[j]为纵坐标的坐标系中,这是条以(s+sumT[i])为斜率,f[i]-sumT[i]*sumC[i]-s*sumC[N]为截距的直线
由于-sumT[i]*sumC[i]-s*sumC[N]是一个常数,斜率也是一个固定的值,这是一个线性规划问题,我们每次取最小的截距
对于点集(sumC[j],f[j])我们其实只需要维护一个下凸壳就行了。当我们需要找到当前的最优的点时,设k=s+sumT[i],最优的点和它左边的点的斜率比k小,和它右边的斜率比k大,参考下面的图。
 
另外我们还发现一点,由于sumC具有单调性,每次加入的点都会在最右边。并且sumT同样具有单调性,这说明斜率是递增的。因此我们只需要维护比当前斜率大的一条条线段,可以通过一个单调队列q来实现
具体操作如下:
1.检查队头的两个决策变量q[l]和q[l+1],斜率f[q[l+1]]-f[q[l]]/(sumC[q[l+1]]-sumC[q[l]])<=s+sumT[i],则把q[l]出队,继续检查新的队头。
2.直接取队头j=q[l]作为最优策略,执行状态转移,得到f[i]
3.把新决策i从队尾插入,在插入之前,若三个决策点j1=q[r-1],j2=q[r],j3=i不满足斜率单调递增(不满足下凸性,即i是无用决策),则直接从队尾把q[r]出队,继续检查新的队尾。
整个算法的时间复杂度O(N),完美的解决问题。
 
下面附上代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std; const int maxn=1e4+;
int n,s;
int sumt[maxn],sumc[maxn],q[maxn];
ll f[maxn];
int main()
{
scanf("%d%d",&n,&s);
for (int i=;i<=n;i++)
{
int t,c;
scanf("%d%d",&t,&c);
sumt[i]=sumt[i-]+t;
sumc[i]=sumc[i-]+c;
}
int l=,r=;
for (int i=;i<=n;i++)
{
while (l<r&&(f[q[l+]]-f[q[l]])<=(s+sumt[i])*(sumc[q[l+]]-sumc[q[l]])) l++;
f[i]=f[q[l]]-(s+sumt[i])*sumc[q[l]]+sumt[i]*sumc[i]+s*sumc[n];
while (l<r&&(f[q[r]]-f[q[r-]])*(sumc[i]-sumc[q[r]])>=(f[i]-f[q[r]])*(sumc[q[r]]-sumc[q[r-]])) r--;
q[++r]=i;
}
printf("%lld",f[n]);
return ;
}

声明:本博客内容参考李煜东算法竞赛进阶指南

POJ1180 Batch Scheduling 解题报告(斜率优化)的更多相关文章

  1. [POJ1180&POJ3709]Batch Scheduling&K-Anonymous Sequence 斜率优化DP

    POJ1180 Batch Scheduling Description There is a sequence of N jobs to be processed on one machine. T ...

  2. POJ-1180 Batch Scheduling (分组求最优值+斜率优化)

    题目大意:有n个任务,已知做每件任务所需的时间,并且每件任务都对应一个系数fi.现在,要将这n个任务分成若干个连续的组,每分成一个组的代价是完成这组任务所需的总时间加上一个常数S后再乘以这个区间的系数 ...

  3. POJ1180 Batch Scheduling -斜率优化DP

    题解 将费用提前计算可以得到状态转移方程: $F_i = \min(F_j + sumT_i * (sumC_i - sumC_j) + S \times (sumC_N - sumC_j)$ 把方程 ...

  4. poj1180 Batch Scheduling

    Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3590   Accepted: 1654 Description There ...

  5. 【LeetCode】1029. Two City Scheduling 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 小根堆 排序 日期 题目地址:https://lee ...

  6. P2365 任务安排 / [FJOI2019]batch(斜率优化dp)

    P2365 任务安排 batch:$n<=10000$ 斜率优化入门题 $n^{3}$的dp轻松写出 但是枚举这个分成多少段很不方便 我们利用费用提前的思想,提前把这个烦人的$S$在后面的贡献先 ...

  7. LeetCode :1.两数之和 解题报告及算法优化思路

    最近开始重拾算法,在 LeetCode上刷题.顺便也记录下解题报告以及优化思路. 题目链接:1.两数之和 题意 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 ...

  8. poj 1180 Batch Scheduling (斜率优化)

    Batch Scheduling \(solution:\) 这应该是斜率优化中最经典的一道题目,虽然之前已经写过一道 \(catstransport\) 的题解了,但还是来回顾一下吧,这道题其实较那 ...

  9. POJ 1180 Batch Scheduling(斜率优化DP)

    [题目链接] http://poj.org/problem?id=1180 [题目大意] N个任务排成一个序列在一台机器上等待完成(顺序不得改变), 这N个任务被分成若干批,每批包含相邻的若干任务. ...

随机推荐

  1. Asp.net button防止点击多次数据提交

     <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat= ...

  2. 创建表空间及plsql查看远程表空间路径

    -新建表空间,登录名和密码 --请尽量把表空间和别的系统分离,这里以Search为例子,登录名和密码以test为例子 create tablespace Search logging datafile ...

  3. Server Tomcat v7.0 Server at localhost failed to start.解决办法(图文详解)

    问题描述 Server Tomcat v7.0 Server at localhost failed to start. 解决办法 把你工作空间文件夹下的如下路径打开: <workspace-d ...

  4. ASP.NET 让ajax请求webform后台方法

    $.ajax({ type: "POST", url: ".aspx/getSubjectDirection", data: JSON.stringify({ ...

  5. ActiveMQ学习笔记(3)----JMS的可靠性机制

    1. 消息接收确认 JMS消息只有在被确认之后,才认为已经被成功的消费了,消息成功消费通常包含三个阶段:客户接收消息,客户处理消息和消息被确认. 在事务性会话中,当一个事务被提交的时候,确认自动发生. ...

  6. Js jquery常用的身份证号码 邮箱电话等验证

    刷了很多博客,https://www.cnblogs.com/hao-1234-1234/p/6636843.html 只有这个比较靠谱.

  7. var和let的区别

    //var 和let的区别 通过var定义的变量,作用域是整个封闭的函数,是全域的, 通过let定义的变量,作用域是在块级或者是子块中 for (let i = 0; i < 10; i++) ...

  8. webpack 操作

    依赖安装 :  全局安装webpack : sudo npm install webpack -g 本地安装webpack : npm install webpack —save-dev  需要注意的 ...

  9. echars 在vue v-if 切换会 显示不出来或者显示出来但是不是百分百显示

    我也是百度看别人写的原因,然后自己总结,以后用到的时候来复制就可以将  v-if换成 v-show 第二不是百分百显示  可以用 this.$nextTick(function() { this.in ...

  10. linux 空间不够了 修改 /boot

    1>  查看空间多少:df -h2>  查看当期内核: uname -r3>  查找内核   rpm -qa | grep kernel4>  删除多余的内核 yum remo ...