【動態規劃】完全揹包問題-瘋狂的採藥

什麼是完全揹包問題?

有N種物品和一個容量爲V的揹包,每種物品都有無限件可用。

第i種物品的體積是c,價值是w。求解將哪些物品裝入揹包可使這些物品的體積總和不超過揹包容量,且價值總和最大。這裏不同之處是每件物品可無限取,這裏就產生了很多可行的優化,比如同體積的有多種物品,則必然可以捨棄價值小的,也可以捨棄體積大於v的。

比較一下01揹包問題:

在M件物品中取出若干件物品放到揹包中,每件物品對應的體積v1,v2,v3,….對應的價值爲w1,w2,w3,,每件物品之多拿一件。

二者的區別就是01揹包裏每件物品至多隻能拿一件,而完全揹包問題中每件物品可以無限拿。

01揹包問題的解決思路是:第i件物品是否放入揹包,取決於總價值的大小。
狀態轉移方程:f[j]=max(f[j],f[j-ti[i]]+v[i]);

for(int i=1;i<=m;i++)
	   for(j=t;j>=t[i];j--)//從右到左計算 
	      f[j]=max(f[j],f[j-ti[i]]+p[i]);

完全揹包問題也是同樣的思路,只是循環的方式不一樣

for(int i=1;i<=m;i++)
	for(int  j=ti[i];j<=t;j++)
	   f[j]=max(f[j],f[j-ti[i]]+v[i]);

下面的題目就是一個完全揹包問題

題目描述

LiYuxiang是個天資聰穎的孩子,他的夢想是成爲世界上最偉大的醫師。爲此,他想拜附近最有威望的醫師爲師。醫師爲了判斷他的資質,給他出了一個難題。醫師把他帶到一個到處都是草藥的山洞裏對他說:“孩子,這個山洞裏有一些不同種類的草藥,採每一種都需要一些時間,每一種也有它自身的價值。我會給你一段時間,在這段時間裏,你可以採到一些草藥。如果你是一個聰明的孩子,你應該可以讓採到的草藥的總價值最大。”

如果你是LiYuxiang,你能完成這個任務嗎?

此題和原題的不同點:

1.每種草藥可以無限制地瘋狂採摘。

2.藥的種類眼花繚亂,採藥時間好長好長啊!師傅等得菊花都謝了!

輸入格式

輸入第一行有兩個整數T(1 <= T <= 100000)和M(1 <= M <= 10000),用一個空格隔開,T代表總共能夠用來採藥的時間,M代表山洞裏的草藥的數目。接下來的M行每行包括兩個在1到10000之間(包括1和10000)的整數,分別表示採摘某種草藥的時間和這種草藥的價值。

輸出格式

輸出一行,這一行只包含一個整數,表示在規定的時間內,可以採到的草藥的最大總價值。

輸入輸出樣例
輸入 #1
70 3
71 100
69 1
1 2
輸出 #1
140

代碼:

#include<iostream>
#include <algorithm>
using namespace std;

int t,m;
int ti[10001],v[10001]; 
int f[100001];
//這是一個完全揹包問題
//大概明白了,與01揹包不同的是完全揹包問題中每件物品的數量是無限的
//01揹包每件物品只有一個 ,就放一次 
//狀態轉移方程到底是怎麼列出來的明白了,就是這個東西放還是不放的問題
//爲什麼,一個順序一個逆序結果就不同了? 需要在捉摸一下
int main(){
	
	cin>>t>>m;
	for(int i=1;i<=m;i++)
	    cin>>ti[i]>>v[i];
	//完全揹包的狀態轉移方程 
	for(int i=1;i<=m;i++)
	for(int  j=ti[i];j<=t;j++)
	   f[j]=max(f[j],f[j-ti[i]]+v[i]);	
	//01揹包的狀態轉移方程
	//for(int i=1;i<=m;i++)
	//for(int j=t;j>=t[i];j--)
	//   f[j]=max(f[j],f[j-ti[i]]+v[i]);	
	cout<<f[t];
	return 0;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章