1. 程式人生 > >硬幣問題——DAG模型上的動態規劃

硬幣問題——DAG模型上的動態規劃

硬幣問題

Description

有n種硬幣,面值分別為 V1,V2,…,Vn。每種都有無限多。給定非負整數S,問可以選用多少個硬幣,使得面值之和恰好為S?輸出硬幣數目的最小值和最大值。 1<=n<=100,0<=S<=10000,1<=Vi<=S;

首先確定狀態也就是面值數額,最大值考慮的時候和巢狀矩形類似。

int d[10005];//用來儲存每種面值數額的值
int V[105];	 //用來存放不同種硬幣的面值。
void Initdp()
{
	memset(d,-1,sizeof(d); //這裡要初始化 d陣列。
	return ;
}
int dp(int S) //狀態是面值數額 S { if(d[S]>=0) //為什麼要>=0 而不是大於0 因為當S為0的時候,d[0]=0,所以這種情況要考慮進來 return d[s]; d[s]=0; for(int i=0;i<n;i++) //n代表硬幣的種類數,每一種都嘗試一下 if(V[i]<=S) //如果說當前這個硬幣沒有大於當前的面值額 d[S]=max(d[S],dp(S-V[i])+1); //決策是 選擇這枚硬幣和不選擇這枚硬幣。 return d[s]; }

最終程式碼:

#include <iostream>
#include
<algorithm>
#include <cstring> using namespace std; int d[10005];//用來儲存每種面值數額的值 int V[105]; //用來存放不同種硬幣的面值。 int n; void Initdp() { memset(d,-1,sizeof(d)); //這裡要初始化 d陣列。 return ; } int dp(int S) //狀態是面值數額 S { if(d[S]>=0) //為什麼要>=0 而不是大於0 因為當S為0的時候,d[0]=0,所以這種情況要考慮進來 return d[S]; d[S]=0; for(
int i=0;i<n;i++) //n代表硬幣的種類數,每一種都嘗試一下 if(V[i]<=S) //如果說當前這個硬幣沒有大於當前的面值額 d[S]=max(d[S],dp(S-V[i])+1); //決策是 選擇這枚硬幣和不選擇這枚硬幣。 return d[S]; } int main() { Initdp(); //初始化d陣列 cin>>n; // 輸入硬幣的種數 for(int i=0;i<n;i++) //輸入每種硬幣的面值 cin>>V[i]; int S; //這個是面值額 cin>>S; cout<<dp(S)<<endl; //最後輸出即可 return 0; }

但是又會發現,S有可能走不到 0 也就是說終點

例如 當S=8時 n=1 而 Vi=3時,這時候S就不能走到0 也就是無法找到任何一種方法使得S為0。
但是這個程式也會輸出,經驗證輸出的是2,但是這個是與題意相違背的。那麼我們應該怎麼做呢…

那麼也就可以轉換成這種形式(詳情參考紫書)

int dp(int S)
{
}
	int & ans=d[S];
	if(ans!=-1) return ans;
	ans=-(1<<30);
	for(int i=1;i<n;i+)
		if(S>=V[i])
			ans=max(ans,dp(S-V[i])+1);
	return ans;