题意:软件公司接了两个项目,来自同一个合同,要一起交付。该公司有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. zookeeper(二): Curator vs zkClient

    目录 zookeeper Curator zkClient 客户端对比 写在前面 1.1. zookeeper应用开发 1.1.1. ZkClient简介 1.1.2. Curator简介 写在最后 ...

  2. CSS 布局实例系列(二)如何通过 CSS 实现一个左边固定宽度、右边自适应的两列布局

    最近在百度 IFE 训练营中看见的一道题目: 用两种不同的方法来实现一个两列布局,其中左侧部分宽度固定.右侧部分宽度随浏览器宽度的变化而自适应变化  个人总结出如下三种实现思路: 通过绝对定位实现 S ...

  3. 页游手游服务器(五)sql缓存层

    sql的通用缓存,是实现最麻烦的一部分,对于查询结果的缓存,主要有如下的结构来缓存: cache tablename--player statement--select * from player w ...

  4. android ui篇 自己写界面

    对于一些较为简单的界面则自己进行写. 在这里就需要了解xml文件中一些基本的属性以及android手机的知识. 一.目前手机屏幕像素密度基本有5种情况.(以下像素密度简称密度) 密度 ldpi mdp ...

  5. (转)ubuntu 12.04搭建Adobe Flash Media Server服务

    破解版传送门:http://fms45.cuplayer.com/fms4download.html 福利:1462-5247-1705-7678-8379-5590 下载解压 cd进目录,./ins ...

  6. androidAndroid开发学习--Ionic+Cordova 环境搭建

    我们看 Ionic 能给我们提供什么?  一个样式库,你可以使用它 来 装饰你的 HTML 网页 ,看起来 想 移动程序的 界面,什么 header .content.footer.grid.list ...

  7. shell基础part1

    shell基础一 一.什么是shell shell是个功能强大的编程语言,也是个解释执行的脚本语言(命令解释器). 二.shell分类 1.bourne shell (包括sh.ksh.Bash.ps ...

  8. 【七】MongoDB管理之分片集群介绍

    分片是横跨多台主机存储数据记录的过程,它是MongoDB针对日益增长的数据需求而采用的解决方案.随着数据的快速增长,单台服务器已经无法满足读写高吞吐量的需求.分片通过水平扩展的方式解决了这个问题.通过 ...

  9. Python问题解决记录

    Python如何进行中文注释:网址 解决Python UnicodeEncodeError: 'ascii' codec can't encode: 网址1.网址2.网址3 Python 字符串转换为 ...

  10. UOJ278 【UTR #2】题目排列顺序

    本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/转载请注明出处,侵权必究,保留最终解释权!   题目链接: http://uoj.ac/co ...