题目描述

H公司在做项目规划,当前3个团队(前端、后端、测试)共同规划完成M个项目,这时候给你3个团队各自人力总和值(XXX人月)。对于某个项目,项目都需要多个团队共同投入完成,每个项目会有一个预估的价值(XXX万元),同时一个项目都需要多个团队共同投入完成(每个项目会有对三个团队的人力需求数量)。让你在多个项目中做项目规划,在人力允许的范围内,使得能够承接的所有项目的预估价值总和量大。

备注:返回结果为能够承接的最大预估价值。如果人力无法承接任何项目,返回0。

输入描述

项目个数:m (0 < n <= 20);

三个团队人力总和:S1,S2,S3 (0 < Si <= 1000)

每个项目预估价值:V1,V2,V3,… Vn;(0 < Vi <= 1000000)

每个项目所需人力:{P11,P12,P13},{P21,P22,P23},{P31,P32,P33},…,{Pm1, Pm2,Pm3}

输出描述

输出项目规划的结果

示例一

输入:

100 100 100

10000 8000

60 60 60

60 60 60

输出:

10000

示例二

输入:

200 200 200

10000 8000 7000

150 150 150

80 80 80

90 90 90

输出:

15000 

说明:

3:3个项目

200 200 200:三个团队各自的人力总和

10000 8000 7000:项目的预估价值(1个项目一个输入,多个项目会有多个输入)

150 150 150:第一个项目对于三个团队的人力需求

80 80 80:第二个项目对于三个团队的人力需求

90 90 90:第三个项目对于三个团队的人力需求

15000:可以容纳8000与7000的项目。 

示例三

输入:

200 200 200

10000 8000 7000

300 100 100

100 300 100

100 100 300

输出:

0

说明:

3:3个项目

200 200 200:三个团队各自的人力总和

10000 8000 7000:项目的预估价值(1个项目一个输入,多个项目会有多个输入)

300 100 100:第一个项目对于三个团队的人力需求

100 300 100:第二个项目对于三个团队的人力需求

100 100 300∶第三个项目对于三个团队的人力需求

0:无法满足任何一个项目的人力需求

思路

首先可以采用暴力回溯的方法,直接满足条件的减去相对应的值,再进行回溯。

也可以采用01背包的分析方法,每个项目都有选与不选2种状态,共2^20=1048576种可能,枚举每种可能。这个容量有三个维度。但直接写背包会超内存,得提取背包容量和重量的后面多少个0开辟小一点的背包数组才能过。可以采用状态压缩的方法,例如100101表示选中第1、3、6个项目。对于一种情况,可以以O(1)时间复杂度求三个部门的剩余人力和项目的总价值,只要剩余人力不为0即可。

考点

01背包,DFS

Java代码

import java.util.Scanner;

public class Main {
    public static int res = 0;
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int[] team = new int[3];
        for (int i = 0; i < 3; i++) {
            team[i] = in.nextInt();
        }
        int[] value = new int[3];
        for (int i = 0; i < 3; i++) {
            value[i] = in.nextInt();
        }
        int[][] person = new int[n][3];
        for (int i = 0; i < n; i++) {
            person[i][0] = in.nextInt();
            person[i][1] = in.nextInt();
            person[i][2] = in.nextInt();
        }
        dfs(person, team, value, 0, 0);
        System.out.println(res);
    }
    public static void dfs(int[][] person, int[] team, int[] value, int index, int cur){
        int n = person.length;
        if (index == n) {  // 终止条件
            res = Math.max(res, cur);
            return;
        }
        for (int i = index; i < n; i++) {
            if (team[0] >= person[i][0] && team[1] >= person[i][1] && team[2] >= person[i][2]) {
                cur += value[i];
                team[0] -= person[i][0];
                team[1] -= person[i][1];
                team[2] -= person[i][2];
                dfs(person, team, value, i + 1, cur);
                cur -= value[i];
                team[0] += person[i][0];
                team[1] += person[i][1];
                team[2] += person[i][2];
            } else {
                dfs(person, team, value, i + 1, cur);
            }
        }
    }
}
最后修改日期: 2023年5月16日

留言

撰写回覆或留言

发布留言必须填写的电子邮件地址不会公开。