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 決策 ...