刷题记录:牛客NC20272[SCOI2009]生日快乐
记录 刷题 牛客
2023-09-14 09:12:54 时间
传送门:牛客
题目描述:
windy的生日到了,为了庆祝生日,他的朋友们帮他买了一个边长分别为 X 和 Y 的矩形蛋糕。现在包括windy ,一共有 N 个人来分这块大蛋糕,要求每个人必须获得相同面积的蛋糕。
windy主刀,每一切只能平行于一块蛋糕 的一边(任意一边),并且必须把这块蛋糕切成两块。这样,要切成 N 块蛋糕,windy必须切 N-1 次。
为了使得每块蛋糕看起来漂亮,我们要求 N块蛋糕的长边与短边的比值的最大值最小。你能帮助windy求出这个比值么?
输入:
5 5 5
输出:
1.800000
emmm,这是一道分治题??,第一感觉有点像dp,但是dp似乎考虑的方面有亿点点的多,并且众所周知一般这种dp感觉很烦的题目大概率是能使用分治来解决的.比如这道题…但是假设分治想不出来的,这道题就有点难以下手了
主要思路:
- 既然我们想到了分治,那么久尽量的朝分治来想这道题,我们会发现这道题对于每一块只有两种情况,要么横着切,要么竖着切.因此需要搜索.对于每一个块,我们可以选择一个位置,将其切为左右两块,然后此时假设已经不能再切了,就记录此时我们的答案,假设还能再切就继续的进行搜索.如此进行分治.那么此时最重要的的是如何找出我们可以切的位置,因为我们肯定是不能直接枚举精度来进行分治的.
- emmm,此时我们需要发现我们的蛋糕的最小长度应该为
Y/(N-1)
,宽度为X/(N-1)
假设我们此时Y是大于X的,为什么是这样的一个数值呢.因为我们每一块蛋糕的面积是固定的显然是X*Y/(N-1)
,所以假设我们的长或者宽小于这个限定值的话,但是我们的长和宽最大只有X或Y,所以此时我们的面积不可能达到我们的所需面积. - 并且我们的长度和宽度应该只能是我们的最小限度的整数倍.这一点可能有点难以理解,可以画图来辅助理解.大致情况应该是这样,假设我一个蛋糕的长或宽不是整数倍的话,肯定会导致有一块蛋糕的长或者宽会小于我们的最小限度.因为假设我们的大蛋糕已经被正常的分成了很多个小蛋糕(即最小单位,先不管我们切多少块,反正最后的蛋糕肯定是由这么多个小块合成的),但是每一块最终的小蛋糕肯定是有一块形状和他一样的,因为面积相同,最后肯定至少有一块一模一样的,那么此时假设我的这块蛋糕的长或者宽并不是整数倍,那么必然会有一块蛋糕的长和宽是比我们的最小限度要小的,那么要不这两个蛋糕最后是合在一块的(这样面积又相互补全了),要么就不可能与其他的蛋糕面积相同
这部分感觉不太好讲,请将自行画图结合题解进行理解
下面是具体的代码部分:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <string.h>
#include <stack>
#include <deque>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
#define root 1,n,1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {
ll x=0,w=1;char ch=getchar();
for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
return x*w;
}
#define maxn 1000000
#define ll_maxn 0x3f3f3f3f3f3f3f3f
const double eps=1e-8;
double x,y,n;
double max(double a,double b) {
if(a>=b) return a;
else return b;
}
double min(double a,double b) {
if(a<=b) return a;
else return b;
}
double dfs(double xx,double yy,double k) {
if(k==1) return max(xx,yy)*1.0/min(xx,yy)*1.0;
double ans=inf;
double ans1,ans2;
for(double i=1;i<=k*1.0/2;i++) {
ans1=max(dfs(i*xx/k,yy,i),dfs(xx-i*xx/k,yy,k-i));
ans2=max(dfs(xx,i*yy/k,i),dfs(xx,yy-i*yy/k,k-i));
ans=min(min(ans1,ans2),ans);
}
return ans;
}
int main() {
cin>>x>>y>>n;
printf("%.6lf\n",dfs(x,y,n));
return 0;
}
相关文章
- Python 学习记录(五)Pycharm导入包
- LeetCode刷题记录
- Node.js 初入门?持续记录
- 【每日随笔】记录完整的劳动仲裁过程 一 ( 赢火虫律师平台 | 赢火虫手机端跟进案件信息 | 等待律师接单 | 提交信息给律师 )
- 【错误记录】使用 Jedis 操作 Redis 数据库报错 ( JedisConnectionException | Redis 连接超时故障排查点 | 绑定配置 | 保护模式 | 防火墙 )
- 人类反超 AI:DeepMind 用 AI 打破矩阵乘法计算速度 50 年记录一周后,数学家再次刷新
- Mysql快速新增数据记录(mysql新增记录)
- 记录MySQL: 新增记录的操作指南(mysql添加一行)
- Linux开机启动记录:解读系统运行状态(linux开机启动日志)
- Linux下的日记软件:简单记录你的每一天(linux日记软件)
- 让Redis记录日志,保护你的数据安全(给redis设置日志)
- Oracle估算掌握记录的完美长度(oracle估算记录长度)