【题目背景】
一个软件开发公司同时要开发两个软件,并且要同时交付给用户,现在公司为了尽快完成这一任务,将每个软件划分成m个模块,由公司里的技术人员分工完成,每个技术人员完成同一软件的不同模块的所用的天数是相同的,并且是已知的,但完成不同软件的一个模块的时间是不同的,每个技术人员在同一时刻只能做一个模块,一个模块只能由一个人独立完成而不能由多人协同完成。一个技术人员在整个开发期内完成一个模块以后可以接着做任一软件的任一模块。写一个程序,求出公司最早能在什么时候交付软件。
【输入格式】
输入文件第一行包含两个由空格隔开的整数n和m,其中1≤n≤100,1≤m≤100。接下来的n行每行包含两个用空格隔开的整数d1和d2,d1表示该技术人员完成第一个软件中的一个模块所需的天数,d2表示该技术人员完成第二个软件中的一个模块所需的天数,其中1≤d1,d2≤100。
【输出格式】
输出文件仅有一行包含一个整数d,表示公司最早能于d天后交付软件。
【样例】
SOFTWARE.IN
3 20
1 1
2 4
1 6
SOFTWARE.OUT
18
【样例解释】
最快的方案是第一个技术人员完成第二个软件的18个模块,用时18天,第三个技术人员完成第一个软件的18个模块,用时18天,其余的模块由第二个技术人员完成,用时12天,做完所有的模块需要18天。如果第一个技术人员完成第二个软件的17个模块,第三个技术人员完成第一个软件的17个模块,其余的模块由第二个技术人员完成,需要用时18天,做完所有模块仍然需要18天,所以少于18天不可能做完所有模块。
曾经做过一个加工生产调度的题 感觉有点像 但死活还是不会做
我个弱b...
到死也没做出来
听了讲解 是二分+DP验证
二分答案想到了 但是不会验证
令f[i][j]表示前i个人做第一个软件j个模块时 可以做第二个软件模块数的最大值
二分时间限制
判断f[时间][模块数]是否大于模块数
如果大于 在l和mid间寻找答案
否则在mid+1和r间寻找答案
dp时注意细节
f[0][0]=0;f[0][1]=-inf;......
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int inf=999999999;
struct self{int x,y;}s[111];
int m,n,mid,l,r,a,b,c;
int ans;
int f[111][111];
int work(int i,int j)
{
if(i<0||j<0)return -inf;
if(f[i][j]!=-1)return f[i][j];
f[i][j]=work(i-1,j)+mid/s[i].y;
for(int a=j-1;a>=0&&s[i].x*(j-a)<=mid;a--)
f[i][j]=max(f[i][j],work(i-1,a)+(mid-s[i].x*(j-a))/s[i].y);
return f[i][j];
}
int main()
{
scanf("%d%d",&m,&n);
for(a=1;a<=m;a++)scanf("%d%d",&s[a].x,&s[a].y);
l=0;r=10000;
while(l<=r)
{
mid=(l+r)>>1;
memset(f,-1,sizeof(f));
f[0][0]=0;
for(a=1;a<=n;a++)f[0][a]=-inf;
work(m,n);
if(f[m][n]>=n)
{
r=mid-1;
ans=mid;
}
else
{
l=mid+1;
}
}
cout<<ans<<'\n';
return 0;
}