CH2401 送礼物

描述

作为惩罚,GY被遣送去帮助某神牛给女生送礼物(GY:貌似是个好差事)但是在GY看到礼物之后,他就不这么认为了。某神牛有N个礼物,且异常沉重,但是GY的力气也异常的大(-_-b),他一次可以搬动重量和在w(w<=2^31-1)以下的任意多个物品。GY希望一次搬掉尽量重的一些物品,请你告诉他在他的力气范围内一次性能搬动的最大重量是多少。

输入格式

第一行两个整数,分别代表W和N。

以后N行,每行一个正整数表示G[i],G[i]<= 2^31-1。

输出格式

仅一个整数,表示GY在他的力气范围内一次性能搬动的最大重量。

样例输入

20 5
7
5
4
18
1

样例输出

19

数据范围与约定

  • 对于20%的数据 N<=26

    对于40%的数据 W<=2^26

    对于100%的数据 N<=45 W<=2^31-1

思路

这么小的数据。。。一般是搜索吧???这么大的W,用DP做肯定不成,而且也不资瓷离散化。。。。

直接搜?+剪枝?我已经剪不下去了。。。不过80分勉勉强强还可以~

代码(搜索+剪枝)

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define MAXN 50 int N;
LL W, ans;
LL G[MAXN], f[MAXN];//f表示“后缀和” bool cmp( LL x, LL y ){ return x > y; } void DFS( int x, LL h ){//x表示当前搜的是第x件物品,h表示已经取到的总重量
while( x <= N && h + G[x] > W ) x++;//由于是降序排序,找到第一个还能继续搬的物品
if ( x > N ){ ans = max( ans, h ); return; }//没东西了(或者没有可以搬的了),当然得回溯 for ( ; x <= N; ++x ){
if ( h + f[x] <= W ){ ans = max( ans, h + f[x] ); return; }//剪枝~ 后面都能拿,当然要都拿来最优啦~ 这个剪枝可以看做是最优化剪枝
DFS( x + 1, h + G[x] );
}
} int main(){
scanf( "%lld%d", &W, &N );
for ( int i = 1; i <= N; ++i ) scanf( "%lld", &G[i] );
sort( G + 1, G + N + 1, cmp );//剪枝~ 降序排序再搜~
for ( int i = N; i >= 1; --i ) f[i] = f[i + 1] + G[i]; DFS( 1, 0 );
printf( "%lld\n", ans );
return 0;
}

相信大家都不会仅满足于80分~还有俩测试点呢。。。

我们用一种神奇的搜索方式——双向搜索!

也就是说,先找前半段,预处理出所有可以达到的总重量,存在一个数组F中,然后再搜索后半段,对于后半段已取的质量,在F中二分找出既满足条件,又最大的重量,加起来更新ans的值就可以了。这样复杂度就为O(\(2^{\frac n 2 }+2^{\frac n 2 } \times \log_2n\))基本可以满足要求。

代码

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define MAXN 50 int N, M;
LL W, ans;
LL G[MAXN];
LL F[20000000], tot; bool cmp( LL x, LL y ){ return x > y; } void DFS_1( int x, LL h ){//第一次搜索,注意所有能得到的重量都要记录,所以不必剪枝 还有注意0也要记录
F[++tot] = h;
while( x <= M && h + G[x] > W ) x++;
for ( ; x <= M; ++x ) DFS_1( x + 1, h + G[x] );
} int EF( LL x ){//手打二分~
int l(1), r(tot), mid, ans(1);
while( l <= r ){
mid = ( l + r ) >> 1;
if ( F[mid] + x <= W ) l = mid + 1, ans = mid;
else r = mid - 1;
}
return ans;
} void DFS_2( int x, LL h ){
ans = max( ans, h + F[EF(h)] );
while( x <= N && h + G[x] > W ) x++;
for ( ; x <= N; ++x ) DFS_2( x + 1, h + G[x] );
} int main(){
scanf( "%lld%d", &W, &N ); M = ( N >> 1 ) + 2;//lyd大佬说前半段1~N/2+2最快~蒟蒻当然照做
for ( int i = 1; i <= N; ++i ) scanf( "%lld", &G[i] );
sort( G + 1, G + N + 1, cmp );//照样排序 DFS_1( 1, 0 );
sort( F + 1, F + tot + 1 ); tot = unique( F + 1, F + tot + 1 ) - F - 1;//排序&去重
DFS_2( M + 1, 0 );
printf( "%lld\n", ans );
return 0;
}

搜索真是博大精深~

「CH2401」送礼物 解题报告的更多相关文章

  1. 「JSOI2015」送礼物

    「JSOI2015」送礼物 传送门 看到这题首先想到分数规划. 我们发现对于当前区间,如果它的最大值和最小值不是分居区间的两个端点的话,那么我们显然可以把两端多出去的部分舍掉,因为,在区间最大值最小值 ...

  2. 「FJOI2016」神秘数 解题报告

    「FJOI2016」神秘数 这题不sb,我挺sb的... 我连不带区间的都不会哇 考虑给你一个整数集,如何求这个神秘数 这有点像一个01背包,复杂度和值域有关.但是你发现01背包可以求出更多的东西,就 ...

  3. 「ZJOI2016」大森林 解题报告

    「ZJOI2016」大森林 神仙题... 很显然线段树搞不了 考虑离线操作 我们只搞一颗树,从位置1一直往后移动,然后维护它的形态试试 显然操作0,1都可以拆成差分的形式,就是加入和删除 因为保证了操 ...

  4. 「SCOI2016」背单词 解题报告

    「SCOI2016」背单词 出题人sb 题意有毒 大概是告诉你,你给一堆n个单词安排顺序 如果当前位置为x 当前单词的后缀没在这堆单词出现过,代价x 这里的后缀是原意,但不算自己,举个例子比如abc的 ...

  5. 「NOI2015」寿司晚宴 解题报告

    「NOI2015」寿司晚宴 这个题思路其实挺自然的,但是我太傻了...最开始想着钦定一些,结果发现假了.. 首先一个比较套路的事情是状压前8个质数,后面的只会在一个数出现一次的再想办法就好. 然后发现 ...

  6. 「SCOI2015」国旗计划 解题报告

    「SCOI2015」国旗计划 蛮有趣的一个题 注意到区间互不交错,那么如果我们已经钦定了一个区间,它选择的下一个区间是唯一的,就是和它有交且右端点在最右边的,这个可以单调队列预处理一下 然后往后面跳拿 ...

  7. 「JLOI2015」骗我呢 解题报告?

    「JLOI2015」骗我呢 这什么神仙题 \[\color{purple}{Link}\] 可以学到的东西 对越过直线的东西翻折进行容斥 之类的..吧? Code: #include <cstd ...

  8. 「JLOI2015」城池攻占 解题报告

    「JLOI2015」城池攻占 注意到任意两个人的战斗力相对大小的不变的 可以离线的把所有人赛到初始点的堆里 然后做启发式合并就可以了 Code: #include <cstdio> #in ...

  9. 「JLOI2015」管道连接 解题报告

    「JLOI2015」管道连接 先按照斯坦纳树求一个 然后合并成斯坦纳森林 直接枚举树的集合再dp一下就好了 Code: #include <cstdio> #include <cct ...

随机推荐

  1. 04Redis入门指南笔记(内部编码规则简介)

    Redis是一个基于内存的数据库,所有的数据都存储在内存中.所以如何优化存储,减少内存空间占用是一个非常重要的话题.精简键名和键值是最直观的减少内存占用的方式,如将键名very.important.p ...

  2. @loj - 2196@「SDOI2014」Lis

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定序列 A,序列中的每一项 Ai 有删除代价 Bi 和附加属性 ...

  3. VSCode配置启动Vue项目

    下载安装并配置VSCode 随便百度上搜个最新的VSCode安装好后,点击Ctrl + Shit + X打开插件扩展窗口进行插件扩展,这里要安装两个插件. 1.vetur插件的安装 该插件是vue文件 ...

  4. 2018-7-29-C#-强转会不会抛出异常

    title author date CreateTime categories C# 强转会不会抛出异常 lindexi 2018-7-29 14:24:1 +0800 2018-4-4 16:24: ...

  5. 2019-7-29-NetBIOS-计算机名称命名限制

    title author date CreateTime categories NetBIOS 计算机名称命名限制 lindexi 2019-07-29 09:59:17 +0800 2018-12- ...

  6. Scoop 包管理工具 安装

    本人浏览器已经跨域 https://get.scoop.sh 访问该地址成功 安装前提(所需要的环境): 操作环境:win10. 确保你的 PowerShell 版本 >= 3. win7或许低 ...

  7. C++调用Lua编程环境搭建及测试代码示例

    C++调用Lua编程环境搭建及测试代码示例 摘要:测试环境是VS2005+LuaForWindows_v5.1.4-45.exe+WIN7 1.安装lua开发环境LuaForWindows_v5.1. ...

  8. HTTP协议---三次握手

    HTTP协议 关于协议 ​ 对于应用层开发人员,接触最多的网络协议通常都是传输层的TCP,为什么这么说,因为再往上的应用层协议,如:HTTP.HTTPS.POP3.SMTP.RPC.FTP.TELNE ...

  9. [转载] iptables 防火墙设置

    http://hongwei.im/iptables-setting-for-ubuntu-1304/ Iptables是一个防火墙,所有的Ubuntu官方发行版(Ubuntu,Kubuntu,Xub ...

  10. Python--day36--操作系统的作用;多道技术;