「CH2401」送礼物 解题报告
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」送礼物 解题报告的更多相关文章
- 「JSOI2015」送礼物
「JSOI2015」送礼物 传送门 看到这题首先想到分数规划. 我们发现对于当前区间,如果它的最大值和最小值不是分居区间的两个端点的话,那么我们显然可以把两端多出去的部分舍掉,因为,在区间最大值最小值 ...
- 「FJOI2016」神秘数 解题报告
「FJOI2016」神秘数 这题不sb,我挺sb的... 我连不带区间的都不会哇 考虑给你一个整数集,如何求这个神秘数 这有点像一个01背包,复杂度和值域有关.但是你发现01背包可以求出更多的东西,就 ...
- 「ZJOI2016」大森林 解题报告
「ZJOI2016」大森林 神仙题... 很显然线段树搞不了 考虑离线操作 我们只搞一颗树,从位置1一直往后移动,然后维护它的形态试试 显然操作0,1都可以拆成差分的形式,就是加入和删除 因为保证了操 ...
- 「SCOI2016」背单词 解题报告
「SCOI2016」背单词 出题人sb 题意有毒 大概是告诉你,你给一堆n个单词安排顺序 如果当前位置为x 当前单词的后缀没在这堆单词出现过,代价x 这里的后缀是原意,但不算自己,举个例子比如abc的 ...
- 「NOI2015」寿司晚宴 解题报告
「NOI2015」寿司晚宴 这个题思路其实挺自然的,但是我太傻了...最开始想着钦定一些,结果发现假了.. 首先一个比较套路的事情是状压前8个质数,后面的只会在一个数出现一次的再想办法就好. 然后发现 ...
- 「SCOI2015」国旗计划 解题报告
「SCOI2015」国旗计划 蛮有趣的一个题 注意到区间互不交错,那么如果我们已经钦定了一个区间,它选择的下一个区间是唯一的,就是和它有交且右端点在最右边的,这个可以单调队列预处理一下 然后往后面跳拿 ...
- 「JLOI2015」骗我呢 解题报告?
「JLOI2015」骗我呢 这什么神仙题 \[\color{purple}{Link}\] 可以学到的东西 对越过直线的东西翻折进行容斥 之类的..吧? Code: #include <cstd ...
- 「JLOI2015」城池攻占 解题报告
「JLOI2015」城池攻占 注意到任意两个人的战斗力相对大小的不变的 可以离线的把所有人赛到初始点的堆里 然后做启发式合并就可以了 Code: #include <cstdio> #in ...
- 「JLOI2015」管道连接 解题报告
「JLOI2015」管道连接 先按照斯坦纳树求一个 然后合并成斯坦纳森林 直接枚举树的集合再dp一下就好了 Code: #include <cstdio> #include <cct ...
随机推荐
- 04Redis入门指南笔记(内部编码规则简介)
Redis是一个基于内存的数据库,所有的数据都存储在内存中.所以如何优化存储,减少内存空间占用是一个非常重要的话题.精简键名和键值是最直观的减少内存占用的方式,如将键名very.important.p ...
- @loj - 2196@「SDOI2014」Lis
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定序列 A,序列中的每一项 Ai 有删除代价 Bi 和附加属性 ...
- VSCode配置启动Vue项目
下载安装并配置VSCode 随便百度上搜个最新的VSCode安装好后,点击Ctrl + Shit + X打开插件扩展窗口进行插件扩展,这里要安装两个插件. 1.vetur插件的安装 该插件是vue文件 ...
- 2018-7-29-C#-强转会不会抛出异常
title author date CreateTime categories C# 强转会不会抛出异常 lindexi 2018-7-29 14:24:1 +0800 2018-4-4 16:24: ...
- 2019-7-29-NetBIOS-计算机名称命名限制
title author date CreateTime categories NetBIOS 计算机名称命名限制 lindexi 2019-07-29 09:59:17 +0800 2018-12- ...
- Scoop 包管理工具 安装
本人浏览器已经跨域 https://get.scoop.sh 访问该地址成功 安装前提(所需要的环境): 操作环境:win10. 确保你的 PowerShell 版本 >= 3. win7或许低 ...
- C++调用Lua编程环境搭建及测试代码示例
C++调用Lua编程环境搭建及测试代码示例 摘要:测试环境是VS2005+LuaForWindows_v5.1.4-45.exe+WIN7 1.安装lua开发环境LuaForWindows_v5.1. ...
- HTTP协议---三次握手
HTTP协议 关于协议 对于应用层开发人员,接触最多的网络协议通常都是传输层的TCP,为什么这么说,因为再往上的应用层协议,如:HTTP.HTTPS.POP3.SMTP.RPC.FTP.TELNE ...
- [转载] iptables 防火墙设置
http://hongwei.im/iptables-setting-for-ubuntu-1304/ Iptables是一个防火墙,所有的Ubuntu官方发行版(Ubuntu,Kubuntu,Xub ...
- Python--day36--操作系统的作用;多道技术;