hrbust 1558 小揹包(簡單01揹包)水坑
小揹包
Time Limit: 1000 MS Memory Limit: 10240 K
Total Submit: 1220(237 users) Total Accepted: 307(208 users) Rating: Special Judge: No
Description
有一個容量為m(1<=m<=4000000)的揹包,有n(1<=n<=16)個物品,每個物品有體積v(1<=v<=2012)和價值w(0<=2012),現在要你選擇一些物品,使得揹包所裝物品的總價值最大。
Input
有多組測試資料,但是不會超過10組。
對於每組測試資料,第一行是兩個整數m和n,表示揹包容量的和物品個數。接下來有n行,每行有兩個整數,表示一個物品的體積和價值。
輸入到檔案結束。
Output
對於每組測試資料,輸出一行,包含一個整數,為揹包能裝下物品的最大價值。
Sample Input
10 3
6 9
5 5
5 5
3 2
1 2
2 1
Sample Output
10
3
過程都只是一個普通的小揹包,注意坑點在最大容積,第一眼看,可能覺得一定會超時爆記憶體,結果再往後面看發現只有16個物品,再往後看,每個物品最大隻有2012,也就是說總重不會超過16*2012,揹包容積最大值遠大於物品體積,此時,dp陣列只用設到33000左右就好,但為防止m過大,畢竟是要這個資料帶入進去遍歷dp陣列的,所以即使沒裝那麼多,也會遍歷陣列遍歷到爆,RE就不可避免了。於是多加個判定條件,當容積遠遠大於所有物品體積時,直接全部裝進去就好了,不用再執行後面的演算法。這樣也是有道理的,畢竟你陣列就是最大體積了,容積再大,也是都可以裝進去的了,不僅省時還能避免陣列越界
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int dp[20][34000];///好坑啊,題目說了揹包那麼大,但是實際16個物品每個物品2012的體積,根本用不了那麼大
struct box
{
int cost;
int value;
}num[20];
int main()
{
int i,j,n,m;
while(scanf("%d%d",&m,&n)!=EOF)
{
int sum=0 ,sum2=0;
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++)
{
scanf("%d%d",&num[i].cost,&num[i].value);
sum=sum+num[i].cost;
sum2=sum2+num[i].value;
}
if(sum<m)///注意自己輸入的是m,即使合在一起的體積沒那麼大,容積還是會在遍歷時用到m的數值,而發生陣列越界,因此注意
{
printf("%d\n",sum2);///當輸入的容積大於總體積時,可以直接輸出所有的價值和,不用一個一個裝上去了
continue;
}
for(i=num[1].cost;i<=m;i++)
{
dp[1][i]=num[1].value;
}
for(i=2;i<=n;i++)
{
for(j=1;j<=m;j++)
{
if(j>=num[i].cost)
{
dp[i][j]=max(dp[i-1][j],dp[i-1][j-num[i].cost]+num[i].value);///記住啊,容積減掉當前遍歷的那個物品的體積,個數也要減掉一個誒
}
else
dp[i][j]=dp[i-1][j];///是物品-1,不是容積-1,是如果裝不了,那就繼承上面那個物品的在此容積下的價值!!!
}
}
// for(i=0;i<=n;i++)///動態規劃表超美的
// {
// for(j=0;j<=m;j++)
// {
// printf(" %d",dp[i][j]);
// }
// printf("\n");
// }
printf("%d\n",dp[n][m]);
}
return 0;
}