luoguP1528&2329 栅栏&切蛋糕
前言
蒟弱本来是在亿万年前做二分答案专题栅栏的,由于数据水所以过掉了,后来发现有一个数据加强版,也就是本题,于是爆T了...过了有个五六个月回来填坑了...现在开O2是在最优解第一个(自豪ing
题目描述
有 \(n\) 块 大小分别为 \(a_i\) 的蛋糕,分给 \(m\) 个嘴大小分别为 \(b_i\) 的人,但是蛋糕只能以整块的形式给人,求最多给多少人。
思路
很明显,答案在排序之后具有单调性,所以可以二分能够分给多少人,但二分并没有一个明确的套路切蛋糕,所以需要进行深搜;
于是来考虑最优贪心策略:
- 首先将所有蛋糕和嘴的大小排序,优先喂嘴小的人;
对应着这两行:
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);
- 排完序后,考虑缩小二分范围,我们从小到大求得嘴大小的前缀和,如果到第 \(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;
我们开始二分+深搜:
- 在深搜过程中,枚举能够切下够这口嘴吃的蛋糕,切掉后蛋糕总大小要减去嘴的大小。如果这块蛋糕切剩下的不够最小嘴的,那么就相当于这块蛋糕没有用了,蛋糕总大小要再减去没有用的这部分。
也就是这样:
if(a[i]>=b[x]){
a[i]-=b[x];tot-=b[x];
if(a[i]<b[1])tot-=a[i];
}
- 显然,当剩下几张嘴的总大小比剩下几块蛋糕的总大小还要大时,方案是不符合的。
也就是这句:
if(pre[x]>tot)return 0;
- 当当前搜索到的这口嘴与下一个要搜索的嘴大小相同时,既然已经枚举到了第 \(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 栅栏&切蛋糕的更多相关文章
- 洛谷P1528 切蛋糕 [搜索,二分答案]
题目传送门 切蛋糕 题目描述 Facer今天买了n块蛋糕,不料被信息组中球球等好吃懒做的家伙发现了,没办法,只好浪费一点来填他们的嘴巴.他答应给每个人留一口,然后量了量每个人口的大小.Facer有把刀 ...
- [洛谷P1528] 切蛋糕
洛谷题目链接:切蛋糕 题目描述 Facer今天买了n块蛋糕,不料被信息组中球球等好吃懒做的家伙发现了,没办法,只好浪费一点来填他们的嘴巴.他答应给每个人留一口,然后量了量每个人口的大小.Facer有把 ...
- 刷题总结——切蛋糕(ssoj)
题目: 切蛋糕 (cake.cpp/c/pas) [问题描述] BG 有一块细长的蛋糕,长度为�. 有一些人要来BG 家里吃蛋糕, BG把蛋糕切成了若干块(整数长度),然后分给这些人.为了公平,每个人 ...
- LRJ入门经典-0903切蛋糕305
原题 LRJ入门经典-0903切蛋糕305 难度级别:B: 运行时间限制:1000ms: 运行空间限制:256000KB: 代码长度限制:2000000B 试题描述 如图所示有一个矩形蛋糕,上面划分成 ...
- 洛谷 P1714 切蛋糕 题解
P1714 切蛋糕 题目描述 今天是小Z的生日,同学们为他带来了一块蛋糕.这块蛋糕是一个长方体,被用不同色彩分成了N个相同的小块,每小块都有对应的幸运值. 小Z作为寿星,自然希望吃到的第一块蛋糕的幸运 ...
- TZOJ 3042 切蛋糕(并查集)
描述 KK是个心灵手巧的好姑娘,她做了一个大蛋糕请她的好朋友们来品尝.这个蛋糕分成n×n个正方形小格,每个小格包含一块水果.KK要把蛋糕切成若干块,显然她不会破坏任意一个小格.无聊的某同学在她切蛋糕时 ...
- 切蛋糕(贪心 or 优先队列)
链接:https://www.nowcoder.com/acm/contest/80/D来源:牛客网 最可爱的applese生日啦,他准备了许多个质量不同的蛋糕,想请一些同学来参加他的派对为他庆生,为 ...
- HDOJ 1722--Cake(切蛋糕问题)
一次生日Party可能有p人或者q人参加,现准备有一个大蛋糕.问最少要将蛋糕切成多少块(每块大小不一定相等),才能使p人或者q人出席的任何一种情况,都能平均将蛋糕分食. Input 每行有两个数p和q ...
- 单调队列练习题解(切蛋糕&好消息,坏消息)
单调队列的练习题解 前言: 在上一篇学习记录中,单调队列给出了几道练习题,因为这两道题的算法以及思路相差无几(几乎可以算是双倍经验quq),所以就在这里集中写一下相关的题解 前置知识: 见:队列专题( ...
随机推荐
- c语言格式字符
格式说明由"%"和格式字符组成,如%d%f等.它的作用是将输出的数据转换为指定的格式输出.格式说明总是由"%"字符开始的. 格式字符有d,o,x,u,c,s,f ...
- Java中为什么notify()可能导致死锁,而notifyAll()则不会(针对生产者-消费者模式)
1.先说两个概念:锁池 和 等待池 锁池:假设线程A已经拥有了某个对象(注意:不是类)的锁,而其它的线程想要调用这个对象的某个synchronized方法(或者synchronized块),由于这些线 ...
- 如何在 PyCharm 中设置 Python 代码模板
#!/usr/bin/env python # -*- coding: utf-8 -*- # Created by iFantastic on $DATE if __name__ == '__mai ...
- 第八篇 -- 对数据库mysql进行连接并压测
参考链接:https://blog.csdn.net/laofashi2015/article/details/81296929 工具:mysql-8.0.12-winx64,apache-jmete ...
- create-react-app 项目安装less
1.安装依赖: npm install less less-loader --save-dev 2.在webpack.config.js里面添加配置:(若webpack.config.js文件没有显示 ...
- HashSet 的实现原理
HashSet 概述 对于 HashSet 而言,它是基于 HashMap 实现的,底层采用 HashMap 来保存元素,所以如果对 HashMap 比较熟悉了,那么学习 HashSet 也是很轻松的 ...
- java小游戏java九宫格
问题来源于吾爱破解https://www.52pojie.cn/thread-1484202-1-1.html 编程目标一:根据下面的"游戏说明",实现该游戏程序,完成响应用户的输 ...
- Centos 7 安装mysql5.7 nginx tomcat
- 微信小程序 -- 英语词典 (小程序插件)
英语词典小程序 基于英语词典小程序插件 - 提供开源地址 项目地址 英语词典小程序插件: 微信小程序 词典 真题基础服务插件(gitee.com) 功能特色 [x] 全面详实的经典词库,详细释义覆盖约 ...
- 比POSTMAN更好用!在国产接口调试工具APIPOST中使用Mock
APIPOST可以让你在没有后端程序的情况下能真实地返回接口数据,你可以用APIPOST实现项目初期纯前端的效果演示,也可以用APIPOST实现开发中的数据模拟从而实现前后端分离.在使用APIPOST ...