生物信息学习笔记 (3) 找零钱

经典问题,给定一些面额的纸币,和要找回金币的总额,找出使得纸币数量最少的方案

今天第一次写 Java, 开始 Java 学习之旅吧

 

public class Make_Change {

	public static void main ( String[] args ) {
		final int [] Value = new int[] { 1 , 2 , 5 , 10 , 20 , 50 } ;
		final int money = 100 ;
		int [] dp = new int[money + 1] ;
		make_change ( money , Value , dp ) ;
	}

	public static void make_change ( final int money , final int [] Value , int [] dp ) {
		int [] pre = new int[money + 1] ;
		for ( int i = 1 ; i <= money ; ++i ) {
			int ans = i ;
			for ( int j = 0 ; j < Value.length ; ++j ) {
				if ( i >= Value[j] ) {
					int temp = dp[i - Value[j]] + 1 ;
					if ( ans > temp ) {
						ans = temp ;
						pre[i] = i - Value[j] ;
					}
				}
			}
			dp[i] = ans ;
			System.out.print ( "面值为 " + i + " 的最少找钱数是  " + ans + "\t" ) ;
			int des = i ;
			while ( pre[des] != 0 ) {
				System.out.print ( des - pre[des] + "  " ) ;
				des = pre[des] ;
			}
			System.out.println ( des ) ;
		}
	}
}

 

 

 

 

 

 

主要是如何保存最优的方案:

思路就是设置一个 pre 数组,因为最优解一定可以分解成某个小于自己的最优解加上某个 零钱 ,

所以,尝试每个硬币,如果在前面最优解的基础上,加上这个硬币更优,就把这个前面最优解的下标 i - Value[i] 记下来,要输出方案时,就输出 i - ( i - Value[i] ) = Value[i]. 

运行结果 :

 

 

 

还有一种更麻烦的思路,就是用一个 vector 二维数组保存每个点所记录的最优解方案,发现前面最优解加上某个零钱更优,就把最优解替换成前面最优解的 vector 的内容,然后 push_back 当前加入的零钱、

 

#include <bits/stdc++.h>
using namespace std ;
int dp[1005] ;
vector < int > Vec[1005] ;

int main () {
	const vector < int > One = { 1 , 2 , 5 , 10 , 20 , 50 } ;
	const int money = 100 ;
	for ( int i = 1 ; i <= money ; ++i ) {
		int ans = i ;
		for ( const auto it : One ) {
			if ( i >= it ) {
				int temp = dp[i - it] + 1 ;
				if ( ans > temp ) {     // 只能保存一组解
					ans = temp ;
					Vec[i].clear () ;
					for ( const auto j : Vec[i - it] )
						Vec[i].push_back ( j ) ;
					Vec[i].push_back ( it ) ;
				}
			}
		}
		dp[i] = ans ;
		cout << "面值为 " << i << " 找钱数  : " << ans << "\t" ;
		for ( const auto it : Vec[i] )
			cout << it << "  " ;
		cout << endl ;
	}
	return 0 ;
}

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值