Atcoder E - Knapsack 2 (01背包进阶版 ex )

E - Knapsack 2



Time Limit: 2 sec / Memory Limit: 1024 MB

Score : 100100 points

Problem Statement

There are NN items, numbered 1,2,…,N1,2,…,N. For each ii (1≤i≤N1≤i≤N), Item ii has a weight of wiwi and a value of vivi.

Taro has decided to choose some of the NN items and carry them home in a knapsack. The capacity of the knapsack is WW, which means that the sum of the weights of items taken must be at most WW.

Find the maximum possible sum of the values of items that Taro takes home.

Constraints

  • All values in input are integers.
  • 1≤N≤1001≤N≤100
  • 1≤W≤1091≤W≤109
  • 1≤wi≤W1≤wi≤W
  • 1≤vi≤1031≤vi≤103

Input

Input is given from Standard Input in the following format:

NN WW
w1w1 v1v1
w2w2 v2v2
::
wNwN vNvN

Output

Print the maximum possible sum of the values of items that Taro takes home.


Sample Input 1 Copy

Copy

3 8
3 30
4 50
5 60

Sample Output 1 Copy

Copy

90

Items 11 and 33 should be taken. Then, the sum of the weights is 3+5=83+5=8, and the sum of the values is 30+60=9030+60=90.


Sample Input 2 Copy

Copy

1 1000000000
1000000000 10

Sample Output 2 Copy

Copy

10

Sample Input 3 Copy

Copy

6 15
6 5
5 6
6 4
6 6
3 5
7 2

Sample Output 3 Copy

Copy

17

Items 2,42,4 and 55 should be taken. Then, the sum of the weights is 5+6+3=145+6+3=14, and the sum of the values is 6+6+5=176+6+5=17.

题目链接:https://atcoder.jp/contests/dp/tasks/dp_e

思路:体积虽然很huge,但价值很小。把最大化价值,转成最小化体积,就还是原来的01背包了。(RUSH_D_CAT大佬指点的)

很不错的一个背包优化的思路,细节见我的代码。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), ‘\0‘, sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
using namespace std;
typedef long long ll;
inline void getInt(int* p);
const int maxn=1000010;
const int inf=0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
ll dp[maxn];
ll n,W;
ll v[maxn];
ll w[maxn];
int main()
{
    memset(dp,0x3f,sizeof(dp));
    gbtb;
    cin>>n>>W;
    repd(i,1,n)
    {
        cin>>w[i]>>v[i];
    }
    ll ans=0ll;
    dp[0]=0;
    repd(i,1,n)
    {
        for(int j=1e5;j>=v[i];--j)
        {
            {
                dp[j]=min(dp[j],dp[j-v[i]]+w[i]);
                if(dp[j]<=W)
                    ans=max(ans,(ll)(j));
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}

inline void getInt(int* p) {
    char ch;
    do {
        ch = getchar();
    } while (ch == ‘ ‘ || ch == ‘\n‘);
    if (ch == ‘-‘) {
        *p = -(getchar() - ‘0‘);
        while ((ch = getchar()) >= ‘0‘ && ch <= ‘9‘) {
            *p = *p * 10 - ch + ‘0‘;
        }
    }
    else {
        *p = ch - ‘0‘;
        while ((ch = getchar()) >= ‘0‘ && ch <= ‘9‘) {
            *p = *p * 10 + ch - ‘0‘;
        }
    }
}

原文地址:https://www.cnblogs.com/qieqiemin/p/10274855.html

时间: 2024-10-08 08:04:18

Atcoder E - Knapsack 2 (01背包进阶版 ex )的相关文章

0-1 背包 改良版

#include <cstdio> #include <cstring> using namespace std; const int maxn = 200; template <class Type> void Traceback(int n,Type w[],Type v[],Type p[maxn][maxn],int *head,int x[]); template <class Type> Type Knapsack(int n,Type c,Ty

FZU 2214 ——Knapsack problem——————【01背包的超大背包】

2214 Knapsack problem Accept: 6    Submit: 9Time Limit: 3000 mSec    Memory Limit : 32768 KB  Problem Description Given a set of n items, each with a weight w[i] and a value v[i], determine a way to choose the items into a knapsack so that the total

FZU 2214 Knapsack problem (01背包)

题意:给你n种物品,每种只有一个,第i种物品的价值为Vi,重量为Wi,把这些物品放入一个重量限制为B的背包中,使得背包内的物品在重量不超过B的前提下,价值尽量大,输出最大价值 1 <= n <= 500 1 <= B, w[i] <= 1000000000 1 <= v[1]+v[2]+...+v[n] <= 5000 思路:我们从范围中可以看到这个物品的重量和背包所能承受的重量特别大,我们不能使用常规的01背包,我们可以把问题转化一下,我们定义d(i,j)是把第i个物

c++01背包一维数组版及java多重背包

#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=1010; int c[maxn],w[maxn]; int dp[maxn]; int main(){ int n,v; cin>>n>>v; for(int i=1;i<=n;i++) cin>>c[i]; for(int i=1;i<=n;i++) cin>>w[i];

01背包//简直要被这道题玩死(掀桌)

先上链接: 表格什么的最清楚了:http://blog.csdn.net/mu399/article/details/7722810 dd大大的背包九讲: —————————————————— 01背包的状态转换方程 f[i,j] = Max{ f[i-1,j-Wi]+Pi( j >= Wi ),  f[i-1,j] } f[i,j]表示在前i件物品中选择若干件放在承重为 j 的背包中,可以取得的最大价值. Pi表示第i件物品的价值. 决策:为了背包中物品总价值最大化,第 i件物品应该放入背包中

0-1背包-回溯法

算法描述: 0-1背包的回溯法,与装载问题的回溯法十分相似.在搜索解空间树时,只要其左儿子结点是一个可行结点,搜索就进入其左子树.当右子树中有可能包含最优解时才进入右子树进行搜索.否则将右子树剪去. 计算右子树上界的更好算法是: 将剩余物品依其单位重量价值排序,然后依次装入物品,直至装不下时,再装入该物品的一部分而装满背包. 算法实现: 由Bound函数计算当前节点处的上界. 类Knap的数据成员记录解空间树的节点信息,以减少参数传递及递归调用所需的栈空间. 在解空间树的当前扩展结点处,仅当要进

装箱问题(0-1背包)

有一批共n个集装箱要装上艘载重量为c的轮船,其中集装箱i的重量为wi.找出一种最优装载方案,将轮船尽可能装满,即在装载体积不受限制的情况下,将尽可能重的集装箱装上轮船. #include <iostream> #define MAX 12882 using namespace std; struct node { int w; }data[MAX]; int dp[MAX],n,m; void Init() { int i; for(i=1;i<=n;i++) scanf("%

出差之前写一个0-1背包的程序吧

又要出差了,也不知道多久才能回来,这段时间应该都不能更新博客了,写了0-1背包程序热热手吧. 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #define MAX_NUM 20 //物品最大个数 5 #define MAX_PACK 100 //背包容量 6 7 int result[MAX_NUM][MAX_PACK]; //全局变量默认初始化0 8 9 /* 10 * 0 1背包问题动态规划方程 11 * 12 * m[i][j]

01背包 模板1

// 0-1背包问题的普通递归算法#include <stdio.h>#define M 10int w[M]={5,3,2,1},v[M]={4,4,3,1};int limit_w=7,maxv=0,n=4; void find(int i,int tw,int tv) //从第i种物品开始,当前已有的重量tw和价值tv{ if (i<n) //进入第i+1件的条件,还没有选完n种物品 if (tw+w[i]<=limit_w ) //选择第i件物品 find(i+1,tw+w