計蒜客 蒜頭君的購物口袋2 01揹包問題

蒜頭君去超市購物,他有一隻容量爲 V 的購物袋,同時他想買n 件物品,已知每件物品的體積 ivi和重要度pi。蒜頭君想知道,挑選哪些物品放入購物袋中,可以使得買到的物品重要度之和最大,且物品體積和不超過購物袋的容量。

輸入格式

第一行輸入兩個整數 VVV1≤V≤10001 \leq V \leq 10001V1000)和nnn1≤n≤1001 \leq n \leq 1001n100)。代表購物袋的總體積爲VVV,蒜頭君一共想買nnn 件物品。

接下來輸入 nnn 行,每行輸入兩個整數 viv_ivipip_ipi1≤vi,pi≤1001 \leq v_i, p_i \leq 1001vi,pi100),分別表示每件物品的體積和重要度。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) 
{
	int max2=0;
	int v,n,i,j;
	scanf("%d%d",&v,&n);
	int dp[v+10],w[n+10],p[n+10];
	memset(dp,0,sizeof(dp));
	for(i=1;i<=n;i++)
	{
		scanf("%d",&w[i]);
		scanf("%d",&p[i]);
	}
	for(i=1;i<=n;i++)
	{
		for(j=v;j>=w[i];j--)
		{
			dp[j] = max(dp[j-w[i]]+p[i],dp[j]);
			if(max2<=dp[j])
			{
				max2= dp[j];
			}
		}
	}
	printf("%d",max2);
return 0;	
}
int max (int a,int b)
{
	if(a>=b)
	{
		return a;
	}else
	{
	return b;
	}
}

輸出一行,輸出一個整數,表示蒜頭君能買到物品的最大重要度之和。

樣例輸入

樣例輸入

50 4
1 5
60 99
49 8
33 7

樣例輸出

13
我們看到的求最優解的揹包問題題目中,事實上有兩種不太相同的問法。有的題目要求“恰好裝滿揹包”時的最優解,有的題目則並沒有要求必須把揹包裝滿。一種區別這兩種問法的實現方法是在初始化的時候有所不同。

如果是第一種問法,要求恰好裝滿揹包,那麼在初始化時除了f[0]爲0其它f[1..V]均設爲-∞,這樣就可以保證最終得到的f[N]是一種恰好裝滿揹包的最優解。

如果並沒有要求必須把揹包裝滿,而是隻希望價格儘量大,初始化時應該將f[0..V]全部設爲0。

爲什麼呢?可以這樣理解:初始化的f數組事實上就是在沒有任何物品可以放入揹包時的合法狀態。如果要求揹包恰好裝滿,那麼此時只有容量爲0的揹包可能被價值爲0的nothing“恰好裝滿”,其它容量的揹包均沒有合法的解,屬於未定義的狀態,它們的值就都應該是-∞了。如果揹包並非必須被裝滿,那麼任何容量的揹包都有一個合法解“什麼都不裝”,這個解的價值爲0,所以初始時狀態的值也就全部爲0了。

這個小技巧完全可以推廣到其它類型的揹包問題,後面也就不再對進行狀態轉移之前的初始化進行講解。

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