【题解】SOFTWARE 二分+搜索/dp

本文介绍了如何解决一个软件开发公司的优化问题,即如何在最短时间内完成两个软件的开发。通过二分搜索和动态规划(dp)的方法,确定技术人员分工以尽早交付软件。文章详细阐述了思路,包括二分法和动态规划的实现细节,并提供了输入输出样例和解释。
摘要由CSDN通过智能技术生成

 

题目描述

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

输入输出格式

输入格式:

输入文件第一行包含两个由空格隔开的整数n和m,接下来的n行每行包含两个用空格隔开的整数d1和d2,d1表示该技术人员完成第一个软件中的一个模块所需的天数,d2表示该技术人员完成第二个软件中的一个模块所需的天数。

输出格式:

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

输入输出样例

输入样例#1: 复制

3 20
1 1
2 4
1 6

输出样例#1: 复制

18

说明

1<=n<=100,1<=m<=100。 1<= d1,d2<=100。

思路

  • 最大值最小(要求做得最慢的人越早做完),因此想到二分

dp

  • 设mid天后交付;
  • $f[i][j]$表示当前i个人共完成了j个模块一时,还能完成多少个模块二
  • 设第i个人完成了k个模块一,则在剩下的时间内他还可以完成$(mid-k*d1[i])/d2[i]$个模块二
  • 可以得到转移方程

$$f[i][j]=max(f[i][j],f[i-1][j-k]+((mid-k*d1[i])/d2[i]))$$

  • 最后检验计较$f[n][m]$与m大小(当n个人完成了m个模块一时,能否完成m个模块二)

搜索

    • 设mid天后交付;
    • 按人员编号进行搜索,用lft[0],lft[1]表示还有几个模块一,模块二需要完成
    • 枚举第i个人做了几个模块一,在通过$(mid-k*d1[i])/d2[i]$算出可以在剩下几天内在做几个模块二
    • lft[0],lft[1]分别减去第i个人完成的模块一,二数量=>进行下一个人的搜索
    • 当i=n时,自然剩下所有的未完成的lft[0],lft[1]都要他完成
    • 计算此时$d1[i]*lft[0]+d2*lft[1]$的大小与mid的关系
这个二分的DFS检验其实是可以记忆化的,如果是成功的就直接退出了,但是不成功的没有退出,但是会重复计算,比如前3个人,模块一还剩下3个,模块二剩下4个,这个f(3,3,4)可能由很多的状态扩展过来,因此会有很多重复计算,不过要记得每次检验之前要清空f
  • 可以用$f[cnt][lft[0]][lft[1]]$记下此方案是否可行,下次再搜到就直接return false

代码

#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#define re register int
using namespace std;
inline int read(){
    int x=0,w=1;
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值