一本通上的某動態規劃題:糖果(openjudge->NOI->2.6->2989)

題目:

2989:糖果

總時間限制:
1000ms
內存限制:
65536kB
描述
由於在維護世界和平的事務中做出巨大貢獻,Dzx被贈予糖果公司2010年5月23日當天無限量糖果免費優惠券。在這一天,Dzx可以從糖果公司的N件產品中任意選擇若干件帶回家享用。糖果公司的N件產品每件都包含數量不同的糖果。Dzx希望他選擇的產品包含的糖果總數是K的整數倍,這樣他才能平均地將糖果分給幫助他維護世界和平的夥伴們。當然,在滿足這一條件的基礎上,糖果總數越多越好。Dzx最多能帶走多少糖果呢?
注意:Dzx只能將糖果公司的產品整件帶走。
輸入
第一行包含兩個整數N(1<=N<=100)和K(1<=K<=100)
以下N行每行1個整數,表示糖果公司該件產品中包含的糖果數目,不超過1000000
輸出
符合要求的最多能達到的糖果總數,如果不能達到K的倍數這一要求,輸出0
樣例輸入
5 7
1
2
3
4
5
樣例輸出
14
提示
Dzx的選擇是2+3+4+5=14,這樣糖果總數是7的倍數,並且是總數最多的選擇。

這道題目運用“模”得的餘數來儲存“同類情況”,數組:f[第i個數][除以k得餘數j]=到第i個爲止除以k能等於j的最大加和。

代碼如下:

#include<iostream>
using namespace std;
int a,n,k,f[101][101];
int main()
{
	cin>>n>>k;
	for(int i=1;i<=n;i++)
	{
		cin>>a;
		f[i][a%k]=a;//將同餘數的儲存在一列,儲存的是可取得該餘數的值,只取此數是必有的一種情況 
		
		for(int j=0;j<k;j++)
			if(f[i-1][j])//只有出現過的餘數,才說明之前存在過至少一種情況供你和當前a加和 
				f[i][(j+a)%k]=f[i-1][j]+a;
				
		for(int j=0;j<k;j++)//每次都更新一下本餘數最大值 ,篩去無關情況 
			f[i][j]=max(f[i][j],f[i-1][j]);
	}
	cout<<f[n][0];
	return 0;
}

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