华为OJ之称砝码

1、题目

现有一组砝码,重量互不相等,分别为m1、m2……mn;他们可取的最大数量分别为x1x2……xn。现在要用这些砝码去称物体的重量,问能称出多少中不同的重量。

 

注:

称重重量包括0

要对输入数据进行校验

方法原型:public static int fama(int n, int[] weight, int[] nums)


2、思路

  本题用到动态规划算法,定义一个标记数组,来记录各种可能的取值,并且后面的解要用到前面的解。 这样讲可能抽象了点,那来个具体的例子:假设weight ={1,2}   nums={2,1} ,由此得boolean类型的flag数组大小为5,因为0也算一种情况需要考虑。当只取第一类砝码时,即2个重量为1的砝码 ,此时flag数组为 :

flag数组
true true true false false

当再放入一个2g砝码时,第一个放入的总重量是2g,从0到2逐次对本次放入的砝码进行求和:2+0 ,2+1,2+2  此时
flag数组
true true true true true
当有n个砝码时,情况类似,具体详情请看下面代码部分。
3、代码
import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();
		int[] weight = new int[n];
		int[] nums = new int[n];
		for(int i=0;i<n;i++){
			weight[i] = scanner.nextInt();
		}
		for(int j=0;j<n;j++){
			nums[j] = scanner.nextInt();
		}
		System.out.println(Weight(weight, nums));
		scanner.close();
		
	}
	
	
	public static int Weight(int[] weight,int[] nums){
		
		// 以为0也包括在内,所以即使没有砝码,也存在一种情况
		int total = 1;
		
		for(int i=0;i<weight.length;i++){
			total += weight[i]*nums[i];
		}
		
		// 声明一个标记数组,用于标记砝码可以组合出来的值
		boolean[] flag = new boolean[total]; 
		// 取第一种砝码,并对组合的重量进行标记
		for(int j=0;j<=nums[0];j++){
			flag[weight[0]*j] = true;
		}
		// 将这一种砝码标记完的各种组合之后,记录下重量
		total = weight[0]*nums[0];
		
		int sum = 0;
		// 从第二种砝码开始取
		for(int i=1;i<weight.length;i++){
			for(int j=1;j<=nums[i];j++){
				for(int k=0;k<=total;k++){
					sum = k + j*weight[i];
					// 如果和大于标记数组长度则跳出当前循环
					if(sum > flag.length-1){
						break;
					}
		            // 如果是第二种砝码重量的整数倍(不大于砝码的个数)直接标记,如果k位已标记加上0~n个砝码的重量未标记,则进行标记
					if(flag[k] && !flag[sum] || k == 0){
						flag[sum] = true;
					}
				}
			}
			// 将本次放入一种砝码与之前的累加总和赋值给total
			total = sum;
		}
		// 对数组中值为true的进行统计
		int count = 0;
		for(int i=0;i<flag.length;i++){
			if(flag[i] == true){
				count++;
			}
		}
		return count;
	}
	
}
留下足迹,特此记之。

你可能感兴趣的:(华为OJ之称砝码)