第一行输入一个整数
代表砝码的个数。
第二行输入
个整数
代表每种砝码的重量。
第三行输入
个整数
代表每种砝码的数量。
输出一个整数,代表利用给定的砝码可以称出的不同的重量数。
2 1 2 2 1
5
在这个样例中,有
个重量为
的砝码,
个重量为
的砝码。称重方式如下:
不放砝码,称重重量为
;
放
个重量为
的砝码,称重重量为
;
放
个重量为
的砝码,称重重量为
;
放
个重量为
的砝码、
个重量为
的砝码,称重重量为
;
放
个重量为
的砝码、
个重量为
的砝码,称重重量为
。
因此,能称出的不同重量有
种,分别是
。
把所有砝码放到一个数组里,转换为组合回溯问题,在每个树枝判断、收集结果。
先把砝码排序,例如[1,1,3,5,6],加入used数组去重,避免得到[1,3,5]、[1, 3, 5]等重复集合,
且并能减小遍历次数,提高效率,Set集合避免重复输出,超时了。19/20
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
while (in.hasNextInt()) { // 注意 while 处理多个 case
int n = in.nextInt();
int[] weights = new int[n];
int[] numbers = new int[n];
for (int i = 0; i < n; i++){
weights[i] = in.nextInt();
}
for (int i = 0; i < n; i++){
numbers[i] = in.nextInt();
}
ArrayList<Integer> map = new ArrayList<>();
for (int i = 0; i < n; i++){
for (int j = 0; j < numbers[i]; j++){
map.add(weights[i]);
}
}
int res = 0;
HashSet<Integer> usedSet = new HashSet<>();
usedSet.add(0);
Collections.sort(map);
int[] used = new int[map.size()];
backtracking(map, usedSet, 0, 0, used);
System.out.println(usedSet.size());
}
}
private static void backtracking(ArrayList<Integer> map,
HashSet<Integer> usedSet, int startindex, int sum, int[] used){
if(!usedSet.contains(sum)){
usedSet.add(sum);
}
for (int i = startindex; i < map.size(); i++){
if (i > 0 && map.get(i) == map.get(i - 1) && used[i - 1] == 0){
continue;
}
used[i] = 1;
sum += map.get(i);
backtracking(map, usedSet, i + 1, sum, used);
sum -= map.get(i);
used[i] = 0;
}
}
} import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int count = in.nextInt();
int[] weight = new int[count];
int[] size = new int[count];
for (int i = 0; i < count; i++) {
weight[i] = in.nextInt();
}
int sumCount = 0;
for (int i = 0; i < count; i++) {
size[i] = in.nextInt();
sumCount += size[i];
}
int[] weights = new int[sumCount];
int maxSum = 0;
int p = 0;
for (int i = 0; i < count; i++) {
for (int j = 0; j < size[i]; j++) {
weights[p++] = weight[i];
maxSum += weight[i];
}
}
boolean[] dp = new boolean[maxSum + 1];
dp[0] = true;
HashSet<Integer> set = new HashSet<>();
set.add(0);
for (int num : weights) {
for (int j = maxSum; j >= num; j--) {
if (dp[j - num]) {
dp[j] = true;
set.add(j);
}
}
}
System.out.println(set.size());
}
} 想了好半天,突然就开窍了,关键在于每次选择砝码时,和之前的每轮选砝码的所有结果进行一一组合,需要两个HashSet倒腾数据。
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
if (in.hasNextInt()) { // 注意 while 处理多个 case
// n种砝码
int n = in.nextInt();
// 记录砝码重量
int[] arr1 = new int[n];
// 记录各砝码数量
int[] arr2 = new int[n];
for (int i = 0; i < n; i++) {
arr1[i] = in.nextInt();
}
for (int i = 0; i < n; i++) {
arr2[i] = in.nextInt();
}
// 用来存储每次选择某个砝码的个数时,和之前所有砝码重量产生的组合
Set<Integer> set = new HashSet<>();
for (int i = 0; i < n; i ++) {
Set<Integer> subSet = new HashSet<>();
for (int j = 0; j <= arr2[i]; j++) {
int a = arr1[i] * j;
if (set.isEmpty()) {
// 第一轮,没有旧数据
subSet.add(a);
} else {
// 之后的数据需要和之前产生的每个结果进行组合
for (Integer is : set) {
subSet.add(is + a);
}
}
}
set.addAll(subSet);
}
System.out.println(set.size());
}
}
}
原来是我想得太复杂了,我们可以把这个问题拆解到每一次称出的重量,然后再汇总起来
import java.util.HashSet;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[] weights = new int[n];
int[] nums = new int[n];
for (int i = 0; i < n; i++) {
weights[i] = in.nextInt();
}
for (int i = 0; i < n; i++) {
nums[i] = in.nextInt();
}
in.close();
HashSet<Integer> set = new HashSet<>(); // 存储所有重量的可能结果,去重
set.add(0);
for (int i = 0; i < n; i++) {
HashSet<Integer> onceAdd = new HashSet<>(); // 本次要添加的重量
for (int j = 1; j <= nums[i]; j++) {
onceAdd.add(j * weights[i]); // 一种砝码的倍数
for (Integer v : set) {
onceAdd.add(v + weights[i] * j); // 之前计算过的重量要加上新砝码
}
}
set.addAll(onceAdd);
}
System.out.println(set.size());
}
}
import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
while (in.hasNext()) { // 注意 while 处理多个 case
int n = in.nextInt();
// 读取砝码的种类
int[] weight = new int[n];
for (int i = 0; i < n; i++) {
weight[i] = in.nextInt();
}
// 读取砝码的数量
List<Integer> list = new ArrayList<>();
for (int i = 0; i < n; i++) {
int s = 1 ;
for (int count = in.nextInt(); count > 0; ) {
// 整合到同一个序列当中
list.add(weight[i] *(Math.min(s, count)));
count -= s;
s = s<<1;
}
}
// 创建一个集合Set
Set<Integer> set = new CopyOnWriteArraySet<>();
// 初始化向集合中添加0
set.add(0);
// 遍历序列list
for (int i : list) {
// 遍历集合Set,对每个Set当中的值加值后,添加到Set当中
for (int k : set) {
set.add(i + k);
}
set.add(i);
}
// 统计Set当中的数量,并输出
System.out.println(set.size());
}
}
}
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
while (in.hasNextInt()) { // 注意 while 处理多个 case
int num = in.nextInt();
int[] typeHeight = new int[num];
int[] numHeight = new int[num];
for (int i = 0; i < num; i++) {
typeHeight[i] = in.nextInt();
}
for (int i = 0; i < num; i++) {
numHeight[i] = in.nextInt();
}
HashSet<Integer> hashSet = new HashSet<>();
hashSet.add(0);
//遍历所有砝码
for (int i = 0; i < num; i++) {
//得到每种砝码的重量和数量
int weight = typeHeight[i];
int number = numHeight[i];
HashSet<Integer> temp = new HashSet<>();
for (int j = 1; j <= number; j++) {
//将当前同种类砝码进行叠加,每次叠加都与之前所称重量数进行对比,有新的就加入到集合中
for (Integer w : hashSet) {
temp.add(w + weight * j);
}
}
hashSet.addAll(temp);
}
System.out.println(hashSet.size());
}
}
} import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
while (in.hasNext()) { // 注意 while 处理多个 case
int n = in.nextInt();
// 读取砝码的种类
int[] weight = new int[n];
for(int i = 0; i < n; i++){
weight[i] = in.nextInt();
}
// 读取砝码的数量
List<Integer> list = new ArrayList<>();
for(int i = 0; i < n; i++){
for(int count = in.nextInt(); count > 0; count--){
// 整合到同一个序列当中
list.add(weight[i]);
}
}
// System.out.println(list);
// 创建一个集合Set
Set<Integer> set = new HashSet<>();
// 初始化向集合中添加0
set.add(0);
// 遍历序列list
for(int i : list){
// 遍历集合Set,对每个Set当中的值加值后,添加到Set当中
int len = set.size();
List<Integer> setList = new ArrayList<>();
// 将set中的值临时存入setList当中用于求和
for(int j : set){
setList.add(j);
}
for(int k : setList){
set.add(i + k);
}
}
// 统计Set当中的数量,并输出
System.out.println(set.size());
}
}
} import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
while (in.hasNextLine()) { // 注意 while 处理多个 case
int num = Integer.valueOf(in.nextLine());
String weight = in.nextLine();
String weightNum = in.nextLine();
String[] arr1 = weight.split(" ");
String[] arr2 = weightNum.split(" ");
int[] weights = new int[num];//存储所有重量
int[] weightNums = new int[num];//存储所有数量
for (int i = 0; i < num; i++) {
weights[i] = Integer.parseInt(arr1[i]);
weightNums[i] = Integer.parseInt(arr2[i]);
}
Set<Integer> set = new HashSet<>();//存储不重复的砝码重量集合
set.add(0);//初始化重量0
for (int i = 0; i < num; i++) {
int wet = weights[i];//遍历每一个重量
int wtn = weightNums[i];//遍历重量对应的数量
Set<Integer> temp = new HashSet<>();//暂存集合
//遍历数量,注意循环的初始值,排查半天
for (int j = 1; j <= wtn; j++) {
for(Integer w : set){
temp.add(w + wet * j);
}
}
set.addAll(temp);
}
System.out.println(set.size());
}
}
} import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
in.nextLine();
String [] weights = in.nextLine().split(" ");
String [] counts = in.nextLine().split(" ");
Set<Integer> temp = new HashSet();
Set<Integer> sets = new HashSet();
sets.add(0);
for(int i = 0; i < n; i++){
temp.clear();
for(int j = 1; j <= Integer.parseInt(counts[i]); j++){
for(Integer item : sets){
int m = item + Integer.parseInt(weights[i])*j;
temp.add(m);
}
}
sets.addAll(temp);
}
System.out.println(sets.size());
}
}