UVA 10310

  題意:求面值n用k個金幣組成的方法數。

  思路:一開始直接想到設狀態dp(i,j)爲面值i用j個硬幣表示的方法數,但最後發現沒辦法轉移,看到有人說用無限揹包,可能是我理解不夠深入,交了幾次都WA了,最後查了寫資料,發現需要用到一個結論,即面值i用j個金幣組成的方法數等於面值i用不超過j的面值的金幣組成的方法數。關於證明可以百度,用到了ferrers圖像的性質,這樣一來狀態dp(i,j)表示面值i用面值不超過j的金幣組成的方法數,那麼對於dp(i,j),我們可以選擇用j和不用j,那麼狀態轉移就是dp(i,j)=dp(i-j,j)+dp(i,j-1)。

#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
long long dp[310][310]={0};
char t[50];
int main()
{
	dp[0][0]=1;
	for(int i=0;i<=300;i++)
		for(int j=1;j<=300;j++){
			if(i>=j) dp[i][j]+=dp[i-j][j];
			dp[i][j]+=dp[i][j-1];
		}
	while(cin.getline(t,50)){
		int l=-1,h=-1,n;
		sscanf(t,"%d%d%d",&n,&l,&h);
		l=min(l,300);h=min(h,300);
		if(l==-1) cout<<dp[n][n]<<endl;
		else if(h==-1) cout<<dp[n][l]<<endl;
		else if(l) cout<<dp[n][h]-dp[n][l-1]<<endl;
		else cout<<dp[n][h]<<endl;
	}
	return 0;
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章