求换取零钱的最少金币个数个数--动态规划问题2

输入m个数字(正数,必须含有1.)代表金币的面值,再输入n代表换钱的总额,求换取的最少金币个数。

动态规划问题2

动态规划的基本思想是将待求解问题分解成若干个子问题,先求解子问题,并将这些子问题的解保存起来,如果以后在求解较大子问题的时候需要用到这些子问题的解,就可以直接取出这些已经计算过的解而免去重复运算。保存子问题的解可以使用填表方式,例如保存在数组中。

代码如下:

import java.util.Scanner;
public class Jin_bin_zhao_ling {
public static void main(String[] args) {
  Scanner sc=new Scanner(System.in);
  System.out.print("输入金币面值的个数:");
  int m,n;
  m=sc.nextInt();
  System.out.println("输入"+m+"个金币的面值(必须包含1)");
  int a[]=new int[m];
  for(int i=0;i<m;++i)
      a[i]=sc.nextInt();
  System.out.print("输入总钱n:");
  n=sc.nextInt();
  sc.close();
  int b[]=hui(a);
  n=ge_shu(b,n);
  System.out.println("金币的最少个数为:"+n);
};
public static int ge_shu(int[] a,int n){
    int len=a.length; /*注意数组的第一个元素为0,要过滤掉*/
    int f[]=new int[n+1];
    f[0]=0;
    for(int i=1;i<=n;++i)   /*核心算法*/
    {
        int j=1,temp=java.lang.Integer.MAX_VALUE;
        while(j<len&&i>=a[j])
        {
            temp=Math.min(f[i-a[j]], temp);
            ++j;
        }
        f[i]=temp+1;
    }
    return f[n];
};
public static int [] hui(int a[]){ /*对输入的数据进行排序并且剔除重复的数字*/
    int len=1; /*返回的长度多加一*/
    for(int i=0;i<a.length;++i)
    {
        int k=i;
        for(int j=i+1;j<a.length;++j)
            if(a[j]<a[k])
                k=j;
        if(k!=i)
        {
            int temp=a[k];
            a[k]=a[i];
            a[i]=temp;
        }
    }
    for(int i=0;i<a.length;++i)
    {
        len++;
        while((i+1)<a.length&&a[i]==a[i+1])/*过滤调用重复元素*/
            ++i;
    }
    int b[]=new int[len];
    int k=1;/*故意把长度增加1,所以前面的下标0空着。方便以后的下标使用。*/
    for(int i=0;i<a.length;++i)
    {
        b[k]=a[i];
        ++k;
        while((i+1)<a.length&&a[i]==a[i+1])
            ++i;
    }
    return b;
};
}
时间: 2024-08-06 03:42:05

求换取零钱的最少金币个数个数--动态规划问题2的相关文章

数位dp(求1-n中数字1出现的个数)

题意:求1-n的n个数字中1出现的个数. 解法:数位dp,dp[pre][now][equa] 记录着第pre位为now,equa表示前边是否有降数字(即后边可不可以随意取,true为没降,true为已降):常规的记忆化搜索 代码: /****************************************************** * author:xiefubao *******************************************************/ #p

求逆序对(inversion)的个数

2-4 逆序对 设A[1...n]是一个包含n个不同数的数组,如果在i<j的情况下,有A[i]>A[j],则(i,j)就称为A中的一个逆序对(inversion). a)列出数组<2, 3, 8, 6, 1>的5个逆序对 b)如果数组的元素取自集合{1,2,...,n}, 那么, 怎样的数组含有最多的逆序对?它包含多少个逆序对? c)插入排序的运行时间与输入数组中逆序对的数量之间有怎样的关系?说明你的理由. d)给出一个算法,它能用Θ(nlgn)的最坏情况运行时间,确定n个元素的任

spoj 694 求一个字符串中不同子串的个数

SPOJ Problem Set (classical) 694. Distinct Substrings Problem code: DISUBSTR Given a string, we need to find the total number of its distinct substrings. Input T- number of test cases. T<=20; Each test case consists of one string, whose length is <=

求二叉树第K层的节点个数+求二叉树叶子节点的个数

size_t _FindLeafSize(Node* root)     //求二叉树叶子节点的个数    {        //static size_t count = 0;        if (root == NULL)            return 0; if (root->_left == NULL&&root->_right == NULL);        return 1; return _FindLeafSize(root->_right) +

求整型中二进制1的个数

1. 确定二进制1的个数: ->循环死& ->x-1&x ->查表,分写死与动态生成,动态生成方法:BitsSetTable256[i] = (i &1) + BitsSetTable256[i /2]; ->并行位运算: int BitCount4(unsigned int n) {    n = (n &0x55555555) + ((n >>1) &0x55555555) ;    n = (n &0x3333333

线段树求LIS并统计最长子序列个数

以下面的题目为例(题目和代码在最后面),给定一个数列(长度最大为10000),求出最长的先增后减子序列长度及个数.做法是先求出以每一个位置结尾的最长单增子序列长度以及以该位置开头的最长单减子序列长度,然后遍历所有位置找出最大先增后减子序列长度. 以最长单增序列(LIS)为例,由于不仅需要整个序列LIS的长度,还要保存以每个位置为结尾位置的LIS长度.记以a[i]结尾的LIS长度为dp[i],则 dp[i] = max{dp[j] | a[j] < a[i]} + 1 这就是一个RMQ问题,涉及单

求给定数据中最小的K个数

public class MinHeap { /* * * Top K个问题,求给定数据中最小的K个数 * * 最小堆解决:堆顶元素为堆中最大元素 * * * */ private int MAX_DATA = 10;//最小10个数 private int[] data;//存储数据 private int len;//当前存储长度,考虑到元素个数可能没有10个,这个时候全部输出 private MinHeap() { data = new int[MAX_DATA]; len=0; } pr

UVA12493 - Stars(求1-N与N互质的个数)欧拉函数

Sample Input 3 4 5 18 36 360 2147483647 Sample Output 1 1 2 3 6 48 1073741823 题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3937 题目大意:圆上有N个点把圆分成N等分,求隔相同的点能一笔画完所有点的方法: 思考:要一笔画出,那么(N,K)必定没有在

求一个整数中二进制1的个数

题目:求一个整数二进制表示1的个数 第一版: 思路:如果一个整数与1做与运算,结果为1,那么该整数最右边一位是1,否则是0: int NumberOf1(int n) { int count = 0; while (n) { if (n&1)//如果一个整数与1做与运算的结果是1,表示该整数最右边是1,否则是0: { count++; } n = n>>1; } return count; } 缺点:因为代码当中有右移,当是负数的时候,要考虑符号位:如果一个正数,右移之后在最左边补n个