SSL2798 2017年10月27日提高组 软件开发(二分+dp)

32 篇文章 0 订阅

2017年10月27日提高组 软件开发

Description

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

Input

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

Output

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

分析:我们二分答案,设答案为mid,f[i][j] 表示前i个人完成了第一个软件的j个模块,此时还可以完成第二个软件的最多模块数。设第i个人要完成k个模块,那么前i-1个人完成了j-k个模块。完成第二个软件的模块数为(mid−k∗d1i)/d2i.
那么方程出来了:
f[i][j]=max(f[i][j],f[i−1][j−k]+(mid−k∗a[i])/b[i])
那么判断是否合法,就比较f[n][m]与m的大小,如果f[n][m]≥m则说明可行。

代码

#include <cstdio>
#include <cstring>
#define maxn 150
using namespace std;

int f[maxn][maxn],a[maxn],b[maxn];
int ans,n,m;

int max(int x,int y)
{
    return x>y?x:y;
}

bool check(int x)
{
    for (int i=0;i<=n;i++)
        for (int j=0;j<=m;j++)
            f[i][j]=-123456789;
    f[0][0]=0;
    for (int i=1;i<=n;i++)
        for (int j=0;j<=m;j++)
            for (int k=0;k<=x/a[i];k++)
                if (k<=j) 
                {
                    int s=(x-k*a[i])/b[i];
                    f[i][j]=max(f[i][j],f[i-1][j-k]+s);
                }
                else break;
    return f[n][m]>=m;
}

int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
        scanf("%d%d",&a[i],&b[i]);
    int l=1,r=20000;
    while (l<r)
    {
        int mid=(l+r)/2;
        if (check(mid)) 
        {
            ans=mid;
            r=mid;
        }
        else l=mid+1;
    }
    printf("%d",l);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值