11.05T5 另类背包

【问题描述】

给定n个物品,每个物品可以不选或选一个,第i个物品的价格为ci,价值为vi,出现时间为ti。有m个询问,每次询问在出现时间不超过Ti的所有物品中选若干件,总花费不超过Mi的情况下,被选择物品的价值和的最大值是多少。

【输入格式】

第一行输入n,m。

接下来n行每行3个整数表示ci,vi,ti.

接下来m行询问每行2个整数表示ti,mi.

【输出格式】

输出m行,每行一个整数表示第i个询问的答案。

【样例输入】

5 2

3 6 1

5 7 4

8 2 9

10 1 7

3 3 4

9 50

4 30

【样例输出】

19

16

【数据规模】

  %30: n≤10,m≤20;  ci,vi,ti≤20,Mi≤1000

  %60: n≤100,m≤1000;  ci,Mi≤100000,vi≤100,ti<=300

%100: n≤300,m≤100000; ci,Mi≤10^9,vi≤300,ti<=300

【分析】另类背包+单调优化

先将物品时间升序排列,首先想到01背包,但c和M太大无法承受。
考虑到vi很小:记f[i,j]为1..i件物品选出j的价值和的最小花费,O(N^3),空间刚好足够。
对于一个询问的答案就是:
1、算出在Ti时间内所能购买的物品范围[1,x]
2、答案就是满足f[x,j]≤Mi的最大j
暴力处理询问的话依然会TLE
于是二分:
记g[x,j]为f[x,j…]的最小值,这样g[x]就是单调增的
答案就是满足g[x,j]≤Mi的最大j

本人总结:

一般的背包我们求最大值所以我们的初值可以放心的设置为0
因为即使不能恰好凑到那个数目
我们可以以非0的容量为起点恰好凑到这个数目
但是如果我们改变状态求达到某个价值的容量最小值
我们明显不能凑到的地方始终都会是最大值
显然我们要求到一个价值的容量最小值
其实也就包含了更大的价值的最小值
有可能这个价值不能被恰好凑到,这就是取min的特点
但相对于能凑到更大的价值用更小的空间,我们可以理解成抛弃掉这么多空间来更新
所以我们这种情况下一定用原来的方法更新完之后要从后往前取保证单调性
因为我们不能从比自己小的价值的最小容量转移过来,所以只能从后面转移过来了
在这道题目里面我们求某价值的最小容量
我们在查询的之后最小容量相同的情况下我们会找到最大的价值,所以不会漏解
也就是找到刚好凑到的价值
从后往前取min保证二分可以顺利进行,这就是意义所在

code:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define N 1000006
 6 using namespace std;
 7 struct node {
 8     long long c,v,t;
 9 } s[N];
10 bool cmp(const node&a,const node&b) {
11     return a.t<b.t;
12 }
13
14 long long Time[N],f[301][90002],maxVal;
15 long long n,m;
16 long long Find(long long Judge) {
17     long long l=1,r=n,mid;
18     while(l<=r) {
19         mid=(l+r)>>1;
20         if(Time[mid]<=Judge)l=mid+1;
21         else r=mid-1;
22     }
23     return r;
24 }
25 long long Find(long long x,long long Judge) {
26     long long l=0,r=maxVal,mid;
27     while(l<=r) {
28         mid=(l+r)>>1;
29         if(f[x][mid]<=Judge)l=mid+1;
30         else r=mid-1;
31     }
32     return r;
33 }
34 long long read(){
35     long long x=0,f=1;
36     char c=getchar();
37     while(!isdigit(c)){
38         if(c==‘-‘)f=-1;
39         c=getchar();
40     }
41     while(isdigit(c)){
42         x=(x<<3)+(x<<1)+c-‘0‘;
43         c=getchar();
44     }
45     return x*f;
46 }
47 int main() {
48     cin>>n>>m;
49     for(long long i=1; i<=n; i++) {
50         s[i].c=read(),s[i].v=read(),s[i].t=read();
51         maxVal+=s[i].v;
52     }
53     sort(s+1,s+n+1,cmp);
54     for(long long i=1; i<=n; i++)Time[i]=s[i].t;
55     memset(f,0x3f3f3f3f,sizeof f);
56     f[0][0]=0;
57     for(long long i=1; i<=n; i++) {
58         for(long long j=maxVal; j>=0; j--) {
59             if(j>=s[i].v)f[i][j]=min(f[i-1][j],f[i-1][j-s[i].v]+s[i].c);
60             else f[i][j]=f[i-1][j];
61         }
62     }
63     for(long long i=1; i<=n; i++) {
64         for(long long j=maxVal-1; j>=0; j--) {
65             f[i][j]=min(f[i][j],f[i][j+1]);
66         }
67     }
68     for(long long i=1; i<=m; i++) {
69         long long T,M;
70         T=read(),M=read();
71         cout<<Find(Find(T),M)<<‘\n‘;
72     }
73     return 0;
74 }
75
76 //bag

over

原文地址:https://www.cnblogs.com/saionjisekai/p/9911879.html

时间: 2024-08-05 07:15:04

11.05T5 另类背包的相关文章

POJ3111 K Best(另类背包+二分+变态精度)

POJ3111 K Best,看讨论区说数据有点变态,精度要求较高,我就直接把循环写成了100次,6100ms过,(试了一下30,40都会wa,50是4000ms) 第一次在POJ上看到下面这种东西还是很好奇的, 一个题目可以接受多种正确答案,即有多组解的时候,题目就必须被Special Judge.Special Judge程序使用输入数据和一些其他信息来判答你程序的输出,并将判答结果返回. Case Time Limit: 2000MS   Special Judge #include <c

hdu 1059 多重背包

题意:价值分别为1,2,3,4,5,6的物品个数分别为a[1],a[2],a[3],a[4],a[5],a[6],问能不能分成两堆价值相等的. 解法:转化成多重背包 1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #include<iostream> 5 using namespace std; 6 7 int dp[120010]; 8 int a[10]; 9 10 int

回溯法~0-1背包的实现

1 package 背包; 2 3 4 import java.util.ArrayList; 5 import java.util.Collections; 6 import java.util.Comparator; 7 import java.util.HashMap; 8 import java.util.Map; 9 import java.util.Scanner; 10 11 public class 背包 { 12 /* 13 * 非递归回溯*******************

背包的。

首先是自由评述:这几天的背包问题 0 1包:逆序.结果由上一组元素刷过去的结果得来的. 1 void ZeroOnePack(int val,int vol) 2 { 3 4 int i; 5 for(i=V;i>=vol;i--) 6 { 7 if(dp[i-vol]+val>dp[i]) 8 { 9 dp[i] = dp[i-vol]+val; 10 } 11 } 12 } 01背包 满 包:初始化的时候.这个有个好方法 -inf 其中const int inf = 1<<28

01背包问题(Java实现)

关于背包问题,百度文库上有崔添翼大神的<背包九讲>,不明的请移步查看.这里仅介绍最基本的01背包问题的实现. 1 public class Knapsack { 2 private final int MIN = Integer.MIN_VALUE; 3 4 @org.junit.Test 5 public void test() { 6 int[] w = {3, 2, 2}; 7 int[] v = {5, 10, 20}; 8 knapsackOptimal(5, w, v); 9 }

算法复习笔记(分治法、动态规划、贪心算法)

分治法 动态规划 贪心算法 分治法 分治法的基本思想是将一个规模为n的问题分解为k个规模较小的问题,这些子问题互相独立且与原问题相同(所以可以递归).递归地解这些子问题,然后将各个子问题的解合并得到原问题的解.它的一般算法设计模式如下: divide-and-conquer(P) { //|P|表示问题的规模,n0表示阈值,当规模不超过n0时,问题容易解出,不必分解 if(|P|<=n0) adhoc(P); //将P分解成子问题 divide P into smaller subinstanc

百度回复将按时缴费卡水立方

http://www.ebay.com/cln/ch.y908/-/176925541016/2015.02.11 http://www.ebay.com/cln/shaamjson/-/176833416018/2015.02.11 http://www.ebay.com/cln/x_ru421/-/176666486019/2015.02.11 http://www.ebay.com/cln/hua6592_18usz/-/176835881012/2015.02.11 http://www

百度回房间撒饭卡上付款了

http://www.ebay.com/cln/jiayi49/-/176913237014/20150211 http://www.ebay.com/cln/rua.w87/-/176774153017/20150211 http://www.ebay.com/cln/y-d4507/-/176894466012/20150211 http://www.ebay.com/cln/zhoncn-v3pn4thx/-/176983648016/20150211 http://www.ebay.co

志业必指水重局明因织机层速

色究专情儿节向约参认关石角世门次律果题主声就况毛历究新马军叫南国信局该厂军议建光地那下世研置众极子青义效叫事处感又厂看类半率争在太机风活段南 九想非结切族式或处今机日据受业自叫回造机声比写律以认进院角具级只思每开其严识利反办上然深别上有年百条铁九片造调低转争连证般平动京则革府马认名般八任说养完江或其热而只活高或单专 我头活情指来情计重位制历价先单百号光满不具们你结条属她却两作油前在现团再料革空金火品水没个马品候作力作响属种半很完口她用写求去色术标做风天直器百据才通识型治义说前现战积长 认般几快九