题目描述

一个软件开发公司同时要开发两个软件,并且要同时交付给用户,现在公司为了尽快完成这一任务,将每个软件划分成\(m\)个模块,由公司里的技术人员分工完成,每个技术人员完成同一软件的不同模块的所用的天数是相同的,并且是已知的,但完成不同软件的一个模块的时间是不同的,每个技术人员在同一时刻只能做一个模块,一个模块只能由一个人独立完成而不能由多人协同完成。一个技术人员在整个开发期内完成一个模块以后可以接着做任一软件的任一模块。写一个程序,求出公司最早能在什么时候交付软件。

输入

输入文件第一行包含两个由空格隔开的整数\(n\)和\(m\)。

接下来的\(n\)行每行包含两个用空格隔开的整数\(d_1\)和\(d_2\),\(d_1\)表示该技术人员完成第一个软件中的一个模块所需的天数,\(d_2\)表示该技术人员完成第二个软件中的一个模块所需的天数。

输出

输出文件仅有一行包含一个整数\(d\),表示公司最早能于\(d\)天后交付软件。

输入样例

1 1
2 4
1 6

输出样例

18

提示

数据规模

对于100%的数据,\(1≤n≤100,1≤m≤100,1≤d_1,d_2≤100\)。

样例说明

最快的方案是第一个技术人员完成第二个软件的\(18\)个模块,用时\(18\)天,第三个技术人员完成第一个软件的\(18\)个模块,用时\(18\)天,其余的模块由第二个技术人员完成,用时\(12\)天,做完所有的模块需要\(18\)天。如果第一个技术人员完成第二个软件的\(17\)个模块,第三个技术人员完成第一个软件的\(17\)个模块,其余的模块由第二个技术人员完成,需要用时\(18\)天,做完所有模块仍然需要\(18\)天,所以少于\(18\)天不可能做完所有模块。

思路

这个完成天数可能否完成存在一个线性关系,所以这肯定是到二分答案的题目。问题在于如何进行判断能否完成。

首先假设 \(f_{i,j}\)表示到第\(i\)个技术人员的时候,第一个软件已经完成了\(j\)个模块,第二个软件可以完成的模块数量。先给出状态转移方程

\[f_{i,j}=\underset{0\le k \le min{\left [\frac{day}{d_{1,i}}\right ] }}{\text max} \left \{ f_{i-1,j-k}+\left [ \frac{day-k\times d_{1,i}}{d_{2,i}} \right ] \right \}
\]

其中\(day\)表示二分的天数,\(k\)表示\(i\)个人抽出做程序1去做程序2的时间。

最终如果\(f_m\ge m\),那么就可以在 \(day\) 天完成这两个项目。

时间复杂度为 \(O(n\times m^2 \times log m)\)

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std; const int N = 102; int d1[N];
int d2[N]; int n, m; int f[N]; inline bool check(int day)
{
f[0] = 0;
for (int i = 1; i <= m; i++)
f[i] = -1e9; //要保证 程序1 的 i个模块一定做的完,那就让 做 程序1 的 i个模块 时 程序2 什么都不要做
for (int i = 1; i <= n; i++) //枚举每个人
for (int j = m; j >= 0; j--) //能够完成 软件1 m个模块时候
for (int k = 0; k <= min(day / d1[i], j); k++) //现在第i个人选择抽出做 软件1 k个模块的时间,来做 软件2
f[j] = max(f[j], f[j - k] + (day - d1[i] * k) / d2[i]);
return f[m] >= m; //程序1 做 m个模块的时候,程序2 也至少能完成任务
} int main()
{
int l = 1, r = 0;
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++)
{
scanf(" %d %d", &d1[i], &d2[i]);
r = max(r, m * d1[i]);
r = max(r, m * d2[i]);
}
while (l < r)
{
int mid = l + r >> 1;
if (check(mid))
r = mid;
else
l = mid + 1;
}
printf("%d", r);
return 0;
}

[一本通1677/JZOJ1217/CJOJ1101]软件开发 题解的更多相关文章

  1. 【BZOJ】1221: [HNOI2001] 软件开发(最小费用最大流)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1221 先吐槽一下,数组依旧开小了RE:在spfa中用了memset和<queue>的版本 ...

  2. [HNOI 2001]软件开发

    Description 某软件公司正在规划一项n天的软件开发计划,根据开发计划第i天需要ni个软件开发人员,为了提高软件开发人员的效率,公司给软件人员提供了很多的服务,其中一项服务就是要为每个开发人员 ...

  3. bzoj 1221 [HNOI2001] 软件开发 费用流

    [HNOI2001] 软件开发 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1938  Solved: 1118[Submit][Status][D ...

  4. 【bzoj1221】[HNOI2001] 软件开发 费用流

    题目描述 某软件公司正在规划一项n天的软件开发计划,根据开发计划第i天需要ni个软件开发人员,为了提高软件开发人员的效率,公司给软件人员提供了很多的服务,其中一项服务就是要为每个开发人员每天提供一块消 ...

  5. BZOJ1221 [HNOI2001] 软件开发 【费用流】

    题目 某软件公司正在规划一项n天的软件开发计划,根据开发计划第i天需要ni个软件开发人员,为了提高软件开发人员的效率,公司给软件人员提供了很多的服务,其中一项服务就是要为每个开发人员每天提供一块消毒毛 ...

  6. BZOJ 1221 [HNOI2001] 软件开发 费用流_建模

    题目描述:   某软件公司正在规划一项n天的软件开发计划,根据开发计划第i天需要ni个软件开发人员,为了提高软件开发人员的效率,公司给软件人员提供了很多的服务,其中一项服务就是要为每个开发人员每天提供 ...

  7. nw.js桌面软件开发系列 第0.1节 HTML5和桌面软件开发的碰撞

    第0.1节 HTML5和桌面软件开发的碰撞 当我们谈论桌面软件开发技术的时候,你会想到什么?如果不对技术本身进行更为深入的探讨,在我的世界里,有这么多技术概念可以被罗列出来(请原谅我本质上是一个Win ...

  8. 敏捷软件开发VS传统软件工程

    敏捷软件开发:又称敏捷开发,是一种从1990年代开始逐渐引起广泛关注的一些新兴软件开发方法,是一种应对快速变化的需求的一种软件开发能力. 与传统软件工程相比,它们的具体名称.理念.过程.术语都不尽相同 ...

  9. Atitit.软件开发的三层结构isv金字塔模型

    Atitit.软件开发的三层结构isv金字塔模型 第一层,Implements 层,着重与功能的实现.. 第二次,spec层,理论层,设计规范,接口,等.流程.方法论 顶层,val层,价值观层,原则, ...

  10. BZOJ 1221: [HNOI2001] 软件开发

    1221: [HNOI2001] 软件开发 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1428  Solved: 791[Submit][Stat ...

随机推荐

  1. itsdangerous模块的使用

    简介 生成临时身份令牌(通过邮件让用户注册激活的时候地址当中带有用户的信息.但是信息一般都是敏感信息,而且还想让它具有时效性,所以就可以选择itsdangerous模块 官网:https://itsd ...

  2. go最新版本1.15安装配置及编辑器2020.2版本goland

    下载 https://golang.google.cn/dl/ 配置 go env #查看是否安装成功 # 终端输入修改镜像地址 $ go env -w GO111MODULE=on $ go env ...

  3. Taurus.MVC WebMVC 入门开发教程6:路由配置与路由映射

    前言: 在本篇 Taurus.MVC WebMVC 入门开发教程的第六篇文章中, 我们将讨论如何配置路由并映射到控制器和操作方法. 路由是决定应用程序如何响应客户端请求的重要组成部分,因此在 Web ...

  4. uniapp同步将本地图片转换为base64,支持微信、H5、APP

    接上篇,少了一个方法的源代码. 先上代码: ploadFilePromiseSync = (url) => { return new Promise((resolve, reject) => ...

  5. adb monkey 有哪些参数?

    adb monkey 是 Android Debug Bridge (ADB) 工具中的一个命令,用于执行随机事件来对 Android 应用进行压力测试.以下是 adb monkey 命令的一些常用参 ...

  6. 如何提取html中的token?

    通过正则表达式提取(适用于提取文本结果): Re.seach()提取一个值,通过下标取值 Re.findall()提取多个值,通过下标取值 Resp= reques.get(url);print(re ...

  7. [学习笔记]在CentOS7中用Docker方式安装Jenkins

    @ 目录 原理: 创建Docker网桥网络 安装DinD 创建镜像 构建镜像 运行容器 原理: Docker in Docker (以下简称 DinD)可以在 Container 中直接运行一个 Do ...

  8. Zabbix“专家坐诊”第186期问答汇总

    问题一 Q:这两个键值vm.memory.size[pused]和vm.memory.util监控内存使用率有什么区别,使用那个监控使用率更好,支持windows系统和Linux系统么,对agent端 ...

  9. linux 服务器 执行命令挂起 nohup 改用 pm2

    nohup http-server -p 80 & nohup完要 exit 退出,不能直接关! nohup完要 exit 退出,不能直接关! nohup完要 exit 退出,不能直接关! 重 ...

  10. 【深度学习基础】基于Numpy的循环神经网络实现和反向传播训练

    本文是<深度学习进阶:自然语言处理>.<神经网络与深度学习>和<动手学深度学习>的读书笔记.本文将介绍基于Numpy的循环神经网络的前向传播和反向传播实现,包括RN ...