任务调度分配题两道 POJ 1973 POJ 1180(斜率优化复习)
POJ 1973
这道题以前做过的。今儿重做一次。由于每个程序员要么做A,要么做B,可以联想到0/1背包(谢谢N巨)。这样,可以设状态
dp[i][j]为i个程序员做j个A项目同时,最多可做多少个B项目。枚举最后一个程序员做多少个A项目进行转移(0/1)。
dp[i][j]=max{dp[i-1][k]+(time-(j-k)*a[i])/b[i]}。于是,二分时间time进行判定即可。
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std; int dp[110][110];
int a[110],b[110];
int n,m; bool slove(int time){
memset(dp,-1,sizeof(dp));
for(int i=0;i<=m;i++){
if(time-i*a[1]<0) continue;
dp[1][i]=(time-i*a[1])/b[1];
}
for(int i=2;i<=n;i++){
for(int j=0;j<=m;j++){
for(int k=0;k<=j;k++){
if(dp[i-1][k]<0||time-(j-k)*a[i]<0) continue;
dp[i][j]=max(dp[i][j],dp[i-1][k]+(time-(j-k)*a[i])/b[i]);
}
}
}
//bool flag=false;
for(int i=0;i<=n;i++){
if(dp[i][m]>=m) return true;
}
return false;
} int main(){
int T;
scanf("%d",&T);
while(T--){
int l=0,r=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d%d",&a[i],&b[i]);
r+=(a[i]*m+b[i]*m);
}
int ans=100000000;
while(l<=r){
int mid=(l+r)>>1;
if(slove(mid)){
ans=mid;
r=mid-1;
}
else l=mid+1;
}
printf("%d\n",ans);
}
return 0;
}
POJ 1180
开始时设了二维的数组。一看范围,就知道不行了。。
可以很容易就看出是DP了。可以倒过来设状态dp[i]表示加入i任务,从i任务到n任务完成所需要的时间。
dp[i]=min{dp[j]+(s+tsum[i]-tsum[j])*fsum[i]}//i之后的第一个分组是从j开始,枚举。
这样还不足够。可以用斜率来优化。假设j<p。如果对于决策i,j更优于p,则有dp[j]+(s+tsum[i]-tsum[j])*fsum[i]<dp[p]+(s+tsum[i]-tsum[j])*fsum[i]。化简有
dp[j]-dp[p]<(tsum[j]-tsum[p])*fsum[i]。可以看到是斜率k=g[j,p]=(dp[j]-dp[p])/(tsum[j]-tsum[p])<fsum[i],j优于p。
对于k<j<p。如果有g[k,j]<g[j,p]。则j必定是可以不要的。因为当g[k,j]<s时,明显k优于j。否则g[k,j]>s,有s<g[k,j]<g[j,p]。说明,k不优于j,j不优于p。
于是,j是可以不要的。
斜率减少。因而可以去掉j。在这里,我们要维护的是斜率的下凸,如:g[k,j]>g[j,p]。这样,对于j点,如果j点可选,则其前面的点均可以不需要了。因为斜率是下凸,会直到某个斜率大于fsum[i],才会选到最优。
用一个单调队列维护即可。
#include <iostream>
#include <cstdio>
#include <algorithm>
#define LL __int64
using namespace std; int t[10010],f[10010];
LL ts[10010],fs[10010];
int que[10010],head,tail;
LL dp[10010]; int main(){
int n,s;
while(scanf("%d",&n)!=EOF){
head=tail=0;
scanf("%d",&s);
for(int i=1;i<=n;i++){
scanf("%d%d",&t[i],&f[i]);
}
dp[n+1]=0; ts[n+1]=fs[n+1]=0;
for(int i=n;i>=1;i--){
ts[i]=(ts[i+1]+t[i]);
fs[i]=(fs[i+1]+f[i]);
}
head=tail=0;
dp[n+1]=0;
que[tail++]=n+1;
dp[n]=(s+ts[n])*fs[n];
que[tail++]=n;
for(int i=n-1;i>=1;i--){
while(head<tail-1&&dp[que[head+1]]-dp[que[head]]<=(ts[que[head+1]]-ts[que[head]])*fs[i])
head++;
dp[i]=dp[que[head]]+(s+ts[i]-ts[que[head]])*fs[i];
while(head+1<tail&&(dp[i]-dp[que[tail-1]])*(ts[que[tail-1]]-ts[que[tail-2]])<=(dp[que[tail-1]]-dp[que[tail-2]])*(ts[i]-ts[que[tail-1]]))
tail--;
que[tail++]=i;
}
printf("%I64d\n",dp[1]);
} return 0;
}
任务调度分配题两道 POJ 1973 POJ 1180(斜率优化复习)的更多相关文章
- POJ P2318 TOYS与POJ P1269 Intersecting Lines——计算几何入门题两道
rt,计算几何入门: TOYS Calculate the number of toys that land in each bin of a partitioned toy box. Mom and ...
- 三分题两道:lightoj1146 Closest Distance、lightoj1240 Point Segment Distance (3D)
lightoj1146 Two men are moving concurrently, one man is moving from A to B and other man is moving f ...
- poj 1180 斜率优化dp
这个题目要是顺着dp的话很难做,但是倒着推就很容易退出比较简单的关系式了. dp[i]=min(dp[u]+(sum[u-1]-sum[i-1]+s)*f[i]);dp[i]代表从i到结尾需要花费的代 ...
- POJ 3709 K-Anonymous Sequence - 斜率优化dp
描述 给定一个数列 $a$, 分成若干段,每段至少有$k$个数, 将每段中的数减少至所有数都相同, 求最小的变化量 题解 易得到状态转移方程 $F_i = \min(F_j + sum_i - su ...
- POJ 1180 斜率优化DP(单调队列)
Batch Scheduling Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 4347 Accepted: 1992 ...
- 穷举(四):POJ上的两道穷举例题POJ 1411和POJ 1753
下面给出两道POJ上的问题,看如何用穷举法解决. [例9]Calling Extraterrestrial Intelligence Again(POJ 1411) Description A mes ...
- 『ACM C++』Virtual Judge | 两道基础题 - The Architect Omar && Malek and Summer Semester
这几天一直在宿舍跑PY模型,学校的ACM寒假集训我也没去成,来学校的时候已经18号了,突然加进去也就上一天然后排位赛了,没学什么就去打怕是要被虐成渣,今天开学前一天,看到最后有一场大的排位赛,就上去试 ...
- 两道人数多,课程少,query多的题
#每天进步一点点# 来两道很相似的题目~ (智商啊智商.....) hihoCoder #1236:Scores (简单的分桶法+bitset) 2015 Beijing Online的最后一题.题目 ...
- FJOI2020 的两道组合计数题
最近细品了 FJOI2020 的两道计数题,感觉抛开数据范围不清还卡常不谈里面的组合计数技巧还是挺不错的.由于这两道题都基于卡特兰数的拓展,所以我们把它们一并研究掉. 首先是 D1T3 ,先给出简要题 ...
随机推荐
- SpringBoot SpringDataJPA 动态查询、多条件查询
Spring-data - JPA用的还是比较多的,之前在公司也一直在用,因为方便.下面我们来整理一下如何配置. pom.xml <?xml version="1.0" en ...
- JavaScript--Date 日期对象
日期对象可以储存任意一个日期,并且可以精确到毫秒数(1/1000 秒). 定义一个时间对象 : var Udate=new Date(); 注意:使用关键字new,Date()的首字母必须大写. 使 ...
- python爬虫之处理验证码
云打码实现处理验证码 处理验证码,我们需要借助第三方平台来帮我们处理,个人认为云打码处理验证码的准确度还是可以的 首先第一步,我们得先注册一个云打码的账号,普通用户和开发者用户都需要注册一下 然后登陆 ...
- Mysql(三):多表查询和存储程序
今天内容: ● 多表查询(内连接 外连接 子查询) ● 存储程序(存储过程 函数) 多表查询 同时从多张数据表中查取到需要的数据即是多表查询. 多表查询时,参与查询的表中每条数据进行组合,这种效果 ...
- 剔除重复jar包,查找重复类
作为程序员,没有遇到过jar包冲突,不是你幸运,就是你还年轻. jar包冲突有着无穷的魔力,一提到就会有说不完的怨愤,道不清的忧伤,这都是内伤.jar 包冲突就像深藏地底的地雷,看上去平常无奇,一切是 ...
- vm装xp安装成功后进入不了系统
1.如果是用虚拟光驱,你肯定步骤是先新建的虚拟机,再安装的虚拟光驱,所以会出现这样的问题.(请先安装虚拟光驱,再新建虚拟机,再用虚拟光驱加载镜像文件,问题解决)2.如果是直接使用的镜像,那么在GHOS ...
- [转]linux实时查看更新日志命令
很多时候在调试生成或正式平台服务器的时候想查看实时的日志输出,在Linux中可以使用tail 或 watch来实现. 比如我们项目中有个 app.log 的日志文件,我们普通读取都使用 vi app. ...
- [文章转载]-我的Java后端书架-江南白衣
我的Java后端书架 (2016年暮春3.0版) 04月 24, 2016 | Filed under 技术 书架主要针对Java后端开发. 3.0版把一些后来买的.看的书添补进来,又或删掉或降级一些 ...
- Gpupdate命令详解
刷新本地和基于 Active Directory 的组策略设置,包括安全设置.该命令可以取代 secedit 命令中已经过时的 /refreshpolicy 选项. MS-DOS命令语法 gpupda ...
- (转)分布式文件存储FastDFS(五)FastDFS常用命令总结
http://blog.csdn.net/xingjiarong/article/details/50561471 1.启动FastDFS tracker: /usr/local/bin/fdfs_t ...