前言

蒟弱本来是在亿万年前做二分答案专题栅栏的,由于数据水所以过掉了,后来发现有一个数据加强版,也就是本题,于是爆T了...过了有个五六个月回来填坑了...现在开O2是在最优解第一个(自豪ing

题目描述

有 \(n\) 块 大小分别为 \(a_i\) 的蛋糕,分给 \(m\) 个嘴大小分别为 \(b_i\) 的人,但是蛋糕只能以整块的形式给人,求最多给多少人。

思路

很明显,答案在排序之后具有单调性,所以可以二分能够分给多少人,但二分并没有一个明确的套路切蛋糕,所以需要进行深搜;

于是来考虑最优贪心策略:

  1. 首先将所有蛋糕和嘴的大小排序,优先喂嘴小的人;

对应着这两行:

n=read();F(i,1,n)a[i]=read(),tot+=a[i];std::sort(a+1,a+n+1);
m=read();F(i,1,m)b[i]=read();std::sort(b+1,b+m+1);
  1. 排完序后,考虑缩小二分范围,我们从小到大求得嘴大小的前缀和,如果到第 \(i\) 个人的嘴大小总和 \(pre_i\) 超过了上面求出的蛋糕大小总和 \(tot\),或者 \(b_i>a[n]\),那么到这里无论如何切都无法满足条件,二分的最大边界就是 \(i-1\) 了。另外,如果蛋糕总和都比最小的嘴小,那么一个也不能满足。

对应着这三行:

if(tot<b[1]){pi(0);return 0;}
F(i,1,m){pre[i]=pre[i-1]+b[i];if(pre[i]>tot||b[i]>a[n]){cnt=i-1;break;}}
if(!cnt)cnt=m;

我们开始二分+深搜:

  1. 在深搜过程中,枚举能够切下够这口嘴吃的蛋糕,切掉后蛋糕总大小要减去嘴的大小。如果这块蛋糕切剩下的不够最小嘴的,那么就相当于这块蛋糕没有用了,蛋糕总大小要再减去没有用的这部分。

也就是这样:

if(a[i]>=b[x]){
a[i]-=b[x];tot-=b[x];
if(a[i]<b[1])tot-=a[i];
}
  1. 显然,当剩下几张嘴的总大小比剩下几块蛋糕的总大小还要大时,方案是不符合的。

也就是这句:

if(pre[x]>tot)return 0;
  1. 当当前搜索到的这口嘴与下一个要搜索的嘴大小相同时,既然已经枚举到了第 \(i\) 块蛋糕,说明第 \(i\) 块蛋糕之前的蛋糕对于这个大小的嘴都是没有正确方案的,于是搜索下一口嘴时就可以直接从第 \(i\) 块蛋糕枚举。

这句话的实现长这样:

if(b[x]==b[x-1])fl=check(x-1,i);else fl=check(x-1,1);

最后无论有没有正确方案都要记得回溯啊!

if(a[i]<b[1])tot+=a[i];
a[i]+=b[x];tot+=b[x];

到最后如果枚举完所有的蛋糕都没有正确方案,就可以直接 \(return\ 0\) 了。

于是本题就可以愉快的结束了~

CODE

#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
namespace EMT{
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void pi(int x){pf("%d",x);}inline void pn(){pf("\n");}inline void ps(int a[],int size){F(i,1,size)pi(a[i]);pn();}
int n,m,a[55],b[1100],ans,cnt,ws,tot,pre[1100];
inline bool check(int x,int st){
if(!x)return 1;
if(pre[x]>tot)return 0;
bool fl=0;
F(i,st,n){
if(a[i]>=b[x]){
a[i]-=b[x];tot-=b[x];
if(a[i]<b[1])tot-=a[i];
if(b[x]==b[x-1])fl=check(x-1,i);else fl=check(x-1,1);
if(a[i]<b[1])tot+=a[i];
a[i]+=b[x];tot+=b[x];
if(fl)return 1;
}
}return 0;
}
inline short main(){
n=read();F(i,1,n)a[i]=read(),tot+=a[i];std::sort(a+1,a+n+1);
m=read();F(i,1,m)b[i]=read();std::sort(b+1,b+m+1);;;;;;
if(tot<b[1]){pi(0);return 0;}
F(i,1,m){pre[i]=pre[i-1]+b[i];if(pre[i]>tot||b[i]>a[n]){cnt=i-1;break;}}
if(!cnt)cnt=m;
int l=1,r=cnt,ans=0;
while(l<=r){
int mid=(l+r)>>1;
if(check(mid,1))l=mid+1,ans=mid;
else r=mid-1;
}
pi(ans);
return 0;
}
}
signed main(){return EMT::main();}

luoguP1528&2329 栅栏&切蛋糕的更多相关文章

  1. 洛谷P1528 切蛋糕 [搜索,二分答案]

    题目传送门 切蛋糕 题目描述 Facer今天买了n块蛋糕,不料被信息组中球球等好吃懒做的家伙发现了,没办法,只好浪费一点来填他们的嘴巴.他答应给每个人留一口,然后量了量每个人口的大小.Facer有把刀 ...

  2. [洛谷P1528] 切蛋糕

    洛谷题目链接:切蛋糕 题目描述 Facer今天买了n块蛋糕,不料被信息组中球球等好吃懒做的家伙发现了,没办法,只好浪费一点来填他们的嘴巴.他答应给每个人留一口,然后量了量每个人口的大小.Facer有把 ...

  3. 刷题总结——切蛋糕(ssoj)

    题目: 切蛋糕 (cake.cpp/c/pas) [问题描述] BG 有一块细长的蛋糕,长度为�. 有一些人要来BG 家里吃蛋糕, BG把蛋糕切成了若干块(整数长度),然后分给这些人.为了公平,每个人 ...

  4. LRJ入门经典-0903切蛋糕305

    原题 LRJ入门经典-0903切蛋糕305 难度级别:B: 运行时间限制:1000ms: 运行空间限制:256000KB: 代码长度限制:2000000B 试题描述 如图所示有一个矩形蛋糕,上面划分成 ...

  5. 洛谷 P1714 切蛋糕 题解

    P1714 切蛋糕 题目描述 今天是小Z的生日,同学们为他带来了一块蛋糕.这块蛋糕是一个长方体,被用不同色彩分成了N个相同的小块,每小块都有对应的幸运值. 小Z作为寿星,自然希望吃到的第一块蛋糕的幸运 ...

  6. TZOJ 3042 切蛋糕(并查集)

    描述 KK是个心灵手巧的好姑娘,她做了一个大蛋糕请她的好朋友们来品尝.这个蛋糕分成n×n个正方形小格,每个小格包含一块水果.KK要把蛋糕切成若干块,显然她不会破坏任意一个小格.无聊的某同学在她切蛋糕时 ...

  7. 切蛋糕(贪心 or 优先队列)

    链接:https://www.nowcoder.com/acm/contest/80/D来源:牛客网 最可爱的applese生日啦,他准备了许多个质量不同的蛋糕,想请一些同学来参加他的派对为他庆生,为 ...

  8. HDOJ 1722--Cake(切蛋糕问题)

    一次生日Party可能有p人或者q人参加,现准备有一个大蛋糕.问最少要将蛋糕切成多少块(每块大小不一定相等),才能使p人或者q人出席的任何一种情况,都能平均将蛋糕分食. Input 每行有两个数p和q ...

  9. 单调队列练习题解(切蛋糕&好消息,坏消息)

    单调队列的练习题解 前言: 在上一篇学习记录中,单调队列给出了几道练习题,因为这两道题的算法以及思路相差无几(几乎可以算是双倍经验quq),所以就在这里集中写一下相关的题解 前置知识: 见:队列专题( ...

随机推荐

  1. IT面试最全逻辑题,收藏后成功率提高10%

    这是小学二年级的数学题: 猫妈妈钓到一些鱼,平均分给了7只小猫,每只小猫分到的鱼和剩下的鱼刚好一样多.猫妈妈最多钓到了多少条鱼? 这个是出来工作后的现场面试题: [1]假设有一个池塘,里面有无穷多的水 ...

  2. java基础---设计模式(3)

    行为型模式 出处:http://blog.csdn.net/zhangerqing 行为型模式包括策略模式.模板方法模式.观察者模式.迭代子模式.责任链模式.命令模式.备忘录模式.状态模式.访问者模式 ...

  3. 永恒之蓝ms17_010漏洞复现

    1.什么是永恒之蓝 永恒之蓝(Eternal Blue)爆发于2017年4月14日晚,是一种利用Windows系统的SMB协议漏洞来获取系统的最高权限,以此来控制被入侵的计算机. 2.SMB协议 SM ...

  4. WIN10 GMSSL编译

    从git上拉取GMSSL代码 从http://gmssl.org/上可以拉取,或者直接从git上https://github.com/guanzhi/GmSSL拉也行. 我是在git上下的,文件为gm ...

  5. C语言:char[]操作

    C语言中char[]的操作函数1.赋值操作在C语言中,char型数组是不可以直接赋值的.例如在如下的代码中,会得到错误: char c1[20] = "women";char c2 ...

  6. SVN教程(包括小乌龟) 全图解

    转载自http://www.cnblogs.com/armyfai/p/3985660.html SVN使用教程总结 SVN简介: 为什么要使用SVN? 程序员在编写程序的过程中,每个程序员都会生成很 ...

  7. Pytest单元测试框架之parametrize参数化

    1.参数化的本质:相同的步骤,但测试数据不同,比如登录的场景 import mathimport pytest# 方式一:分离出Listdef list_Test(): list = [ [2, 2, ...

  8. Appium -- adb monkey操作(一)

    1.Monkey简介在Android的官方自动化测试领域有一只非常著名的"猴子"叫Monkey,这只"猴子"一旦启动,就会让被测的Android应用程序像猴子一 ...

  9. 单细胞分析实录(18): 基于CellPhoneDB的细胞通讯分析及可视化 (上篇)

    细胞通讯分析可以给我们一些细胞类群之间相互调控/交流的信息,这种细胞之间的调控主要是通过受配体结合,传递信号来实现的.不同的分化.疾病过程,可能存在特异的细胞通讯关系,因此阐明这些通讯关系至关重要. ...

  10. CentOS 7安装Python3 笔记

    当前系统为阿里云的CentOS7.3 64位操作系统. 为了能让后续安装的软件(django,uwsgi,nginx等)尽量减少出现bug的几率,先把可能的依赖包都安装上. 一.安装依赖包 yum - ...