1. 程式人生 > >hrbust 1558 小揹包(簡單01揹包)水坑

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; }