nyoj 1091 还是01背包(超大数)

nyoj 1091 还是01背包

描述

有n个重量和价值分别为 wi 和 vi 的物品,从这些物品中挑选总重量不超过W的物品,求所有挑选方案中价值总和的最大值

1 <= n <=40

1 <= wi <= 10^15

1 <= vi <= 10^15

1 <= W <= 10^15

分析:在做的时候毫无头绪,在网上看了其他大神的博客才AC了,数据超大无法使用之前的思路(超时且dp数组开不了这么大),但是由本题条件可知n的值非常小,可用递归配合剪枝解题

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define Max(a, b) a > b ? a:b
using namespace std;
typedef long long ll;
const ll INF = 1000000000000000;
ll w[45], v[45];
ll sw[45], sv[45];
ll n, W, ans;
void solve(int i, ll W, ll V) {
    if(i == 0) {
        ans = Max(ans, V);
        return;
    }
    if(W == 0 || ans >= V + sv[i]) return;//背包满或者当前总的加上这个前i个的总价值小于当前的总value,这步是剪枝
    if(W >= sw[i]) {//因为是从上往下找的,所以只要当前容量能装下前i个的和,所以这时一定是最大的 ,剪枝
        V += sv[i];
        ans = Max(ans, V);
        W = 0;
        return;
    }
    if(w[i] <= W) solve(i-1, W - w[i], V + v[i]);
    solve(i-1, W, V);
}
int main() {
    while(cin >> n >> W) {
        ans = -1;
        memset(sw, 0, sizeof(sw));
        memset(sv, 0, sizeof(sv));
        for(int i = 1; i <= n; i++) {
            cin >> w[i] >> v[i];
            sw[i] = sw[i-1] + w[i];
            sv[i] = sv[i-1] + v[i];
        }
        solve(n, W, 0);
        cout << ans << endl;
    }
    return 0;
} 

原文地址:https://www.cnblogs.com/kindleheart/p/8870742.html

时间: 2024-08-28 12:46:05

nyoj 1091 还是01背包(超大数)的相关文章

NYOJ 题目1091 还是01背包(二分,超大01背包)

还是01背包 时间限制:10000 ms  |  内存限制:228000 KB 难度: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

Buy the souvenirs---hdu2126(01背包输出方案数)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2126 有n个物品每个物品的价格是v[i],现在有m元钱问最多买多少种物品,并求出有多少种选择方法: 如果将物品的价格看做容量,将它的件数1看做价值的话,那么用01背包就可以求的花费m钱所能买到的最大件数dp[m]. 但是题目还要求方案数,因此很容易想到再建立一个数组f[j],存储j元钱能买dp[j]个物品的方案数. 在求解01背包的过程中,要分两种情况讨论: 设当前所选的物品为i 1.   若选了物

01背包方案数(变种题)Stone game--The Preliminary Contest for ICPC Asia Shanghai 2019

题意:https://nanti.jisuanke.com/t/41420 给你n个石子的重量,要求满足(Sum<=2*sum<=Sum+min)的方案数,min是你手里的最小值. 思路: 从最大重量的石子开始背包,每次ans+=dp[j-v[i]]就行了. 1 #define IOS ios_base::sync_with_stdio(0); cin.tie(0); 2 #include <cstdio>//sprintf islower isupper 3 #include &

洛谷 P1064 金明的预算方案【DP/01背包-方案数】

题目背景 uim神犇拿到了uoi的ra(镭牌)后,立刻拉着基友小A到了一家--餐馆,很低端的那种. uim指着墙上的价目表(太低级了没有菜单),说:"随便点". 题目描述 不过uim由于买了一些辅(e)辅(ro)书,口袋里只剩M元(M<=10000). 餐馆虽低端,但是菜品种类不少,有N种(N<=100),第i种卖ai元(ai<=1000).由于是很低端的餐馆,所以每种菜只有一份. 小A奉行"不把钱吃光不罢休",所以他点单一定刚好吧uim身上所有钱

hdu2126---Buy the souvenirs(01背包方案数)

Problem Description When the winter holiday comes, a lot of people will have a trip. Generally, there are a lot of souvenirs to sell, and sometimes the travelers will buy some ones with pleasure. Not only can they give the souvenirs to their friends

nyoj 三国志 (Dijkstra + 01背包)

... 总是没思路  真要命 注意两点之间可能有多条权值不同的路径,不过只要在输入时取最小值就好了.. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<string> 6 #include<queue> 7 #include<algorithm> 8 #include<map>

NYOJ 1091 超大01背包(折半枚举)

这道题乍一看是普通的01背包,最最基础的,但是仔细一看数据,发现普通的根本没法做,仔细观察数组发现n比较小,利用这个特点将它划分为前半部分和后半部分这样就好了,当时在网上找题解,找不到,后来在挑战程序设计上找到了这个题,就拿来引用一下 挑选物品的方法总从2^n中,直接枚举肯定不行,因为n最大为40,但是如果n为20就可以了,这时候就要用到折半枚举,先枚举前一半,在枚举后一半.先把前把部分的选取方法对应的重量和价值总和记为w1, v1,这样后半部分寻找w2 <= W - w1时 使v2最大的选取方

nyoj 860 又见01背包 【另类01背包】

分析: 首先这道题不能当做普通的01背包问题,因为W <= 10^9,开不了,那么大的数组,肯定有其他的思路,观察一下我们知道价值v小的很,最大100, 那我们就可以利用这一点,拿价值 之和作为原来的质量之和, 但是有一点要注意:因为题意是要在质量不超过W的范围内,找出最大的价值,我们现在是以最大的价值求质量,那么仔细分析一下,我们就能想明白,要以某价值i的背包存放尽量小的质量,这样反过来分析一下就可以知道,较小的质量有个较大的价值序号,这样完全满足题意了, 最后还有一点,就是价值背包的每一个(

超大背包(挑战编程之01背包)

先来温习01背包: 01背包是在M件物品取出若干件放在空间为W的背包里,每件物品的体积为W1,W2--Wn,与之相对应的价值为P1,P2--Pn. 求出获得最大价值的方案. 注意:在本题中,所有的体积值均为整数. 思路: 考虑用动态规划的方法来解决,这里的:阶段是:在前N件物品中,选取若干件物品放入背包中:状态是:在前N件物品中,选取若干件物品放入所剩空间为W的背包中的所能获得的最大价值:决策是:第N件物品放或者不放:由此可以写出动态转移方程:我们用f[i,j]表示在前 i 件物品中选择若干件放