前言

蒟弱本来是在亿万年前做二分答案专题栅栏的,由于数据水所以过掉了,后来发现有一个数据加强版,也就是本题,于是爆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. Django基础-04篇 Django开发前后端联动

    1. 写views views.py代码块 1.在前端以/article/{{ article.id }}这种方式请求后台, 参数配置在urls.py中path('category/<int:i ...

  2. python 模拟点击微信

    from PyQt5 import QtCore,QtWidgets import win32gui, win32api, win32con # 调用win32api的模拟点击功能实现ctrl+v粘贴 ...

  3. C语言:位运算

    所谓位运算,就是对一个比特(Bit)位进行操作.在<数据在内存中的存储>一节中讲到,比特(Bit)是一个电子元器件,8个比特构成一个字节(Byte),它已经是粒度最小的可操作单元了.C语言 ...

  4. xmind8 Mac序列号

    1.首先去官网下载xmind8的安装包:XMind for Mac 也可以去我的百度网盘下载:    链接:https://pan.baidu.com/s/1eY52YsSaPmr-YFhB62Cli ...

  5. Centos7 安装Oracle11g Express Edition

    Centos7 安装Oracle11g Express Edition 下载地址:https://download.oracle.com/otn/linux/oracle11g/xe/ 一.安装相关依 ...

  6. SpringBoot中时间格式化的5种方法!

    在我们日常工作中,时间格式化是一件经常遇到的事儿,所以本文我们就来盘点一下 Spring Boot 中时间格式化的几种方法. ​ 时间问题演示 为了方便演示,我写了一个简单 Spring Boot 项 ...

  7. 重新手写一个Vue

    该版把上一次的数据修改就更新全部页面改为了局部更新,相比于上一版的在数据绑定上不是简单的一个监听set再全部更新,具体见下文. 总体流程 仍然是根据自己理解来实现的绑定,相较于上一版的数据更新就全部刷 ...

  8. P3312 数表

    P3312 数表 题意 求出 \[\sum_{i=1}^n\sum_{j=1}^m\sigma(\gcd(i,j))[\sigma(\gcd(i,j))\le a] \] 其中 \(\sigma\) ...

  9. layui 页面加载完成后ajax重新为 html 赋值 遇到的坑

    页面加载完毕后,通过 ajax 按照返回值,为部分 html 赋值: $(function(){ ..... }) 直接这样写,报错,$ 没有定义什么的,错位原因为 jquery 引入错误. layu ...

  10. etcd raft 处理流程图系列1-raftexample

    最近在看raft相关的代码和实现,发现etcd的raft模块在实现上还是比较灵活的,但缺点就是需要用户实现比较多的功能,如存储和网络等,同时带来的优点就是不会对用户的存储和传输作限制.网上对该模块的描 ...