1. 問題描述:
n種硬幣,面值分別是:v[1],v[2],……v[n]。給定非負整數s,可以選用多少個硬幣,使得面值之和恰好為s?求出硬幣數目的最大值和最小值。
2. 分析:
初始狀態為:s,目標狀態為0。若當前狀態在i,每使用乙個硬幣j,狀態便轉移到i-v[j]。我們用d(i)表示求總和為i的最少硬幣數量(其實就是動態規劃中的「狀態」),那麼怎麼從前面的狀態(並不一定是d(i-1)這乙個狀態)到d(i)這個狀態?假設硬幣集合為coins[0~n],在求d(i)之前,我們假設d(1~i-1)全部都求出來了,那麼d(i)=min(其實這就是「狀態轉移方程」)。
舉例說明:coins=,n=11。
d(0)=0;
d(1)=0;
d(2)=d(0)+1=1;
d(3)=d(0)+1=1;
d(4)=d(2)+1=2;
d(5)=min=1;
d(6)=min=2;
3. 記憶化搜尋**:
#include
#include
using namespacestd;
int n, s, v[100],d[100], vis[100];//vis[i]=0:標誌狀態i沒有計算過;否則計算過
int dpmax(int s);
int dpmin(int s);
void print(int*d,int s);列印出組成s的硬幣大小。
int main()
cin >> n >> s;
for(int i = 1; i <= n; ++i)
cin >> v[i];
memset(vis, 0, sizeof(vis));
vis[0]=1; //記憶化搜尋的初始化必須將除了目標狀態的所有狀態設定為0
d[0]=0;
cout << dpmax(s) << endl;
print(d,s);
coutvis[0]=1;
cout << dpmin(s) << endl;
print(d,s);
return 0;
int dpmax(int s)//求最大的硬幣數量
if(vis[s])
return d[s];
vis[s] = 1;
int &ans = d[s];
ans = -(1<<30);
for(int i = 1; i <= n; ++i)
if(s >= v[i])
ans = max(ans, dpmax(s - v[i]) + 1);
return ans;
int dpmin(int s)//求最少的硬幣數量
if(vis[s])
return d[s];
vis[s] = 1;
int &ans = d[s];
ans = 1<<30;
for(int i = 1; i <= n; ++i)
if(s >= v[i])
ans = min(ans, dpmin(s - v[i]) +1);
return ans;
void print(int *d,int s)
for(int i=0; iif(s>=v[i]&&d[s]==d[s-v[i]]+1)
coutreturn;
4. 遞推法**:
#include
#include
#include
using namespacestd;
const intinf=1<<30;
int n,s;
intv[100],minv[100],maxv[100],mincoin[100],maxcoin[100];
//mincoin、maxcoin:儲存對應路徑上硬幣的大小
void print(int *d,int s);
int main()
cin>>n>>s;
for(int i=0;icin>>v[i];
minv[0]=maxv[0]=0;//
遞推的最下層
for(int i=1;i<=s;i++)
minv[i]=inf;
maxv[i]=-inf;
for(int i=1;i<=s;i++)
for(int j=0;jif(i>=v[j])
if(maxv[i]maxv[i]=maxv[i-v[j]]+1;
maxcoin[i]=v[j];
if(minv[i]>minv[i-v[j]]+1)
minv[i]=minv[i-v[j]]+1;
mincoin[i]=v[j];
coutcoutreturn 0;
void print(int*d,int s)
while(s)
coutcout<
動態規劃演算法 湊硬幣
動態規劃演算法是電腦科學演算法中最重要也是最常用的乙個演算法,巧妙的利用它可以解決很多複雜的問題,另外也頻繁的出現在各大網際網路公司的面試中,因此掌握它是十分必要的。但該演算法對於初學者來說,要想徹底的掌握理解它並非易事,本系列教程將帶領大家一起來學習該演算法,通過經典的案列介紹和解題分析,試圖歸納...
動態規劃演算法求解硬幣找零問題
1.問題描述 現存在一堆面值為 v1 v2 v3 個單位的硬幣,問最少需要多少個硬幣才能找出總值為 t 個單位的零錢?假設這一堆面值分別為 1 2 5 21 25 元,需要找出總值 t 為 63 元的零錢。2.分析 動態規劃的基本思想是將待求解問題分解成若干個子問題,先求解子問題,並將這些子問題的解...
動態規劃演算法
一 動態規劃演算法原理 將待求解的問題分解成若干個相互聯絡的子問題,先求解子問題,然後從這些子問題的解得到原問題的解 對於重複出現的子問題,只在第一次遇到的時候對它進行求解,並把答案儲存起來。了不去求解相同的子問題,引入乙個陣列,把所有子問題的解存於該陣列中,這就是動態規劃所採用的基本方法。動態規劃...