试题G.砝码称重

200 阅读2分钟

问题描述

你有一架天平和 N 个砝码,这 N 个砝码重量依次是 W1,W2,⋅⋅⋅,WN。

请你计算一共可以称出多少种不同的正整数重量?

注意砝码可以放在天平两边。

输入格式

输入的第一行包含一个整数 N。

第二行包含 N 个整数:W1,W2,W3,⋅⋅⋅,WN。

输出格式

输出一个整数代表答案。

数据范围

对于 50% 的评测用例,1≤N≤15。

对于所有评测用例,1≤N≤100,N 个砝码总重不超过 100000。

输入样例:

3
​
1 4 6

输出样例:

10

样例解释

能称出的 10 种重量是:1、2、3、4、5、6、7、9、10、11。
1 = 12 = 64 (天平一边放 6,另一边放 4);
3 = 414 = 45 = 616 = 67 = 1 + 69 = 4 + 6110 = 4 + 611 = 1 + 4 + 6

Java解题

//01背包
//转化一下就是用三个数相加相减,所能生成的数字
​
import java.util.Scanner;
import static java.lang.Math.abs;
public class test {
​
    public static final int N=110,M= (int) 2e5+10; //题目要求的最大值
    public static void main(String[] args) {
        //输入
        Scanner in=new Scanner(System.in);
        int n=in.nextInt();//个数
        int m=0;//砝码的最大值
        int a[]=new int[N];//每一个砝码的值
        for(int i=1;i<=n;i++){
            a[i]=in.nextInt();
            m+=a[i];
        }
     //动态规划 dp[][] 通过true,false来判断改值是否可以被称出
      boolean dp[][]=new boolean[N][M];
        dp[0][0]=true;
        //dp[i][j] i代表用的砝码数,j代表所能称重的值
        for(int i=1;i<=n;i++){
            for(int j=0;j<=m;j++){
                //条件一:i-1,已经是true  条件二:i-1,差a[i]达到j 条件三:i-1,多a[i]达到j,此条件不易想到,一般都是加,此处是减
                dp[i][j]=dp[i-1][j]||dp[i-1][abs(j-a[i])]||dp[i-1][j+a[i]];
            }
        }
        //最后的输出个数
        int ans=0;
        //循环查找n个砝码可以称出的个数
        for(int i=1;i<=m;i++){
            if(dp[n][i]){
                ans++;
            }
        }
        System.out.println(ans);
    }
}