《凑硬币》 动态规划算法入门

题目描写叙述

假设我们有面值为1元、3元和5元的硬币若干枚。怎样用最少的硬币凑够11元?

思路问题

这是博客http://hawstein.com/posts/dp-novice-to-advanced.html上面的一个入门的小样例。

动态规划算法的核心是:每一个子问题的状态和状态的转移方程。

状态是:dp[i] ,即凑够i元最少须要的硬币的个数

转移方程是:dp[i] = min(dp[i-C1]+1,dp[i-C2]+1,dp[i-C3]+1,……,dp[i-Cj]+1])

即。每一个状态的值都是最小的那个。

编写代码

说明:通过递归函数dp_fun实现了对状态数组dp的初始化

#include<iostream>
using namespace std;
int coin[3] = {1,3,5}; 
int dp[12] ;
int min(int a,int b)
{
	return (a<b)? a:b;
}
void dp_fun(int i,int num)
{
	if(i == 0)
	{
		dp[i] = 0;
		dp_fun(1,num);
		return;
	}
	else
	{
		int MIN = 9999;
		for(int j=0;j<3;j++)
		{
			if(i>=coin[j])
			{
				MIN = min(dp[i-coin[j]]+1,MIN);
			}
		}
		dp[i] = MIN;
		if(i == num)return;
		else
		dp_fun(i+1,num);
	}
}
int main()
{
	dp_fun(0,11);		//表示要凑齐11元的硬币
	for(int i=0;i<12;i++)
	{
		cout<<"凑齐"<<i<<"元。至少须要"<<dp[i]<<"枚硬币"<<endl;
	} 
	return 0; 
}

输出结果:

凑齐0元。至少须要0枚硬币
凑齐1元,至少须要1枚硬币
凑齐2元,至少须要2枚硬币
凑齐3元,至少须要1枚硬币
凑齐4元,至少须要2枚硬币
凑齐5元,至少须要1枚硬币
凑齐6元。至少须要2枚硬币
凑齐7元,至少须要3枚硬币
凑齐8元,至少须要2枚硬币
凑齐9元。至少须要3枚硬币
凑齐10元,至少须要2枚硬币
凑齐11元,至少须要3枚硬币

上面的程序是用递归写的。比較长,以下在写一个用两层循环的:

talk is cheap ,show me the code:

#include<iostream>
using namespace std;
int coin[3] = {1,3,5}; 
int dp[12] ;
void dp_fun(int num)
{
	dp[0] = 0;
	for(int i=1;i<=num;i++)
	{
		dp[i] = 9999;
		for(int j=0;coin[j]<=i&&j<3;j++)
		{
			if(dp[i-coin[j]]+1 < dp[i])
				dp[i] = dp[i-coin[j]]+1;
		}
	} 
}
int main()
{
	dp_fun(11);		//表示要凑齐11元的硬币
	for(int i=0;i<12;i++)
	{
		cout<<"凑齐"<<i<<"元,至少须要"<<dp[i]<<"枚硬币"<<endl;
	} 
	return 0; 
}


posted @ 2017-05-26 13:28  mfmdaoyou  阅读(3514)  评论(0编辑  收藏  举报