赞
踩
为了更好的阅读体检,可以查看我的算法学习网
本题在线评测链接:P1334
某组织举行会议,来了多个代表团同时到达,接待处只有一辆汽车,可以同时接待多个代表团,为了提高车辆利用率,请帮接待员计算可以坐满车的接待方案,输出方案数量。
约束:
第一行 代表团人数,英文逗号隔开,代表团数量小于 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]
本题可以抽象成一个背包(车)容量为m,有n个不同重量的物品(代表团),问恰好装满背包的方案数
可以看出本题其实是01背包问题的变种,利用01背包思路来计算方案数
不懂01背包的童鞋可以点这里
其中01背包中的物品个数、背包容量分别对应题中的代表团数量、车的容量
本题我们采用一维(即优化后的01背包)来写,可以这么理解,dp[w]表示恰好装成容量为w的方案数
对于人数为i的代表团,装进车后容量w为的转移方程为:dp[w] += dp[w - i]
,(注:这里不懂的童鞋一定要去学习一下原始二维的01背包是如何优化成一维的)
需要注意的是,本题是个计数问题,初始化只需要将dp[0]初始化为1(毕竟车刚为空时是一种方案),其余的初始化为0
具体看代码
入职小技巧:01背包问题的一维做法不仅可以省空间,还可以使得在做题敲代码时更快
#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;
}
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])
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]);
}
}
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();
});
});
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为车容量
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。