揹包問題詳解

2022-04-10 18:57:48 字數 4111 閱讀 1344

nyoj289蘋果(01揹包)

時間限制:3000 ms  |  記憶體限制:65535 kb

難度:3

描述

ctest有n個蘋果,要將它放入容量為v的揹包。給出第i個蘋果的大小和價錢,求出能放入揹包的蘋果的總價錢最大值。

輸入

有多組測試資料,每組測試資料第一行為2個正整數,分別代表蘋果的個數n和揹包的容量v,n、v同時為0時結束測試,此時不輸出。接下來的n行,每行2個正整數,用空格隔開,分別代表蘋果的大小c和價錢w。所有輸入數字的範圍大於等於0,小於等於1000。

輸出

對每組測試資料輸出乙個整數,代表能放入揹包的蘋果的總價值。

樣例輸入

3 31 1

2 13 1

0 0樣例輸出

2#include

#include

#define n 1001

int dp[n];

int max(int a,int b)

if(a>b)

return a;

else

return b;

int main()

int n,v,i,j,c,w;

while(scanf("%d %d",&n,&v))

if(n==0&&v==0)

break;

memset(dp,0,sizeof(dp));

for(i=1;i<=n;i++)

scanf("%d %d",&c,&w);

for(j=v;j>=c;j--)

dp[j]=max(dp[j],dp[j-c]+w);

printf("%d\n",dp[v]);

return 0;

時間限制:1000 ms  |  記憶體限制:65535 kb

難度:3

描述

有n個重量和價值分別為wi 和 vi 的 物品,從這些物品中選擇總重量不超過 w 

的物品,求所有挑選方案中物品價值總和的最大值。

1 <= n <=100

1 <= wi <= 10^7

1 <= vi <= 100

1 <= w <= 10^9

輸入

多組測試資料。

每組測試資料第一行輸入,n

和 w ,接下來有n行,每行輸入兩個數,代表第i個物品的wi 和 vi。

輸出

滿足題意的最大價值,每組測試資料佔一行。

樣例輸入

4 5
2 3
1 2
3 4
2 2

樣例輸出

7

這道題其實和一般的01揹包沒有什麼區別,只是這道題目按照正常的思維去做不行了,因為容量太大,開個10^9的陣列開不了,所以這時候就需要換種思維,這個題剛開始沒理解,後來在網上在題解,發現都說是互換重量和價值,但是一直沒理解什麼意思,後來,仔細想了想那個最最基礎的01揹包是怎麼推出來的才想通了, 也不能說是互換價值和重量,那樣其實並不能加深理解,做完這個題之後,發現又對揹包理解深了一點,寫個部落格,留下紀念

這道題很容易發現其實重量很大,達到10^9,但是價值很小啊,現在就來推一下這個所謂的「互換」是怎麼來的 (其實我覺得還不如從最原始的來,不叫做「互換」好理解點), 最原始的那個式子

dp[i][j]表示當取 i 個, 重量為 j 的時候揹包的最大價值,狀態轉移方程就是 dp[i][j] = max(dp[i - 1][j], dp[i-1][j - weight[i]] + value[i]), 這個式子的意思想必大家都明白吧,前面的那個意思是不取當前這個,後面的這個是取上當前這個物品, 後來再經空間優化之後變成了dp[j] = max(dp[j], dp[j - weight[i]] + value[i]), 仔細觀察會發現二維陣列時,那兩種狀態都是i - 1,所以就可以去掉,但是得注意,迴圈遍歷的時候要逆序,正序的話就成完全揹包了, 忘了說這個dp[j]表示什麼了, dp[j]就是 當取到重量為j 的時候的最大價值。弄明白了這些。這時候就可以來看這個題了, 題目要求和普通的01揹包一樣,求能裝的最大價值,普通方法就是直接找最大價值,現在要換種思維,找最小的重量, 因為同樣價值,重量越小,那麼最後能裝的價值就可能越大,所以這個dp[i][j]就表示 當 取 i 個, 價值為j 的時候的最小重量,狀態轉移方程為 dp[i][j] = min(dp[i - 1][j], dp[i - 1][j - value[i]] + weight[i]), 和那個最初推的一樣,不再羅嗦,空間優化之後狀態轉移方程為dp[j] = min(dp[j], dp[j - value[i]] + weight[i]), 同樣的意思,dp[j]表示 價值為j 的時候的最小重量,到最後只要從最大價值往下遍歷這個dp陣列,只要找到dp[j] <= 揹包重量的時候就直接輸出 j , 這時候j就是最大的。

#include

#include

#define min(a,b) a#define n 10003

int dp[n];

int weight[102];

int value[102];

int main()

int n,w;

while(~scanf("%d %d",&n,&w))

int sum=0;

for(int i=0;iscanf("%d%d",&weight[i],&value[i]);

sum+=value[i];

memset(dp,111,sizeof(dp));

dp[0]=0;

for(int i=0;ifor(int j=sum;j>=value[i];j--)

dp[j]=min(dp[j],dp[j-value[i]]+weight[i]);

for(int i=sum;i>=0;i--)

if(dp[i]<=w)

printf("%d\n",i);

break;

return 0;

nyoj311完全揹包

時間限制:3000 ms  |  記憶體限制:65535 kb

難度:4

描述

直接說題意,完全揹包定義有n種物品和乙個容量為v的揹包,每種物品都有無限件可用。第i種物品的體積是c,價值是w。求解將哪些物品裝入揹包可使這些物品的體積總和不超過揹包容量,且價值總和最大。本題要求是揹包恰好裝滿揹包時,求出最大價值總和是多少。如果不能恰好裝滿揹包,輸出no

輸入

第一行: n 表示有多少組測試資料(n<7)。 

接下來每組測試資料的第一行有兩個整數m,v。 m表示物品種類的數目,v表示揹包的總容量。(0輸出

對應每組測試資料輸出結果(如果能恰好裝滿揹包,輸出裝滿揹包時揹包內物品的最大價值總和。 如果不能恰好裝滿揹包,輸出no)

樣例輸入

21 5

2 22 5

2 25 1

樣例輸出no1

#include

#include

int d[50001];

int main()

int n,i,j;

int c,v,a,b;

scanf("%d",&n);

while(n--)

scanf("%d%d",&c,&v);

memset(d,-11,sizeof(d));

d[0]=0;

for(i=0;iscanf("%d%d",&a,&b);

for(j=a;j<=v;j++)

if(d[j]d[j]=d[j-a]+b;

if(d[v]<0)

printf("no\n");

else

printf("%d\n",d[v]);

return 0;

揹包問題詳解

問題描述 有n件物品和乙個容量為v的揹包。第i件物品的重量是w i 價值是p i 求解將哪些物品裝入揹包可使這些物品的總重量不超過揹包容量,且價值總和最大。思路 每種物品僅有一件,可以選擇放或不放。f i,v 表示前i件物品放入乙個容量為v的揹包可以獲得的最大價值。狀態轉移方程為 f i,v max...

揹包問題系列詳解

揹包問題是乙個關於最優解的經典問題。通常被討論的最多的,最經典的揹包問題是0 1揹包問題 0 1 knapsack problem 它是一切揹包問題及相關揹包問題的基礎。本篇博文將詳細分析0 1揹包問題,並給出0 1揹包問題的幾種解法,同時也對0 1揹包問題的內涵進行延伸,豐富其外延至完全揹包問題和...

01揹包問題詳解

01揹包問題簡單描述 有乙個揹包和n個物品,揹包的承載量為c,每件物品重量為w i 價值為v i 問如何裝才能使揹包中物品的總價值最大?解題方法 f i,j 在前i個物品中選擇若干件放在承重為j的揹包中,可以取得的最大的價值。f i,j max f i 1,j w i v i f i 1,j 決策 ...