揹包問題例題總結
揹包問題之前學了,不過現在又忘得差不多了(可惜之前沒有寫部落格總結),現在結合例題重新複習一下。
例1:
揹包1
Time Limit: 2000/1000ms (Java/Others)
Problem Description:
有 n 個重量和價值分別為Wi,Vi的物品,現從這些物品中挑選出總量不超過 W 的物品,求所有方案中價值總和的最大值。
Input:
輸入包含多組測試用例,每一例的開頭為兩位整數 n、W(1<=n<=10000,1<=W<=1000) ,接下來有 n 行,每一行有兩位整數 Wi、Vi(1<=Wi<=10000,1<=Vi<=100)。
Output:
輸出為一行,即所有方案中價值總和的最大值。
Sample Input:
3 4 1 2 2 5 3 7
Sample Output:
9
附上AC程式碼加解析:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <list>
#include <map>
#include <stack>
#include <queue>
using namespace std;
#define long long ll
int dp[1111];//建立一個dp陣列,用來儲存剩下w重量可用時所擁有的價值最大w,即dp[w] = v
int main()
{
int n,w;
int wi[11111];
int vi[11111];
while(cin >> n >> w)
{
memset(dp,0,sizeof(dp));
for(int i = 0;i < n;i++)
scanf("%d%d",&wi[i],&vi[i]);
for(int i = 0;i < n;i++)//列舉出每個物品
for(int j = w;j >= wi[i];j--)//將剩餘重量從大到小排列,不能從小到大列舉,因為這樣會導致一個物品可能被使用多次
dp[j] = max(dp[j],dp[j-wi[i]]+vi[i]);
printf("%d\n",dp[w]);
}
return 0;
}
例二:
揹包2
Time Limit: 2000/1000ms (Java/Others)
Problem Description:
有 n 個重量和價值分別為Wi,Vi的物品,現從這些物品中挑選出總量剛好為 W 的物品 ,求所有方案中價值總和的最大值。
Input:
輸入包含多組測試用例,每一例的開頭為兩位整數 n、W(1<=n<=10000,1<=W<=1000) ,接下來有 n 行,每一行有兩位整數 Wi、Vi(1<=Wi<=10000,1<=Vi<=100)。
Output:
輸出為一行,即所有方案中價值總和的最大值。若不存在剛好填滿的情況,輸出“-1”。
Sample Input:
3 4 1 2 2 5 2 1 3 4 1 2 2 5 5 1
Sample Output:
6 -1
這題就是上題的改版,附上AC程式碼:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <list>
#include <map>
#include <stack>
#include <queue>
using namespace std;
#define long long ll
int dp[11111];
int main()
{
int n,w;
while(~scanf("%d%d",&n,&w))
{
memset(dp,-1,sizeof(dp));//所有值設定為-1,當dp[i]等於-1時,表示暫時沒有出現剩餘i重量的情況
dp[0] = 0;//設定一個初始值為0
int wi[n],vi[n];
for(int i = 0;i < n;i++)
scanf("%d%d",&wi[i],&vi[i]);
for(int i = 0;i < n;i++)
for(int j = w;j >= wi[i];j--)
if(dp[j-wi[i]] != -1)
dp[j] = max(dp[j],dp[j-wi[i]]+vi[i]);
printf("%d\n",dp[w]);
}
return 0;
}
例3:
揹包3
Time Limit: 2000/1000ms (Java/Others)
Problem Description:
有 n 種(每一種有無數個)重量和價值分別為Wi,Vi的物品,現從這些物品中挑選出總 量不超過 W 的物品,求所有方案中價值總和的最大值。
Input:
輸入包含多組測試用例,每一例的開頭為兩位整數 n、W(1<=n<=10000,1<=W<=1000) ,接下來有 n 行,每一行有兩位整數 Wi、Vi(1<=Wi<=10000,1<=Vi<=100)
Output:
輸出為一行,即所有方案中價值總和的最大值。
Sample Input:
3 4 1 2 2 5 3 7 3 5 2 3 3 4 4 5
Sample Output:
10 7
這題跟第一題類似,如果理解第一題為什麼是把剩餘重量從大到小排列,就能理解為什麼只要這題從小到大排列即可AC
附上AC程式碼:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <list>
#include <map>
#include <stack>
#include <queue>
using namespace std;
#define long long ll
int dp[11111];
int main()
{
int n,w;
while(~scanf("%d%d",&n,&w))
{
memset(dp,0,sizeof(dp));
int wi[n],vi[n];
for(int i = 0;i < n;i++)
scanf("%d%d",&wi[i],&vi[i]);
for(int i = 0;i < n;i++)
for(int j = wi[i];j <= w;j++)//剩餘重量從小到大就能重複利用每個物品,從大到小就只能利用一次
dp[j] = max(dp[j],dp[j-wi[i]]+vi[i]);
printf("%d\n",dp[w]);
}
return 0;
}
例4:
揹包4
Time Limit: 2000/1000ms (Java/Others)
Problem Description:
有 n 個重量和價值分別為Wi,Vi的物品,現從這些物品中挑選出總量不超過 W 的物品,求所有方案中價值總和的最大值。
Input:
輸入包含多組測試用例,每一例的開頭為兩位整數 n、W;接下來有 n 行,每一行有兩位整數 Wi、Vi 其中: 1<=n<=100 1<=W<=1000,000,000 1<=Wi<=10,000,000 1<=Vi<=100。
Output:
輸出為一行,即所有方案中價值總和的最大值。
Sample Input:
4 5 2 3 1 2 3 4 2 2 4 10000000 2 3 2 2 3 3 1 2
Sample Output:
7 10
這題需要轉換下思維,因為按照前面的方法,重量太大,肯定會超時,不過,相對而言,價值卻變小了。如果理解了前面幾題,並轉換了思維,這題應該不難。
附上AC程式碼:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <list>
#include <map>
#include <stack>
#include <queue>
using namespace std;
#define long long ll
int dp[11111];
int main()
{
int n,w;
while(~scanf("%d%d",&n,&w))
{
for(int i = 0;i < 10005;i++)
dp[i] = 1111111111;
dp[0] = 0;
int wi[n],vi[n];
for(int i = 0;i < n;i++)
scanf("%d%d",&wi[i],&vi[i]);
for(int i = 0;i < n;i++)
for(int j = 10005;j >= vi[i];j--)
if(dp[j-vi[i]] != 1111111111 && dp[j-vi[i]]+wi[i] <= w)
dp[j] = min(dp[j],dp[j-vi[i]]+wi[i]);
for(int i = 10004;i >= 0;i--)
if(dp[i] != 1111111111)
{
printf("%d\n",i);
break;
}
}
return 0;
}
相關文章
- 揹包問題解題方法總結
- 揹包題型總結
- 揹包問題
- 揹包問題(01揹包與完全揹包)
- 【leetcode】揹包問題彙總LeetCode
- 資料結構和演算法面試題系列—揹包問題總結資料結構演算法面試題
- ACM 揹包問題ACM
- 01揹包問題
- 【資料結構與演算法】揹包問題總結梳理資料結構演算法
- JavaScript中揹包問題(面試題)JavaScript面試題
- 揹包問題大合集
- 從【零錢兌換】問題看01揹包和完全揹包問題
- JavaScript 揹包問題詳解JavaScript
- 揹包問題的一道經典問題
- 01揹包問題的解決
- 揹包問題----動態規劃動態規劃
- 【動態規劃】揹包問題動態規劃
- Java實現-揹包問題IJava
- Java實現-揹包問題IIJava
- Java實現-揹包問題VIJava
- 揹包問題的演算法演算法
- chapter12-2-揹包問題APT
- 二維費用揹包問題
- 動態規劃 01揹包問題動態規劃
- 【動態規劃】01揹包問題動態規劃
- 動態規劃-01揹包問題動態規劃
- 動態規劃篇——揹包問題動態規劃
- 動態規劃--01揹包問題動態規劃
- leetcode題解(0-1揹包問題)LeetCode
- 基礎揹包問題的一些題目!!
- 【動態規劃】01揹包問題【續】動態規劃
- 【演算法】0-1揹包問題演算法
- 資料結構與演算法——0-1揹包問題資料結構演算法
- 位元組面試演算法題-0,1揹包問題面試演算法
- Codeup 貨幣系統(完全揹包問題)
- 0-1揹包問題(動態規劃)動態規劃
- acm演算法之三大揹包問題ACM演算法
- 01揹包面試題系列(一)面試題