《湊硬幣》 動態規划算法入門


題目描寫敘述

假設我們有面值為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; 
}



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM