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. dynamic_cast, static_cast, const_cast, reinterprt_cast浅析

    用法:dynamic_cast < type-id > ( expression ) 说明:Type-id必须是类的指针.类的引用或者void *:如果type-id是指针类型,那么exp ...

  2. 2018-8-10-win10-uwp-读取保存WriteableBitmap-、BitmapImage

    title author date CreateTime categories win10 uwp 读取保存WriteableBitmap .BitmapImage lindexi 2018-08-1 ...

  3. 什么是redis

    什么是redis 1.Redis是远程的 有客户端和服务端,客户端和服务端可以布置在不同的机器上,两者经过redis自定义的协议远程传输和交互的,我们一般说的是服务端. 2.Redis是基于内存的 所 ...

  4. Flex AIR应用GPS定位功能(Android和IOS)

    说明: 使用AIR进行GPS定位功能实现时,会经常判断GPS是否打开.一般的官方或者书上的介绍的方法,测试后,只能对Android系统进行判断,而对ios系统则无法进行判断. 经过研究测试,终于解决实 ...

  5. java接口(interface)

    引入:抽象类是从多个类中抽象出来的模板,若要将这种抽象进行得更彻底,就得用到一种特殊的“抽象类”→ 接口; 例子: 生活中听说过的USB接口其实并不是我们所看到的那些插槽,而是那些插槽所遵循的一种规范 ...

  6. CentOS7在防火墙与端口上的操作

    https://jingyan.baidu.com/article/cdddd41cb3bf6c53cb00e1ac.html CentOS7在安装软件包或类库的时候,常常会因为防火墙的拦截和端口未开 ...

  7. 买房的贷款时间是否是越长越好?https://www.zhihu.com/question/20842791

    买房的贷款时间是否是越长越好?https://www.zhihu.com/question/20842791

  8. 为什么有的文件从SVN上更新不下来

    前几天使用eclipse的插件从SVN上更新代码,将全部的代码更新下来后启动项目,前台报错说有些js文件找不到,后来检查我的工程里确实没有那些文件,经过检查发现SVN上却有这些文件,那为什么更新不下来 ...

  9. P1054 全组合

    题目描述 给定n,m,按字典序输出所有从1-n里面取出m个数的组合.比如从1-3里面取出2个的组合是: 1 2 1 3 2 3 输入格式 输入两个数n,m.其中 \(0<n<=10,0&l ...

  10. P1033 沙茶会传染

    题目描述 已知沙茶会传染,而且每一轮每一个沙茶都会传染给另外x个不是沙茶的人,让他们变成沙茶. 已知一开始人群中只有一只沙茶,请问n轮之后人群中会有多少沙茶? 输入格式 两个数 \(x(1 \le x ...