batch

★☆   输入文件:batch.in   输出文件:batch.out   简单对比
时间限制:1 s   内存限制:128 MB

题目描

N个任务排成一个序列在一台机器上等待完成(顺序不得改变),这N个任务被分成若干批,每批包含相邻的若干任务。从时刻0开始,这些任务被分批加工,第i个任务单独完成所需的时间是Ti。在每批任务开始前,机器需要启动时间S,而完成这批任务所需的时间是各个任务需要时间的总和(同一批任务将在同一时刻完成)。每个任务的费用是它的完成时刻乘以一个费用系数Fi。请确定一个分组方案,使得总费用最小。

例如:S=1;T={1,3,4,2,1};F={3,2,3,3,4}。如果分组方案是{1,2}、{3}、{4,5},则完成时间分别为{5,5,10,14,14},费用C={15,10,30,42,56},总费用就是153。

输入格式

第一行是N(1<=N<=5000)。

第二行是S(0<=S<=50)。

下面N行每行有一对数,分别为Ti和Fi,均为不大于100的正整数,表示第i个任务单独完成所需的时间是Ti及其费用系数Fi

输出格

一个数,最小的总费用。

输入样

5
1
1 3
3 2
4 3
2 3

1 4

输出样

153

额  哇哇哇  dp写挂了 QAQ

正解1

f[i]   前i个任务的最优结果

f[i]=min{f[j] +sumt[i]*(sumc[i]-sumc[j])+S*(sumc[n]-sumc[j])}

好东西呢 唉 QAQ

详细题解如下:

暴力方法

由于每一批任务连续,所以预处理出两个前缀和数组:

sumt[i] 表示 执行前i个任务所需要的时间 , 即t[1]+t[2]+...+t[n]

sumc[i] 表示 不乘时间时,执行前i个任务所需要的费用 , 即c[1]+c[2]+...+c[n]

dp子状态:

dp[i][j] 表示 前i个任务分成j批所需要的最小费用。

于是可以由dp[k][j-1]推出dp[i][j]:

dp[i][j]=min{dp[k][j-1]+(s*j+sumt[i])*(sumc[i]-sumc[k])}

时间复杂度O(n^3),

空间复杂度O(n^2)。

略微优化

暴力方法的dp子状态空间是二维的,由于N <= 10000 ,所以考虑将二维状态降到一维。

将第一维去掉的想法不太实际,故考虑将第二维去掉。

首先思考所有任务都放到同一批中,观察每个任务需要等待S时间的次数:

任务编号 1  2  3  ...  n

等待次数 1  1  1  ...  1

当将1~pos1分成一个区间时,每个任务需要等待的次数变为:

任务编号 1  2  3  ...  pos1  pos1+1  ...  n

等待次数 1  1  1  ...   1      2     ...  2

(如果仍然看不出来,可以再分几次找找规律)

观察等待次数:每次多分出一个区间,区间左端点到n都需要多等待一次S时间。

故可以推出一个新的方程:

dp[i]=min{dp[j]+sumt[i]*(sumc[i]-sumc[j]+s*(sumc[n]-sumc[j]))

dp[i]并不只是前i个的时间  还要加上对后面的影响

上面其实就已经AC了  (但是老师的本意是要让我们写斜率优化)

斜率优化

当每次求dp[i]时,分别整理i,j的信息,把原来的方程进行玄学变形(移项):

dp[i]=min{dp[j]-(s+sumt[i])*sumc[j]}+sumt[i]*sumc[i[]+s*sumc[n]

去掉min函数,把dp[j]和sumc[j]看作变量,整理出dp[j]关于sumc[j]的一次函数(重要!):

dp[j]=(s+sumt[i]) * sumc[j] + (dp[i]-sumt[i]*sumc[i]-s*sumc[n])

y  =    k       *    x    +                 b

其中sumc[j]是自变量,dp[j]是因变量,s+sumt[i]是斜率,后面一串为截距。

建立一个平面直角坐标系:

每个决策j的二元组(sumc[j] , dp[j])表示坐标系中的点。

当前状态dp[i]表示直线的截距(且这条直线斜率为s+sumt[i])。

令直线过每个点可以得到解出截距,使截距最小的就是最优决策。

如图:

讨论三个决策点j1,j2,j3(j1<j2<j3)对应的坐标系中的点:

第一种情况:上凸。用眼睛观察(hhh)可知,j2此时不可能成为最佳决策点,故放弃。

第二种情况:下凹。此时j2有可能成为最佳决策点。

最后把所有可能成为最佳决策点的j处理出来,即维护一个相邻点斜率单调递增的“凸壳”。

其中最佳决策点左端斜率<s+sum[i],右端斜率>s+sum[i](可以证明这样的点只有一个)。

又因为s+sumt[i]是单调递增的,所以可以用单调队列找第一个右端斜率>s+sum[i]的点。

总时间复杂度:循环递推O(n)+单调队列O(n)=O(n)。

空间复杂度:一维状态O(n)。

#include <stdio.h>
typedef long long ll;
typedef double db;
const int N=1e6+;
int n,S,s[N],t[N],q[N],head,tail;
ll dp[N],val[N];
db k(int j,int k){return (db)(val[j]-val[k])/(s[j]-s[k]);}
int main()
{
freopen("batch.in","r",stdin);
freopen("batch.out","w",stdout);
scanf("%d%d",&n,&S);
for (int i=;i<=n;i++){
scanf("%d%d",&t[i],&s[i]);
t[i]+=t[i-];
s[i]+=s[i-];
}
q[head=tail=]=;
for (int i=;i<=n;i++){
for (;head<tail&&k(q[head],q[head+])<S+t[i];head++);
int j=q[head];
dp[i]=dp[j]+ll(s[n]-s[j])*(S+t[i]-t[j]);
val[i]=dp[i]+(ll)s[i]*t[i]-(ll)s[n]*t[i];
for (;head<tail&&k(q[tail-],q[tail])>k(q[tail],i);tail--);
q[++tail]=i;
}
printf("%lld\n",dp[n]);
return ;
}

N^2暴力AC!

#include<bits/stdc++.h>
#define maxn 5005
using namespace std;
int t[maxn],f[maxn],sumt[maxn],sumf[maxn],dp[maxn];
int main(){
// freopen("batch.in","r",stdin);freopen("batch.out","w",stdout);
int n,s;scanf("%d%d",&n,&s);
for(int i=;i<=n;i++) scanf("%d%d",&t[i],&f[i]);
for(int i=;i<=n;i++) sumt[i]=sumt[i-]+t[i],sumf[i]=sumf[i-]+f[i];
memset(dp,0x3f,sizeof(dp));
// dp[1]=t[1]*f[1]+s*(sumf[n]-sumf[1]);
dp[]=;
for(int i=;i<=n;i++)
for(int j=;j<i;j++)
dp[i]=min(dp[i],dp[j]+sumt[i]*(sumf[i]-sumf[j])+s*(sumf[n]-sumf[j]));
printf("%d",dp[n]);
//f[i]=min{f[j] +sumt[i]*(sumc[i]-sumc[j])+S*(sumc[n]-sumc[j])}
return ;
}

P2365 任务安排 batch 动态规划的更多相关文章

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

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

  2. 2018.07.09 洛谷P2365 任务安排(线性dp)

    P2365 任务安排 题目描述 N个任务排成一个序列在一台机器上等待完成(顺序不得改变),这N个任务被分成若干批,每批包含相邻的若干任务.从时刻0开始,这些任务被分批加工,第i个任务单独完成所需的时间 ...

  3. luogu P2365 任务安排(FJOI2019 batch)

    洛谷传送门 FJOI 日常原题 $2333$(似乎还不如 SDOI2012 任务安排 $2333$) 显然考虑 $dp$,这个是经典的把未来的代价先计算的 $dp$,然后才是斜率优化 一开始想状态时一 ...

  4. [洛谷P2365] 任务安排

    洛谷题目链接:任务安排 题目描述 N个任务排成一个序列在一台机器上等待完成(顺序不得改变),这N个任务被分成若干批,每批包含相邻的若干任务.从时刻0开始,这些任务被分批加工,第i个任务单独完成所需的时 ...

  5. tyvj1098[luogu 2365]任务安排 batch

    题目描述 N个任务排成一个序列在一台机器上等待完成(顺序不得改变),这N个任务被分成若干批,每批包含相邻的若干任务.从时刻0开始,这些任务被分批加工,第i个任务单独完成所需的时间是Ti.在每批任务开始 ...

  6. luogu P2365 任务安排

    嘟嘟嘟 如果常规dp,\(dp[i][j]\)表示前\(i\)个任务分\(j\)组,得到 \[dp[i][j] = min _ {k = 0} ^ {i - 1} (dp[k][j - 1] + (s ...

  7. 洛谷P2365 任务安排 [解法二 斜率优化]

    解法一:http://www.cnblogs.com/SilverNebula/p/5926253.html 解法二:斜率优化 在解法一中有这样的方程:dp[i]=min(dp[i],dp[j]+(s ...

  8. 洛谷P2365 任务安排 [解法一]

    题目描述 N个任务排成一个序列在一台机器上等待完成(顺序不得改变),这N个任务被分成若干批,每批包含相邻的若干任务.从时刻0开始,这些任务被分批加工,第i个任务单独完成所需的时间是Ti.在每批任务开始 ...

  9. 洛谷 P2365 任务安排【dp】

    其实是可以斜率优化的但是没啥必要 设st为花费时间的前缀和,sf为Fi的前缀和,f[i]为分组到i的最小花费 然后枚举j转移,考虑每次转移都是把j到i分为一组这样意味着j及之后的都要增加s的时间,同时 ...

随机推荐

  1. Native memory allocation (mmap) failed to map xxx bytes for committing reserved memory

    遇到问题 在服务器上运行 nexus 出现Native memory allocation (mmap) failed to map 838860800 bytes for committing re ...

  2. H3C 基本ACL

  3. 【codeforces 764C】Timofey and a tree

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  4. git checkout简介

    原文: http://web.mit.edu/~thefred/MacData/afs/sipb/project/git/git-doc/git-checkout.html  git checkout ...

  5. easyui—window在vue-element-ui中的使用(坑)

    自己给自己挖的坑 !!! 项目中,布局外层使用easyui框架中的window;内部显示内容的table使用element-ui框架,需求将window使用border-image作为边框,之后发现拉 ...

  6. 2019-8-31-C#-控制台使用-UAC-权限

    title author date CreateTime categories C# 控制台使用 UAC 权限 lindexi 2019-08-31 16:55:58 +0800 2018-07-05 ...

  7. 【NOIP数据结构专项】单调队列单调栈

    [FZYZ P1280 ][NOIP福建夏令营]矩形覆盖 Description 有N个矩形,矩形的底边边长为1,且均在X轴上,高度给出,第i个矩形的高为h[i],求最少需要几个矩形才能覆盖这个图形. ...

  8. com.netflix.discovery.DiscoveryClient : Completed shut down of DiscoveryClient

    启动报错:com.netflix.discovery.DiscoveryClient    : Completed shut down of DiscoveryClient 解决方案: 添加web主件 ...

  9. 利用Aspose.cells 将查询出的数据导出为excel,并在浏览器中下载。

    正题前的唠叨 本人是才出来工作不久的小白菜一颗,技术很一般,总是会有遇到一些很简单的问题却不知道怎么做,这些问题可能是之前解决过的.发现这个问题,想着提升一下自己的技术水平,将一些学的新的‘好’东西记 ...

  10. Team Foundation Server 2015使用教程【7】:权限为读取器的团队成员连接tfs及checkin操作