NYOJ 860 又见01背包(思维)

2019-01-10 11:16:23 浏览数 (1)

       刚一看这道题以为是01背包的裸题,TLE了一次后发现这是一道拐了个弯的裸题,题中给的物品重量范围太大了,所以我们可以换种思路,把最大价值求出来,然后在dp中用价值去存重量,然后价值从大到小遍历找出第一个不大于题中给的重量,然后输出价值即可。

AC代码:

代码语言:javascript复制
#include <iostream>
#include <cstring>
using namespace std;
const int MAXN = 1000000;
int dp[MAXN];
int w[200];
int v[200];
int m,p;
int main()
{
    while(cin>>m>>p){
      int sum = 0;
    for(int i=0;i<m;i  ){
      cin>>w[i]>>v[i];
      sum =v[i];
    }
    memset(dp,MAXN,sizeof(dp));      // 要求最小值,需要都初始化为最大值
    dp[0] = 0;                       // 这个符合情况,需要单独把dp[0]初始化为0
    for(int i=0;i<m;i  ){            // 01背包按重量存入dp
      for(int j=sum;j>=v[i];j--){
        dp[j] = min(dp[j],dp[j-v[i]] w[i]);
      }
    }
    for(int i=sum;i>=0;i--){    // 从价值最大开始往后遍历
      if(dp[i] <= p){           // 当遍历到第一个dp[i] <= p 时刚好符合题意,输出i即可
        cout<<i<<endl;
        break;
      }
    }
  }
  return 0;
}
/***
   [来源] NYOJ 860
   [题目] 又见01背包
   [大意]
      虽然是一个01背包题,但是数据范围太大,跑下来肯定会TLE所以要换种方式去做,因为要求重量不超过W的最大价值,可以
      反着求最小重量,对应的就是其最大价值。详细看代码注释。
    [输入]
      4 5
      2 3
      1 2
      3 4
      2 2
    [输出]
      7
  */

0 人点赞