华为机试4.27:项目规划

项目规划
题目描述

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}

输出描述

输出项目规划的结果

样例1
输入
2 
100 100 100
10000 8000
60 60 60
60 60 60
输出
10000
解释
22个项目
100 100 100:三个团队各自的人力总和
100008000:项目的预估价值(1个项目一个输入,多个项目会有多个输入)
60 60 60:第一个项目对于三个团队的人力需求
60 60 60:第二个项目对于三个团队的人力需求
10000:输出项目规划的结果 
样例2
输入
3 
200 200 200
10000 8000 7000
150 150 150
80 80 80
90 90 90
输出
15000 
解释
33个项目
200 200 200:三个团队各自的人力总和
10000 8000 7000:项目的预估价值(1个项目一个输入,多个项目会有多个输入)
150 150 150:第一个项目对于三个团队的人力需求
80 80 80:第二个项目对于三个团队的人力需求
90 90 90:第三个项目对于三个团队的人力需求
15000:可以容纳80007000的项目。 
样例3
输入
3 
200 200 200
10000 8000 7000
300 100 100
100 300 100
100 100 300
输出
0
解释
33个项目
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即可。

参考代码
  1. 暴力回溯
import java.util.Scanner;

public class Main3 {
    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);
            }
        }
    }
}
  1. 01背包
    wait wait
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值