GHOJ 1023 软件

题目大意

        一个软件开发公司同时要开发两个软件,并且要同时交付给用户,现在公司为了尽快完成这一任务,将每个软件划分成$m$个模块($1 leq m leq 100$),由公司里的$n$个技术人员分工完成($1 leq n leq 100$)。

        每个技术人员完成同一软件的不同模块的所用的天数是相同的,并且是已知的,但完成不同软件的一个模块的时间是不同的,第$i$个人技术人员完成第一个软件的一个模块的时间为$d1[i]$,完成第二个软件的一个模块的时间为$d2[i]$。

        每个技术人员在同一时刻只能做一个模块,一个模块只能由一个人独立完成而不能由多人协同完成。一个技术人员在整个开发期内完成一个模块以后可以接着做任一软件的任一模块。写一个程序,求出公司最早能在什么时候交付软件。

题解

        我们设$dp[i]$为完成第一个软件的$i$个模块的情况下最多能完成第二个软件的模块的数量,我们可以二分完成时间$mid$,所有技术人员都最多能用$mid$的时间,然后就是背包模板了,以$d1$为费用,以$d2$为价值。

#include <iostream>
#include <cstring>
#include <algorithm>

#define MAX_N (100 + 5)
#define MAX_M (100 + 5)

using namespace std;

struct Node
{
    int d1, d2;
};

int n, m;
Node a[MAX_N];
int dp[MAX_M];
int ans;

int main()
{
    cin >> n >> m;
    for(register int i = 1; i <= n; ++i)
    {
        cin >> a[i].d1 >> a[i].d2; 
    }
    int lt = 1, rt = 20000, mid;
    while(lt <= rt)
    {
        mid = lt + rt >> 1;
        memset(dp, -1, sizeof dp);
        dp[0] = 0;
        for(register int i = 1; i <= n; ++i)
        {
            for(register int j = m; j >= 0; --j)
            {
                for(register int k = 0; k <= j && k * a[i].d1 <= mid; ++k)
                {
                    if(~dp[j - k]) dp[j] = max(dp[j], dp[j - k] + (mid - k * a[i].d1) / a[i].d2);
                }
            }
        }
        if(dp[m] >= m) 
        {
            ans = mid;
            rt = mid - 1;
        }
        else lt = mid + 1;
    }
    cout << ans;
    return 0;
}
参考程序
原文地址:https://www.cnblogs.com/kcn999/p/11275622.html