题意:软件公司接了两个项目,来自同一个合同,要一起交付。该公司有n个程序猿来做这两个项目A和B,每个项目都被分为m个子项目,给定每个程序猿做一个A中的子项目需要的时间Xi秒,和做B中的子项目所需时间Yi秒,问最短需要多少时间可以完成这两项工程。

分析:显然同一时刻不同的工人可以一起工作,那么面临的问题也就是一个工作的分配,让某一时刻的某个工人干A还是干B,来使AB尽快都完成。刚始做的时候确实没有什么头绪,后来看了大牛们的解题报告,大多是二分时间判断再加上并行DP来解决这个问题。但是仔细分析的好像特别少,想我这种菜鸟真是看不懂。隔了两天,还是硬着头皮开始一步步分析他们的思路。

题解:二分时间呢,就是枚举时间,然后验证看看在这个时间内能否完成这两个项目。如果满足就用二分法进一步缩小范围,直到求得最精确地结果。这里也涉及到一个时间上限的问题,大家都知道,二分法在初始的时候有下限和上限两个值,下限很简单就设为1,上限要看题目的要求和测试数据的强弱了。这道题呢,上限设为30000就可以通过了,但是这里还是用动态获得上限为好。也就是根据输入数据求得上限,这个上限就是完成这两个项目的最长时间,那么我们可以求得所有程序猿中完成单个子项目的最大值Max,再乘以子项目的总数2m就是粗略的上限了。这里还可以优化,因为我们求得是最短的时间,肯定大大低于这个上限。如Max
/ (n+1) *2m。

还有一个就是DP的状态转移方程的确定了,首先,dp[ i ][ j ]表示前 i 个人在完成 j 个A子项目时最多能完成的B子项目的个数,最后只要判断dp[n][m]是否大于m就可以了,如果大于则满足要求,小于则不行。状态转移方程 为 dp[ i ][ j ] = max(dp[ i ][ j ], dp[ i-1 ][ j-k ] + (time-k * x[i] ) / y[i] );这个方程呢,之前一直没有理解,就是因为没有意识到这个是并行的运算。有句话说的好“时间对每个人都是公平的”,在这里也是一样,每个程序猿都有一个time,他可以选择在这个时间里做多少个A子项目和多少个B子项目,使得开发的进度满足公司的整体需求。这个转换方程求得是前
i 个人完成了j个A项目时,最多能完成的B子项目 。那么这就取决于第 i 个人的选择,如果第 i 个人完成 k 个A子项目,那么前 i-1 个人就应该完成了 j-k个A子项目。然而谁也不知道这个该死的第 i 个程序猿会做多少个A子项目啊,所以我们只能从0到m假设他做的A子项目,从中找到最短的时间。然后再告诉他应该做的确切的个数,服从公司的整体需求。这个问题用到了一个子循环可以解决。这里还可以有一个优化,在给定的时间下第 i 个程序猿可能做不了m个A子项目,最多只能做Time/a[i]个。

这里还有一个很重要的优化,就跟0-1背包的空间优化差不多。0-1背包时,把二维的dp数组用一维数组实现了,这里可以参照这种方法,用一维数组实现dp.

import java.util.Scanner;

public class Main{
static int N =102;
static int[] a=new int[N];
static int[] b=new int[N];
static int[] dp=new int[N];
static int n,m;
static boolean judge(int time){
for(int i=0;i<N;i++){
dp[i]=-1;
}
dp[0]=0;
for(int i=0;i<n;i++){
for(int j=m;j>=0;j--)
if(dp[j] != -1){
for(int k=m;k>=0;k--){
if(a[i]*k <= time && j+k <= m)
dp[j+k]=Math.max(dp[j+k],dp[j]+(time-a[i]*k)/b[i]);
}
}
}
return dp[m] >= m;
} public static void main(String args[]){
Scanner sc=new Scanner(System.in);
int cas=sc.nextInt();
while(cas--!=0){
n=sc.nextInt();
m=sc.nextInt();
int max_time=-1;
for(int i=0;i<n;i++){
a[i]=sc.nextInt();
b[i]=sc.nextInt();
max_time=Math.max(max_time,a[i]);
max_time=Math.max(max_time,b[i]);
}
max_time=max_time*m*2;
int left,right,mid;
int min_time=0;
left=1;
right=max_time;
while(left <= right){
mid=(left+right)>>1;
if(judge(mid)){
right=mid-1;
min_time=mid;
}
else
left=mid+1;
}
System.out.println(min_time);
}
}
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

Poj 1973 Software Company(二分+并行DP)的更多相关文章

  1. 二分+动态规划 POJ 1973 Software Company

    Software Company Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 1112   Accepted: 482 D ...

  2. 任务调度分配题两道 POJ 1973 POJ 1180(斜率优化复习)

    POJ 1973 这道题以前做过的.今儿重做一次.由于每个程序员要么做A,要么做B,可以联想到0/1背包(谢谢N巨).这样,可以设状态 dp[i][j]为i个程序员做j个A项目同时,最多可做多少个B项 ...

  3. POJ3208 Apocalypse Someday(二分 数位DP)

    数位DP加二分 //数位dp,dfs记忆化搜索 #include<iostream> #include<cstdio> #include<cstring> usin ...

  4. 搜索+剪枝 POJ 1416 Shredding Company

    POJ 1416 Shredding Company Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 5231   Accep ...

  5. POJ 3216 Repairing Company(最小路径覆盖)

    POJ 3216 Repairing Company id=3216">题目链接 题意:有m项任务,每项任务的起始时间,持续时间,和它所在的block已知,且往返每对相邻block之间 ...

  6. POJ-2018 Best Cow Fences(二分加DP)

    Best Cow Fences Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 10174 Accepted: 3294 Desc ...

  7. 【bzoj5174】[Jsoi2013]哈利波特与死亡圣器 二分+树形dp

    题目描述 给你一棵以1为根的有根树,初始除了1号点为黑色外其余点均为白色.Bob初始在1号点.每次Alice将其中至多k个点染黑,然后Bob移动到任意一个相邻节点,重复这个过程.求最小的k,使得无论B ...

  8. poj - 1953 - World Cup Noise(dp)

    题意:n位长的01序列(0 < n < 45),但不能出现连续的两个1,问序列有多少种. 题目链接:id=1953" target="_blank">h ...

  9. BZOJ_1044_[HAOI2008]木棍分割_二分答案+DP+单调队列

    BZOJ_1044_[HAOI2008]木棍分割_二分答案+DP Description 有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个 ...

随机推荐

  1. Go 学习笔记

    官网: https://golang.org/ 环境: $GOROOT: GOROOT环境变量指定了Go的安装目录. $GOPATH: GOPATH 环境变量指定workspace的目录. 命令行: ...

  2. Java语言实现简单FTP软件------>源码放送(十三)

    Java语言实现简单FTP软件------>FTP协议分析(一) Java语言实现简单FTP软件------>FTP软件效果图预览之下载功能(二) Java语言实现简单FTP软件----- ...

  3. windows7下cmd命令窗口没有滚动条的解救方法

    由于昨天的好123问题没有解决,我想查看一下本机的ip地址等,于是打开了cmd窗口,输入ipconfig/all命令进行查看,但是发现出现了下面的窗口,无法进行滚动,完全无法查看详细的信息. 然后我百 ...

  4. HDU 4513 吉哥系列故事――完美队形II(Manacher)

    题目链接:cid=70325#problem/V">[kuangbin带你飞]专题十六 KMP & 扩展KMP & Manacher V - 吉哥系列故事――完美队形I ...

  5. git push问题 objects/pack/tmp_pack_XXXXXX': Permission denied

    1.上传时的权限问题 在执行git push origin master之后,上传过程中报出如下错误: objects/pack/tmp_pack_XXXXXX': Permission denied ...

  6. delete 和 truncate 的 区别

    如果要清空表中的所有记录,可以使用下面的两种方法: DELETE FROM table1     TRUNCATE TABLE table1 以下 为之区别: 1)执行速度和灵活性    trunca ...

  7. RLearning第1弹:初识R语言

    R作为一种统计分析软件,是集统计分析与图形显示于一体的.体积小.开源.很强的互动性.自从学了R本人就很少再用matlab了... 一.R语言由函数和赋值构成. R使用<-(最好养成使用习惯),而 ...

  8. python3 计算文件夹中所有py文件里面代码行数,注释行数,空行数

    import os,re #代码所在位置 FILE_PATH = './' def analyze_code(codefilesource): ''' 打开一个py文件统计其中的代码行数,包括空格和注 ...

  9. Django中日志管理

    在settings中设置日志的相关信息,然后再逻辑代码区就可以保存相应的信息了 #简单设置: LOGGING = { 'version': 1, 'disable_existing_loggers': ...

  10. [MEF] 学习之一 入门级的简单Demo

    MEF 的精髓在于插件式开发,方便扩展. 我学东西,习惯性的先搞的最简单的Demo出来,看看有没有好玩的东东,然后继续深入.这个博文,不谈大道理,看demo说事儿. 至于概念,请google ,大把大 ...