【备战秋招】每日一题:2023.05-B卷-华为机试 - 代表团坐车

为了更好的阅读体检,可以查看我的算法学习网
本题在线评测链接:P1334

题目描述

某组织举行会议,来了多个代表团同时到达,接待处只有一辆汽车,可以同时接待多个代表团,为了提高车辆利用率,请帮接待员计算可以坐满车的接待方案,输出方案数量。

约束:

  1. 一个团只能上一辆车,并目代表团人数(代表团数量小于 30 30 30,每个代表团人数小于 30 30 30)小于汽车容量(汽车容量小于 100 100 100)
  2. 需要将车辆坐满

输入描述

第一行 代表团人数,英文逗号隔开,代表团数量小于 30 30 30,每个代表团人数小于 30 30 30

第二行 汽车载客量,汽车容量小于 100 100 100

输出描述

坐满汽车的方案数量
如果无解输出 0 0 0

样例

输入

5,4,2,3,4,6
10

输出

4

说明

解释以下几种方法都可以坐满车,所有,优先接待输出为 4 4 4

[ 2 , 3 , 5 ] [2,3,5] [2,3,5]

[ 2 , 4 , 4 ] [2,4,4] [2,4,4]

[ 2 , 3 , 5 ] [2,3,5] [2,3,5]

[ 2 , 4 , 4 ] [2,4,4] [2,4,4]

思路:01背包

本题可以抽象成一个背包(车)容量为m,有n个不同重量的物品(代表团),问恰好装满背包的方案数

可以看出本题其实是01背包问题的变种,利用01背包思路来计算方案数

不懂01背包的童鞋可以点这里

其中01背包中的物品个数、背包容量分别对应题中的代表团数量、车的容量

本题我们采用一维(即优化后的01背包)来写,可以这么理解,dp[w]表示恰好装成容量为w的方案数

对于人数为i的代表团,装进车后容量w为的转移方程为:dp[w] += dp[w - i],(注:这里不懂的童鞋一定要去学习一下原始二维的01背包是如何优化成一维的)

需要注意的是,本题是个计数问题,初始化只需要将dp[0]初始化为1(毕竟车刚为空时是一种方案),其余的初始化为0

具体看代码

入职小技巧:01背包问题的一维做法不仅可以省空间,还可以使得在做题敲代码时更快

代码

C++
#include <iostream>
#include <vector>
#include <sstream>

using namespace std;

int main() {
    string inputStr;
    getline(cin, inputStr);
    stringstream ss(inputStr); // 使用流输入
    int m, num;
    vector<int> a;

    while (ss >> num) {
        a.push_back(num);
        if (ss.peek() == ',') {
            ss.ignore();
        }
    }

    cin >> m;
    vector<int> dp(m + 1, 0); // dp[n]表示恰好装成容量为n的方案数
    dp[0] = 1; // 初始化dp[0] = 1,表示容量为0的方案为1种

    for (int i : a) {
        for (int j = m; j >= i; j--) {
            dp[j] += dp[j - i]; // 转移方程为:dp[n] += dp[n - i]
        }
    }

    cout << dp[m] << endl;

    return 0;
}

python
a = [int(x) for x in input().split(',')]
m = int(input())
dp = [0] * (m + 1) # dp[n]表示恰好装成容量为n的方案数
dp[0] = 1 # 初始化dp[0] = 1,表示容量为0的方案为1种
for i in a:
    for j in range(m, i - 1, -1):
        dp[j] += dp[j - i] # 转移方程为:dp[n] += dp[n - i]
print(dp[m])
Java
import java.util.Scanner;
import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String inputStr = scanner.nextLine();
        String[] nums = inputStr.split(",");
        List<Integer> a = new ArrayList<>();
        for (String num : nums) {
            a.add(Integer.parseInt(num.trim()));
        }

        int m = scanner.nextInt();
        int[] dp = new int[m + 1];// dp[n]表示恰好装成容量为n的方案数
        dp[0] = 1;// 初始化dp[0] = 1,表示容量为0的方案为1种

        for (int i : a) {
            for (int j = m; j >= i; j--) {
                dp[j] += dp[j - i]; // 转移方程为:dp[n] += dp[n - i]
            }
        }

        System.out.println(dp[m]);
    }
}

JavaScript
const readline = require('readline');

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

rl.question('', (inputStr) => {
  const a = inputStr.split(',').map(Number);

  rl.question('', (m) => {
    const dp = new Array(Number(m) + 1).fill(0); // dp[n]表示恰好装成容量为n的方案数
    dp[0] = 1; // 初始化dp[0] = 1,表示容量为0的方案为1种

    for (let i of a) {
      for (let j = m; j >= i; j--) {
        dp[j] += dp[j - i]; // 转移方程为:dp[n] += dp[n - i]
      }
    }

    console.log(dp[m]);
    rl.close();
  });
});

Go
package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)

	inputStr, _ := reader.ReadString('\n')
	inputStr = strings.TrimSpace(inputStr)
	nums := strings.Split(inputStr, ",")

	var a []int
	for _, numStr := range nums {
		num, _ := strconv.Atoi(numStr)
		a = append(a, num)
	}

	mStr, _ := reader.ReadString('\n')
	m, _ := strconv.Atoi(strings.TrimSpace(mStr))

	dp := make([]int, m+1) // dp[n]表示恰好装成容量为n的方案数
	dp[0] = 1 // 初始化dp[0] = 1,表示容量为0的方案为1种

	for _, i := range a {
		for j := m; j >= i; j-- {
			dp[j] += dp[j-i] // 转移方程为:dp[n] += dp[n - i]
		}
	}

	fmt.Println(dp[m])
}

时间复杂度

O ( n m ) O(nm) O(nm)

其中n为代表团数量,m为车容量

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

塔子哥学算法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值