zoukankan      html  css  js  c++  java
  • 动态规划——换钱的最少货币数

    题目:

      给定数组arr, arr中所有的值都为正数且不重复。每个值代表一中面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim代表要找的钱数,求组成aim的最少货币数。

    思路:

      如果arr的长度为N, 则生成一个行数为N, 列数为aim+1的动态规划表dp[N][aim+1], dp[i][j]的含义为:在可以任意使用arr[0...i]货币的情况下,组成j所需的最小张数。

      设: arr=[5,2,3,1] aim = 5

      1.dp[0..N-1][0]的值表示找钱数为0时需要的最少张数,所以全设为0。(矩阵的第一列)

         0 0 0 0 0 0

      dp= 0 0 0 0 0 0

         0 0 0 0 0 0

         0 0 0 0 0 0 

         2.dp[0][0...aim]的值表示只能使用arr[0]货币也就是5的情况下,找0 ,1,2,3,4,5的钱的情况下。其中无法找开的一律设为32位的最大值,记为max.

          0   max  max  max  max   1  

      dp=    0    

            0

          0

      3.剩下的位置依次从左到右,再从上到下计算。假设计算到(i,j)位置,dp[i][j]的值可能来自下面的情况:

        完全不使用当前货币arr[i]情况系的最少张数,即dp[i-1][j]的值

        只使用一张当前货币arr[i]的情况下的最少张数,即dp[i-1][j-arr[i]]+1  其中 j-arr[i]的值为使用了一张arr[i]后,还需要找多少钱。 i-1是指使用arr[i]之前的钱来兑换

        只使用两张当前货币arr[i]的情况下的最少张数,即dp[i-1][j-2*arr[i]]+2

        只使用三张当前货币arr[i]的情况下的最少张数,即dp[i-1][j-3*arr[i]]+3

        所有情况中,取最小的纸张数。所以:

        dp[i][j] = min{dp[i-1][j],  dp[i-1][j-k*arr[i]]} + k   ==>

        dp[i][j] = min{dp[i-1][j], min{dp[i-1][j-x*arr[i]]+x (x >= 1)}}   ==>

         设x-1 = y  >= 0   ==> x = y +1代入得

        dp[i][j] = min{dp[i-1][j], min{dp[i-1][j-arr[i]-y*arr[i]+y+1 (y>=0)}}

        又因为min{dp[i-1][j-arr[i]-y*arr[i]+ y (y>=0)] =>

        dp[i][j-arr[i]] 因为其中 dp[i-1][j-y*arr[i]+y] = dp[i][j] 

        最终有:dp[i][j] = min{dp[i-1][j], dp[i][j-arr[i]+1]} 如果 j-arr[i] < 0,即发生越界。

        说明arr[i]太大了,用一张都会超出钱数j,所以令dp[i][j]=dp[i-1][j]即可。

        

      

               0   max  max  max  max     1  

      dp=    0    max     1  max  2  1

          0  max  1    1  2   1

          0  1    1    1   2  1

    package chapter_4.solution3;
    
    public class Solution_3 {
    
        public static void main(String[] args) {
            int[] arr = {5,2,3,1};
            int aim = 5;
            System.out.println(minConins1(arr, aim));
        }
    
        public static int minConins1(int[] arr, int aim){
            if(arr == null || arr.length == 0 || aim < 0){
                return -1;
            }
            int[][] dp = new int[arr.length][aim+1];
            int max = Integer.MAX_VALUE;
            //设置第一行
            for(int j=1; j <= aim; j++){
                dp[0][j] = max;
                if(j-arr[0] >= 0 && dp[0][j-arr[0]] != max ){
                    dp[0][j] = dp[0][j-arr[0]] + 1;
                }
            }
            int left = 0;
            for(int i=1; i < arr.length; i++){
               for(int j=1; j <=aim; j++){
              left = max;
    if(j-arr[i] >=0 && dp[i][j-arr[i]] != max){ left = dp[i][j-arr[i]] + 1; } dp[i][j] = Math.min(left, dp[i-1][j]); } } for(int i=0; i < arr.length; i++){ for(int j=0; j<= aim; j++){ System.out.print(dp[i][j] + " "); } System.out.println(); } return dp[arr.length-1][aim] != max ? dp[arr.length-1][aim] : -1; } }
  • 相关阅读:
    httpd设置HTTPS双向认证
    crossdomain.xml的配置详解
    hibernate中的merge()方法
    解决java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver问题
    oracle自定义函数:将使用点分隔符的编码转成层级码格式的编码
    jsp页面科学计数法显示问题的解决办法
    javascript检索某个字符或字符串在源字符串中的位置(下标)
    webwork遍历数组标签
    过多得操作DOM会降低WEB应用的性能
    vue中$refs的用法及作用详解
  • 原文地址:https://www.cnblogs.com/huangyichun/p/6337358.html
Copyright © 2011-2022 走看看