题目描述

一个软件开发公司同时要开发两个软件,并且要同时交付给用户,现在公司为了尽快完成这一任务,将每个软件划分成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;
char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') w=-1,ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+ch-48,ch=getchar();
return x*w;
}
int lft[2]; //还有多少模块要完成
int a1[1000],a2[1000];
int mid,n,m;
char f[110][110][110];
bool chek(int cnt) { //cnt--人
if (f[cnt][lft[1]][lft[2]]) return false; //表示前cnt个人 剩下lef[1] 和lef[2]时不可行
if (cnt==n) {
if (lft[1]*a1[cnt]+lft[2]*a2[cnt] <= mid)
return true;
else {
f[cnt][lft[1]][lft[2]]=true;
return false;
}
}
for (re i=0;i*a1[cnt]<=mid&&i<=lft[1];i++) {
int j=(mid-i*a1[cnt])/a2[cnt]; //可做的a2数
if (j>lft[2]) j=lft[2];
lft[1]-=i;
lft[2]-=j;
if (chek(cnt+1)) return true;
lft[1]+=i;
lft[2]+=j;
}
f[cnt][lft[1]][lft[2]] = true;
return false;
} int main() {
freopen("T21331.in","r",stdin);
freopen("T21331.out","w",stdout);
n=read(),m=read();
for (re i=1;i<n+1;i++){
a1[i]=read();
a2[i]=read();
}
if (n == 1) { printf("%d",m*a1[1]+m*a2[1]); return 0; }
int cnt=0;
int r=min(max(m*a1[2],m*a2[1]),max(m*a1[1],m*a2[2]));
int ans=0x7f7f7f7f;
while (cnt<=r) {
mid=(cnt+r)>>1;
lft[1]=m;
lft[2]=m;
memset(f,0,sizeof f);
if (chek(1)){
ans=min(mid,ans);
ans = mid;
r=mid-1;
}
else cnt=mid+1;
}
printf("%d",ans);
return 0;
}

搜索

#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#define re register int
using namespace std;
const int inf=2147483647;
const int N=110;
inline int read(){
int x=0,w=1;
char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') w=-1,ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+ch-48,ch=getchar();
return x*w;
}
int f[N][N],d[N][2],n,m,t;
int main() {
freopen("T21331.in","r",stdin);
freopen("T21331.out","w",stdout);
re i,j,k;
n=read(),m=read();
for(i=1;i<=n;++i) d[i][0]=read(),d[i][1]=read();
int l=0,r=100000;
int mid;
while (l<r) {
mid=(l+r)>>1;
for(i=0;i<=n;++i) for(j=0;j<=m;++j) f[i][j]=-inf;
f[0][0]=0;
for(i=1;i<=n;++i)
for(j=0;j<=m;++j)
for(k=0;k<=min(j,mid/d[i][0]);++k)
f[i][j]=max(f[i][j],f[i-1][j-k]+(mid-d[i][0]*k)/d[i][1]);
if(f[n][m]>=m) r=mid;
else l=mid+1;
}
printf("%d",l);
return 0;
}

dp

【题解】SOFTWARE 二分+搜索/dp的更多相关文章

  1. Poj 1973 Software Company(二分+并行DP)

    题意:软件公司接了两个项目,来自同一个合同,要一起交付.该公司有n个程序猿来做这两个项目A和B,每个项目都被分为m个子项目,给定每个程序猿做一个A中的子项目需要的时间Xi秒,和做B中的子项目所需时间Y ...

  2. 【题解】hdu 3586 Information Disturbing 二分 树形dp

    题目描述 Information DisturbingTime Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java ...

  3. (四连测)滑雪场的高度差题解---二分 + 搜索---DD(XYX)​​​​​​​的博客

    滑雪场的高度差 时间限制: 1 Sec  内存限制: 128 MB 题目描述 滑雪场可以看成M x N的网格状山地(1 <= M,N <= 500),每个网格是一个近似的平面,具有水平高度 ...

  4. 8VC Venture Cup 2016 - Final Round D. Preorder Test 二分 树形dp

    Preorder Test 题目连接: http://www.codeforces.com/contest/627/problem/D Description For his computer sci ...

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

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

  6. CF360B Levko and Array (二分查找+DP)

    链接:CF360B 题目: B. Levko and Array time limit per test 2 seconds memory limit per test 256 megabytes i ...

  7. HDU 5682 zxa and leaf 二分 树形dp

    zxa and leaf 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5682 Description zxa have an unrooted t ...

  8. hihocoder #1301 : 筑地市场 二分+数位dp

    #1301 : 筑地市场 题目连接: http://hihocoder.com/problemset/problem/1301 Description 筑地市场是位于日本东京都中央区筑地的公营批发市场 ...

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

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

随机推荐

  1. 那些在GitHub能提高你的编程技能的项目

    1.免费的编程书籍 免费的开发手册 167K Repo:github.com/EbookFoundation/free-programming.. 2. 很棒的话题 包含了各种有趣的话题 148k R ...

  2. JVM核心技术(第一篇)

    目录 Java基础知识 一. 字节码技术 二.JVM类加载器 类的加载时机 三.JVM内存结构 四.JVM启动参数 4.1 系统属性参数 4.2 运行模式 4.3 堆内存 4.4 GC相关 4.5 分 ...

  3. raft协议

    一.Raft一致性算法 Eureka:Peer To Peer,每个节点的地位都是均等的,每个节点都可以接收写入请求,每个节点接收请求之后,进行请求打包处理,异步化延迟一点时间,将数据同步给 Eure ...

  4. MySQL分区表最佳实践

    前言: 分区是一种表的设计模式,通俗地讲表分区是将一大表,根据条件分割成若干个小表.但是对于应用程序来讲,分区的表和没有分区的表是一样的.换句话来讲,分区对于应用是透明的,只是数据库对于数据的重新整理 ...

  5. 【BUAA软工】Visual Lab Online——功能规格说明书

    项目 内容 班级:北航2020春软件工程 博客园班级博客 作业:明确和撰写软件的功能规格说明书 功能规格说明书 当前版本:v1.0 修订历史: 版本号 修订时间 修订说明 v1.0 2020/04/0 ...

  6. 解决nohup: 忽略输入并把输出追加到"nohup.out"或者nohup: 忽略输入重定向错误到标准输出端

    nohup启动脚本的时候,没有指定输出路径,默认使用当前目录的nohup.out 例如下面这句就是默认使用nohup.out作为输出文件: nohup script.sh & 改成下面的,则/ ...

  7. 回车与换行的区别:CRLF、CR、LF

    引言 以下是 MySQL 8 导出数据的窗口,导出数据时需要选择记录分隔符,这就需要你明白 CRLF.CR 和 LF 分别代表什么,有何区别,否则可能导出数据会出现莫名其米的问题. 名词解释 CR:C ...

  8. PHP相关session的知识

    由于http协议是一种无状态协议,所以没有办法在多个页面间保持一些信息.例如,用户的登录状态,不可能让用户每浏览一个页面登录一次.session就是为了解决一些需要在多页面间持久保持一种状态的机制.P ...

  9. C语言关于指针函数与函数指针个人理解

    1,函数指针 顾名思义,即指向函数的指针,功能与其他指针相同,该指针变量保存的是所指向函数的地址. 假如是void类型函数指针定义方式可以是 void (*f)(参数列表);亦可以先用 typedef ...

  10. JMeter36个内置函数及11个新增函数介绍

    JMeter内置了36个函数,这些函数可以通过函数助手进行编辑和测试.了解这些函数,不仅能提高JMeter的使用熟练度,也有助于知晓测试工具或测试框架通用的函数有哪些,在自主设计时,作为参考借鉴. J ...