Description

【题目描述】

蛤布斯有n个物品和一个大小为m的背包,每个物品有大小和价值,它希望你帮它求出背包里最多能放下多少价值的物品。

【输入数据】

第一行两个整数n,m。接下来n行每行两个整数xi,wi,表示第i个物品的大小和价值。

【输出数据】

一行一个整数表示最大价值。

【样例输入】

5 100

95 80

4 18

3 11

99 100

2 10

【样例输出】

101

【数据范围】

对于20%的数据,xi<=1500。

对于另外30%的数据,wi<=1500。

对于100%的数据,n<=40,0<=m<=10^18,0<=xi,wi<=10^15。


中途相遇法这个东西比较有意思.

这题接近于可行的办法就是暴搜, O(2 ^ n), 但是会炸掉.

不难发现, 假如时间复杂度优化至O(2 ^ (n / 2)), 那么这题就是可以过的, 因此可以这样做:

把所有物品分为左右两半, 2 ^ (n / 2)枚举在同一半中每一种选取物品方案(即从小到大枚举i)所得到的价值以及, 记录入L[i], R[i]中(通过i的二进制拆分来得到当前的具体方案).

将L, R排序, 去掉那些空间大而价值小的方案, 扫一遍利用决策单调性即可得到答案.

附上代码(跑得好慢…)

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxN = 40;
struct item
{
long long size, val;
item(){}
item(long long first, long long second): size(first), val(second){}
}a[maxN], L[1 << (maxN >> 1)], R[1 << (maxN >> 1)];
int operator <(item x, item y)
{
if(x.size == y.size)
return x.val > y.val;
return x.size < y.size;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("pack.in", "r", stdin);
freopen("pack.out", "w", stdout);
#endif
ios::sync_with_stdio(false);
long long n, m;
cin >> n >> m;
for(int i = 0; i < n; i ++)
cin >> a[i].size >> a[i].val;
int mid = n >> 1;
for(int i = 0; i < 1 << (mid); i ++)
{
long long sizeSum = 0, valSum = 0;
for(int j = 0; j < mid; j ++)
if((i >> j) & 1)
sizeSum += a[j].size, valSum += a[j].val;
L[i] = item(sizeSum, valSum);
}
sort(L, L + (1 << mid));
long long cntL = 1;
for(int i = 1; i < 1 << mid; i ++)
if(L[cntL - 1].val < L[i].val)
L[cntL ++] = L[i];
for(int i = 0; i < 1 << (n - mid); i ++)
{
long long sizeSum = 0, valSum = 0;
for(int j = 0; j < n - mid; j ++)
if((i >> j) & 1)
sizeSum += a[mid + j].size, valSum += a[mid + j].val;
R[i] = item(sizeSum, valSum);
}
sort(R, R + (1 << (n - mid)));
long long cntR = 1;
for(int i = 1; i < 1 << (n - mid); i ++)
if(R[cntR - 1].val < R[i].val)
R[cntR ++] = R[i];
long long p = 0, q = cntR - 1;
long long ans = 0;
for(int p = 0; p < cntL; p ++)
{
while(L[p].size + R[q].size > m && q)
q --;
if(L[p].size + R[q].size > m)
continue;
ans = max(ans, L[p].val + R[q].val);
}
cout << ans;
}

中途相遇法 解决 超大背包问题 pack的更多相关文章

  1. 【uva 1152】4 Values Whose Sum is Zero(算法效率--中途相遇法+Hash或STL库)

    题意:给定4个N元素几个A,B,C,D,要求分别从中选取一个元素a,b,c,d使得a+b+c+d=0.问有多少种选法.(N≤4000,D≤2^28) 解法:首先我们从最直接最暴力的方法开始思考:四重循 ...

  2. uva 6757 Cup of Cowards(中途相遇法,貌似)

    uva 6757 Cup of CowardsCup of Cowards (CoC) is a role playing game that has 5 different characters (M ...

  3. LA 2965 Jurassic Remains (中途相遇法)

    Jurassic Remains Paleontologists in Siberia have recently found a number of fragments of Jurassic pe ...

  4. HDU 5936 Difference 【中途相遇法】(2016年中国大学生程序设计竞赛(杭州))

    Difference Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total ...

  5. 【中途相遇法】【STL】BAPC2014 K Key to Knowledge (Codeforces GYM 100526)

    题目链接: http://codeforces.com/gym/100526 http://acm.hunnu.edu.cn/online/?action=problem&type=show& ...

  6. 高效算法——J 中途相遇法,求和

    ---恢复内容开始--- J - 中途相遇法 Time Limit:9000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Su ...

  7. 【UVALive】2965 Jurassic Remains(中途相遇法)

    题目 传送门:QWQ 分析 太喵了~~~~~ 还有中途相遇法这种东西的. 嗯 以后可以优化一些暴力 详情左转蓝书P58 (但可能我OI生涯中都遇不到正解是这个的题把...... 代码 #include ...

  8. uva1152 - 4 Values whose Sum is 0(枚举,中途相遇法)

    用中途相遇法的思想来解题.分别枚举两边,和直接暴力枚举四个数组比可以降低时间复杂度. 这里用到一个很实用的技巧: 求长度为n的有序数组a中的数k的个数num? num=upper_bound(a,a+ ...

  9. LA 2965 中途相遇法

    题目链接:https://vjudge.net/problem/UVALive-2965 题意: 有很多字符串(24),选出一些字符串,要求这些字符串的字母都是偶数次: 分析: 暴力2^24也很大了, ...

随机推荐

  1. LOJ 101 最大流(ISAP 模板)

    开long long的最大流 #include<bits/stdc++.h> using namespace std; ;//点数的最大值 ;//边数的最大值 ; struct Edge ...

  2. 思维水题:UVa512-Spreadsheet Tracking

    Spreadsheet Tracking Data in spreadsheets are stored in cells, which are organized in rows (r) and c ...

  3. jmeter中重要组件及其执行顺序

    jmeter中重要组件有:Sampler,计时器,前置处理器和后置处理器,断言,Controller,Listener和配置原件. 同类组件之间是从上到下的顺序执行,不同组件之间是按照以下的顺序执行的 ...

  4. ADB命令后台修改系统默认输入法

    今天要研究uiautomator如何输入中文,看网上有一种常用的解决办法:http://www.cnblogs.com/yajing-zh/p/5125387.html在这篇博客最后提出来的问题,也是 ...

  5. Educational Codeforces Round 2 Edge coloring of bipartite graph

    题意: 输入一个二分图,用最少的颜色数给它的每条边染色,使得同一个顶点连的边中颜色互不相同. 输出至少需要的颜色数和任意一种染色方案. 分析: 证明不会,只说一下(偷瞄巨巨代码学到的)做法. 假设点的 ...

  6. python网络编程相关

    什么是网络套接字socket?简述基于tcp协议的套接字的通信流程. 为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了称为套接字 (Socket)的接口,区分 ...

  7. nuc 第二届山西省大学生程序设计大赛 魔力手环

    problem 很妙啊--发现状态转移矩阵每一行都可以由上一行平移得到,每次只算第一行然后平移,\(O(n^3)\) 就变成了 \(O(n^2)\). #include <iostream> ...

  8. Android之高效率截图

    本文来自网易云社区 作者:孙圣翔 在一张Android手机上截图有好多办法,为了能够高效率的截图,我几乎把所有的方法都尝试了一般.走了好多路,也遇到了好多的问题. 只是想记录下这其中的不容易. 下面所 ...

  9. 理一理Spring如何对接JUnit

    测试代码 package org.simonme.srcstudy.spring3.demo.stub; import static org.junit.Assert.assertNotNull; i ...

  10. 【bzoj】P4407于神之怒加强版(莫比乌斯反演)

    题目链接 套路一般的枚举$gcd(i,j)=w$.设$min(n,m)=top$,则有 $\sum\limits_{i=1}^{n}\sum\limits_{j=1}{m}gcd(i,j)$ $=\s ...