1091-還是01揹包(入門)
阿新 • • 發佈:2019-01-02
1091-還是01揹包
- 記憶體限制:223MB 時間限制:10000ms 特判: No
- 通過數:1 提交數:1 難度:5
題目描述:
有n個重量和價值分別為 wi 和 vi 的物品,從這些物品中挑選總重量不超過W的物品,求所有挑選方案中價值總和的最大值。
輸入描述:
多組測試資料。 每組測試資料第一行輸入n 和 W ,接下來有n行,每行輸入兩個數,代表第i個物品的wi 和 vi。 1 <= n <=40 1 <= wi <= 10^15 1 <= vi <= 10^15 1 <= W <= 10^15
輸出描述:
每組資料輸出一行,代表挑選方案中價值總和的最大值。
樣例輸入:
複製
4 5
2 3
1 2
3 4
2 2
樣例輸出:
7
這題是在01揹包改了一下。這次不妨用dp針對不同價值計算最小的重量。dp[j]=min(dp[j],dp[j-v[i]]+w[i]), j<=n*maxx,
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; const int maxn=1e6+10; ll dp[maxn]; ll wei[maxn],v[maxn]; const int inf=0x3f3f3f3f; int main() { ll n,w; int t; while(~scanf("%lld%lld",&n,&w)) { memset(dp,inf,sizeof(dp)); ll mx=-1; for(int i=0;i<n;i++) { scanf("%lld%lld",&wei[i],&v[i]); mx=max(mx,v[i]); } dp[0]=0; for(int i=0;i<n;i++) for(int j=n*mx;j>=v[i];j--) { dp[j]=min(dp[j],dp[j-v[i]]+wei[i]); } ll j; for(j=n*mx;j>=0&&dp[j]>w;j--); printf("%lld\n",j); } }
改的很巧,既然重量太大,那就dp[j]中j代表著價值,找j價值的最小重量,然後只需找出dp[j]<=W的最大j。出口是dp[0]=0;