软件开发

来源:互联网 发布:最美古诗词 知乎 编辑:程序博客网 时间:2024/04/27 15:20

Description

小沐的软件开发公司同时要开发两个软件,并且要同时交付给用户。为了尽快完成这一任务,他将每个软件划分成m 个模块,由公司里的技术人员分工完成。 

每个技术人员完成同一软件的不同模块的所用的天数是相同的,并且是已知的,但完成不同软件的一个模块的时间是不同的,每个技术人员在同一时刻只能做一个模块,一个模块只能由一个人独立完成而不能由多人协同完成。一个技术人员在整个开发期内完成一个模块以后可以接着做任一软件的任一模块。小沐请你帮忙写一个程序计算应怎样分配每个技术人员的任务,才能让这两个软件的交付时间尽量早。

Input

第一行包含两个由空格隔开的整数n 和m,其中1≤n≤100,1≤m≤100。 
接下来的 n 行每行包含两个用空格隔开的正整数a 和b,其中第i+1 行的a 表示技术人员i 完成第一个软件中的一个模块所需的天数,b 表示该技术人员完成第二个软件中的一个模块所需的天数,其中l≤a,b≤100。

Output

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

Sample Input

3 201 12 41 6

Sample Output

18

Hint

【输入输出样例说明】 
最快的方案是第一个技术人员完成第二个软件的18 个模块,用时18 天,第三个技术人员完成 
第一个软件的18 个模块,用时18 天,其余的模块由第二个技术人员完成,用时12 天,做完所有模 
块需要18 天。 
如果第一个技术人员完成第二个软件的17 个模块,第三个技术人员完成第一个软件的17 个模 
块,其余的模块由第二个技术人员完成,需要用时18 天,做完所有模块仍然需要18 天,所以少于 
18 天不可能做完所有模块。 
【数据范围】 
对于 30%的数据:1≤n≤10,1≤m≤10 
对于50%的数据:1≤n≤50,1≤m≤50 
对于100%的数据,1≤n≤100,1≤m≤100,l≤a,b≤100


【分析】

        官方题解

二分穷举d,每穷举一个d,用动态规划进行验证:

:f(i,j)=i个人在d天内完成软件1j个模块后,还能最多完成软件2的模块数

则状态转移方程为:

f(i,j)=MAX{f(i-1,j-x)+(d-x*a[i])/b[i] | 0<=x<=d/a[i] && x<=j }

    那么,如果f(n,m)>=m则说明d可行,否则d不可行!

时间复杂度:O(n*m*m*log2(ans))


【代码】

#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<ctime>#include<iostream>#include<algorithm>using namespace std;const int MAX_ANS=20000;const int INF=999999999;int N,M;int a[105],b[105],f[105][105];void _init(){scanf("%d%d",&N,&M);for(int i=1;i<=N;i++)    scanf("%d%d",&a[i],&b[i]);}bool _can_match(int d)         //DP验证 {for(int i=0;i<=N;i++)      //注意这两个初值     for(int j=0;j<=M;j++)        f[i][j]=-INF;for(int i=0;i*a[1]<=d;i++)    f[1][i]=(d-a[1]*i)/b[1];for(int i=2;i<=N;i++)    for(int j=0;j<=M;j++)        for(int x=0;x*a[i]<=d&&x<=j;x++)            f[i][j]=max(f[i][j],f[i-1][j-x]+(d-x*a[i])/b[i]);return (f[N][M]>=M);}void _solve(){int Left=0,Right=MAX_ANS,Mid,ans;while(Left<=Right)         //二分 {Mid=(Left+Right)>>1;if(_can_match(Mid)){ans=Mid;Right=Mid-1;}else    Left=Mid+1;}printf("%d\n",ans);}int main(){_init();_solve();return 0;}


原创粉丝点击