Light OJ 1180 Software Company (二分+DP)

来源:互联网 发布:萧井陌 编程入门指南 编辑:程序博客网 时间:2024/06/14 23:31

题意:有两个任务A,B,每个任务可以分成相同且独立的m个子任务。有n个员工,第i个员工完成A的一个子任务的时间是a[i],完成B的一个子任务的时间是b[i]。求完成所有任务所需要的最短时间。

解析:首先想到了二分时间,判断在规定时间内是否能完成任务。但是怎么判断,想了好久,最后还是参考了别人的想法。

每一个人是独立的,每一个小任务也是独立的,对于员工i来说,可以完成x个A的任务,并完成y个B的任务(a[i]*x+b[i]*y<=T)

这样一来,我们设dp[i][j]为考虑前i个人并完成j个A任务时最多能完成多少B任务。

转移方程:dp[i][j] = max(dp[i-1][j-k]+(T-k*a[i])/b[i]).


[code]:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int n,m,a[105],b[105],dp[105][105];bool sol(int x){    int i,j,k,bound;    memset(dp,-1,sizeof(dp));    dp[0][0] = 0;    for(i = 1;i <= n;i++){        bound = x/a[i];        for(j = 0;j <= m;j++){            for(k = 0;k <= j&&k <= bound;k++){                if(dp[i-1][j-k]==-1) continue;                dp[i][j] = max(dp[i][j],dp[i-1][j-k]+(x-k*a[i])/b[i]);            }        }    }    return dp[n][m]>=m;}int main(){    int i,j,cas;    scanf("%d",&cas);    for(int T=1;T<=cas;T++){        scanf("%d%d",&n,&m);        for(i = 1;i <= n;i++) scanf("%d%d",&a[i],&b[i]);        int lb,rb,mid;        lb = 0,rb = 50001;        while(rb-lb>1){            mid = (lb+rb)>>1;            if(sol(mid)) rb = mid;            else lb = mid;        }        printf("Case %d: %d\n",T,rb);    }    return 0;}


0 0
原创粉丝点击