求换取零钱的最少金币个数个数--动态规划问题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; }; }