一道算法题:在超市用现金结账时,有以下几种纸币,arr[] =[100,50,20,5,1]

,现在求我如何付钱以及收银员如何找钱,才能使付给收银员张数和收银员找回的张数加起来最少?比如我结账需付19,我可以付20,然后收银员找1,这样只需要2张钱,数量最少。

参加某线下笔试,有这么一道选做题。。。。。。。。

思路:

假设理应当付A块,现在实际付了B块,则要解决两个问题:表达B块最少多少张钱?表达B-A块最少多少张钱?枚举下B,取两个最小值的和的最小值即可。B取[A,100+A)肯定对。

表达n块最少需要多少张钱这就成了一个经典的完全背包问题。参见背包九讲的完全背包一节。当然value不是最大化而是最小化。

作者:Tim Shen
链接:https://www.zhihu.com/question/46344632/answer/100978186

下面是自己的实现

import java.util.Arrays;
import java.util.Scanner;

/*
 * 在超市用现金结账时,有以下几种纸币,arr[] =[100,50,20,10,5,1],现在求我如何付钱以及收银员如何找钱,才能使付给收银员张数和收银员找回的张数加起来最少?
比如我结账需付19,我可以付20,然后收银员找1,这样只需要2张钱,数量最少。
 */
public class coinChange {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int[] coins = {1,5,10,20,50,100};
		int target = in.nextInt();
		int ret = Integer.MAX_VALUE;
		int bb = 0;
		for(int B=target;B<target+100;B++){
			int t1 = coinChange(coins,B);
			int t2 = coinChange(coins,B-target);
			if(ret > (t1+t2)){
				ret = t1 + t2;
				bb = B;
			}
			//ret = Math.min(ret, t1+t2);
		}
		//System.out.println(bb);
		System.out.println(ret);
	}
	 public static int coinChange(int[] coins, int amount) {
	        if(amount==0)return 0;
	    int[] min=new int [amount+1];
	    Arrays.fill(min,amount+1);
	    min[0]=0;
	    for(int i=1;i<=amount;i++){
	    for(int j=0;j<coins.length;j++){
	        if(coins[j]<=i && min[i-coins[j]]+1<min[i])
		    min[i]=min[i-coins[j]]+1;
	        }
	    }    
	    return min[amount]==amount+1?-1:min[amount];

	    }
}