算法练习之---最小邮票数

    前言:

      关于这种巧妙的排列组合类的算法问题,需要找到这种问题求解的特点,然后根据这种特点逐步求解的过程。在本问题中,要求解和一致情况下的组合数最小,这里我定义一个和sum长度一致的数组存放结果值,双重循环遍历完张数的总个数,在其中的第二层从sum值开始递减,逐渐找最小,最后输出数组中的结果位即可。

 

题目描述

    有若干张邮票,要求从中选取最少的邮票张数凑成一个给定的总值。     如,有1分,3分,3分,3分,4分五张邮票,要求凑成10分,则使用3张邮票:3分、3分、4分即可。 
输入描述:
    有多组数据,对于每组数据,首先是要求凑成的邮票总值M,M<100。然后是一个数N,N〈20,表示有N张邮票。接下来是N个正整数,分别表示这N张邮票的面值,且以升序排列。


输出描述:
      对于每组数据,能够凑成总值M的最少邮票张数。若无解,输出0。

输入例子:
10
5
1 3 3 3 4

输出例子:
3

 

import java.util.Scanner;

public class 最小邮票数 {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while(in.hasNext()){
            int sum=in.nextInt();
            int count = in.nextInt();
            int[] num=new int[count];
            for(int i=0;i<count;i++){
                num[i]=in.nextInt();
            }
            System.out.println(Mincount(num,count,sum));
        }
        in.close();

    }
    
    private static int Mincount(int[] num,int count,int sum){
        int[] dp = new int[sum + 1];
        for (int i = 1; i < dp.length; i++) {
            dp[i] = sum + 1;   //第0位为0,从第1位开始各位都为sum+1
        }
        for (int i = 0; i < count; i++) {
            for (int j = sum; j >= num[i]; j--) {   //j的值递减,直到和这个位上的数值相等时停止递减
                dp[j] = Math.min(dp[j], dp[j - num[i]] + 1); //比较最新的dp值和以前的dp,选取最小,刷新数据
                //System.out.println(dp[j]+"   i="+i+"   "+"j="+j);
            }
        }
        if (dp[sum]==sum+1) {
            return 0;
        }
        return dp[sum];
        
    }

}

 

posted @ 2016-08-09 10:25  华不摇曳  阅读(1267)  评论(0编辑  收藏  举报