POJ-1190生日蛋糕(详细题解)深度优先搜索

2024-01-08 12:30

本文主要是介绍POJ-1190生日蛋糕(详细题解)深度优先搜索,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

POJ-1190

题目描述

7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层生日蛋糕,每层都是一个圆柱体。
设从下往上数第i(1 <= i <= M)层蛋糕是半径为Ri, 高度为Hi的圆柱。
当i < M时,要求Ri > Ri+1且Hi > Hi+1。
由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积Q最小。
令Q = Sπ,请编程对给出的N和M,找出蛋糕的制作方案(适当的Ri和Hi的值),使S最小。(除Q外,以上所有数据皆为正整数)

输入

有两行,第一行为N(N <= 10000),表示待制作的蛋糕的体积为Nπ;第二行为M(M <= 20),表示蛋糕的层数为M。

输出

仅一行,是一个正整数S(若无解则S = 0)。

例子输入

100
2

例子输出

68

提示

圆柱公式
体积V = πR 2H
侧面积A’ = 2πRH
底面积A = πR 2

在这里插入图片描述

蛋糕的体积: V = N π = π R 1 2 H 1 + π R 2 2 H 2 + . . . + π R n 2 H n V=Nπ=πR_1^2H_1+πR_2^2H_2+...+πR_n^2H_n V=Nπ=πR12H1+πR22H2+...+πRn2Hn

: N = R 1 2 H 1 + R 2 2 H 2 + . . . + R n 2 H n N=R_1^2H_1+R_2^2H_2+...+R_n^2H_n N=R12H1+R22H2+...+Rn2Hn
其中 ( R 1 > R 2 > R 3 > . . . > R n 且 H 1 > H 2 > H 3 > . . . > H n ) (R_1>R_2>R_3>...>R_n且H_1>H_2>H_3>...>H_n) (R1>R2>R3>...>RnH1>H2>H3>...>Hn)

蛋糕的表面积: Q = S π = π R 1 2 + 2 π R 1 H 1 + 2 π R 2 H 2 + . . . + 2 π R n H n Q=Sπ=πR_1^2+2πR_1H_1+2πR_2H_2+...+2πR_nH_n Q=Sπ=πR12+2πR1H1+2πR2H2+...+2πRnHn

: S = R 1 2 + 2 R 1 H 1 + 2 R 2 H 2 + . . . + 2 R n H n S=R_1^2+2R_1H_1+2R_2H_2+...+2R_nH_n S=R12+2R1H1+2R2H2+...+2RnHn
其中 ( R 1 > R 2 > R 3 > . . . > R n 且 H 1 > H 2 > H 3 > . . . > H n ) (R_1>R_2>R_3>...>R_n且H_1>H_2>H_3>...>H_n) (R1>R2>R3>...>RnH1>H2>H3>...>Hn)

解题思路:
深度优先搜索:
从底层开始搜索,当底层半径和高度确定时,则搭建剩余层蛋糕所需的最小体积(min_v)和最大体积(max_v)就可以确定了,因此,每当我们搭建完一层时,应该比较一下max_v,min_v和剩余可用体积 V − V i V-V_i VVi)此时有三种情况:
第一种情况、

如果搭建完剩余层所需的最小体积(min_v)比剩余可用体积( V − V i , 其 中 V i V-V_i,其中V_i VVi,Vi表示搭建底层蛋糕已经使用的体积)还要大,则说明题目所固定的体积不够用,此时应该减小底层固定的半径 R i 和 H i R_i和H_i RiHi,直到它们满足第三种情况

第二种情况、

如果搭建完剩余蛋糕层所需最大体积(max_v)比剩余可用体积( V − V i V-V_i VVi)还要小的话,则说用题目所固定的体积用不完,此时应该增大底层固定的半径 R i 和 H i R_i和H_i RiHi,直到它们满足第三种情况

第三种情况、

如果搭建完剩余蛋糕层所需的最小体积(min_v)和最大体积(max_v)满足(min_v < = ( V − V i ) < = <=(V-V_i)<= <=(VVi)<=max_v),则说明从第一层至当前层所搭建的蛋糕层符合题目要求,继续向上层搭建

由题目给定的数值,我们无需考虑π值,则上述的体积可用直接用整数值表示,比如:
当前已用体积 V i = R 1 2 H 1 + R 2 2 H 2 + . . . R i 2 H i V_i=R_1^2H_1+R_2^2H_2+...R_i^2H_i Vi=R12H1+R22H2+...Ri2Hi
当前剩余体积 V − V i = N − ( R 1 2 H 1 + R 2 2 H 2 + . . . R i 2 H i ) = R i + 1 2 H i + 1 + R i + 2 2 H i + 2 + . . . R n 2 H n V-V_i=N-(R_1^2H_1+R_2^2H_2+...R_i^2H_i)=R_{i+1}^2H_{i+1}+R_{i+2}^2H_{i+2}+...R_n^2H_n VVi=N(R12H1+R22H2+...Ri2Hi)=Ri+12Hi+1+Ri+22Hi+2+...Rn2Hn

1.首先确定第一层半径R和高度H的最大值最小值:
总共有M层蛋糕,且每一层的半径和高度都是整数 ( R 1 > R 2 > R 3 > . . . > R n 且 H 1 > H 2 > H 3 > . . . > H n ) (R_1>R_2>R_3>...>R_n且H_1>H_2>H_3>...>H_n) (R1>R2>R3>...>RnH1>H2>H3>...>Hn),则最高层的半径和高度至少为1,由此可以确定第一层的半径和高度皆不小于M;

N = R 1 2 H 1 + R 2 2 H 2 + . . . + R n 2 H n N=R_1^2H_1+R_2^2H_2+...+R_n^2H_n N=R12H1+R22H2+...+Rn2Hn 得:

M = 1 , H 1 = 1 M=1,H_1=1 M=1,H1=1时, R 1 R_1 R1最大,且此时 R 1 = N R_1=\sqrt{N} R1=N ,所以 R 1 R_1 R1的取值范围为[M, N \sqrt{N} N ] 当 R 1 R_1 R1的值确定时, H 1 = N R 1 2 H_1=\frac{N}{R_1^2} H1=R12N,同时 H 1 > = M H_1>=M H1>=M

2.依次确定上一层的半径和高的范围

M − i + 1 < = R i < = R i − 1 − 1 ; M-i+1<=R_i<=R_{i-1}-1; Mi+1<=Ri<=Ri11;
M − i + 1 < = H i < = H i − 1 − 1 ; M-i+1<=H_i<=H_{i-1}-1; Mi+1<=Hi<=Hi11;

3.根据已确定的半径和高度判断是否有可能满足题目要求
即分析上述的三种情况,max_v 和 min_v 和 V 三者之间的关系,若不满足则不断改变当前 R 和 H 的值,直到满足为止

4.确定最小的表面积
1.将第一次符合题目要求1的表面积(min_s)记录,然后在遍历其它情况,如果在深度优先搜索的过程中发现已搭建的蛋糕表面积大于之前记录的最小表面积(min_s)则这种情况无需继续遍历,此时应该改变R和H的值,再进行另一种情况的遍历。
2.如果确立一种新的情况则判断当前蛋糕变面积和之前确立的最小表面积的值进行比较,如果当前 S < S< S<min_s,则交换它们的值,(即更新最小表面积)

5.当枚举完所有情况时返回最小表面积的值

代码如下(C++):

//time:563MS
#include<iostream>
#include<cmath>
#include<string>
#include<iomanip>
#include<map>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
int N, M;//分别表示体积和层数
int min_s = 0x7fffffff;//初始化为最大值
inline int min_v(int m)//此函数用于计算搭建剩余蛋糕层所需的最小体积
{int v = 0;//将剩余层的半径设为最小值,即从最高层到当前的上一层分别为1,2,3,4...M-m//每一层高度H取值和R一样,才能保证V最小;for (int R = M - m; R >= 1; R--){int H = R;v += R * R * H;}return v;
}inline int max_v(int r, int h, int m)//此函数用于计算搭建剩余蛋糕层所需的最大体积
{int v = 0;//由于上层半径和高度必须必下层半径和高度小,所以每一层半径和高度的最大取值应是其下层的半径或高度减一for (int R = r, H = h; m <= M; R--, H--,m++){//只有将剩余的每一层的半径和高度设为最大值,才能保证求得的V最大v += R * R * H;}return v;
}
inline void dfs(int r, int h, int m, int s, int v)//深度优先搜索,其中m表示当前在搭建的层数,s表示已经搭建的蛋糕层的表面积,v表示已经使用的体积
{if (m == M && N == v && s < min_s){min_s = s;//更新最小表面积的数值return;}//如果预估蛋糕的最小面积大于前面所确立最小面积,则无需继续深索if (r == 0 || s + 2 * (N - v) / r > min_s)return;//如果预估搭建剩余层所需的最小体积大于剩余可用体积,则说明规定的体积不够用,返回if (min_v(m) > N - v)//第一种情况return;//如果预估搭建剩余层所需的最大体积小于剩余可用体积,则说明无法达到规定的体积,返回if (max_v(r, h, m) < N - v)//第二种情况return;//如果上述条件均不满足,则说明满足第三种情况,则继续深索for (int R = r - 1; R >= M - m; R--)//枚举下一层蛋糕的半径for (int H = h - 1; H >= M - m; H--)//枚举下一层蛋糕的高{//注意,此时的最小值不是M-m+1,因为对应的是下一层的半径和高,所以最小值应该是M-mdfs(R, H, m + 1, s + 2 * R * H, v + R * R * H);//深搜下一层}
}
int main()
{scanf_s("%d%d", &N, &M);for (int r1 = M; r1 * r1 <= N; r1++)//枚举所有可能的半径和高度for (int h1 = N / (r1 * r1); h1 >= M; h1--){int s = r1 * r1 + r1 * h1 * 2;//表示第一层的表面积int v = r1 * r1 * h1;//表示第一层使用的体积dfs(r1, h1, 1, s, v);//固定了第一层的半径和高度之后,往上层去探索}if (min_s == 0x7fffffff)cout << 0 << endl;elsecout << min_s << endl;return 0;
}

如果此文能够帮助到您,烦请点赞收藏,嘻嘻!
以上内容如有不足,请谅解并欢迎指出,最后附上本人微信公众号,欢迎大家一起讨论学习,更多精彩内容请关注公众号:“艺千秋录”,欢迎留言共同进步;
在这里插入图片描述


  1. 符合题目要求的意思就是成功搭建了层数为M且体积为Nπ的蛋糕。 ↩︎

这篇关于POJ-1190生日蛋糕(详细题解)深度优先搜索的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/583453

相关文章

深度解析Python中递归下降解析器的原理与实现

《深度解析Python中递归下降解析器的原理与实现》在编译器设计、配置文件处理和数据转换领域,递归下降解析器是最常用且最直观的解析技术,本文将详细介绍递归下降解析器的原理与实现,感兴趣的小伙伴可以跟随... 目录引言:解析器的核心价值一、递归下降解析器基础1.1 核心概念解析1.2 基本架构二、简单算术表达

深度解析Java @Serial 注解及常见错误案例

《深度解析Java@Serial注解及常见错误案例》Java14引入@Serial注解,用于编译时校验序列化成员,替代传统方式解决运行时错误,适用于Serializable类的方法/字段,需注意签... 目录Java @Serial 注解深度解析1. 注解本质2. 核心作用(1) 主要用途(2) 适用位置3

Java MCP 的鉴权深度解析

《JavaMCP的鉴权深度解析》文章介绍JavaMCP鉴权的实现方式,指出客户端可通过queryString、header或env传递鉴权信息,服务器端支持工具单独鉴权、过滤器集中鉴权及启动时鉴权... 目录一、MCP Client 侧(负责传递,比较简单)(1)常见的 mcpServers json 配置

Python与MySQL实现数据库实时同步的详细步骤

《Python与MySQL实现数据库实时同步的详细步骤》在日常开发中,数据同步是一项常见的需求,本篇文章将使用Python和MySQL来实现数据库实时同步,我们将围绕数据变更捕获、数据处理和数据写入这... 目录前言摘要概述:数据同步方案1. 基本思路2. mysql Binlog 简介实现步骤与代码示例1

基于C#实现PDF转图片的详细教程

《基于C#实现PDF转图片的详细教程》在数字化办公场景中,PDF文件的可视化处理需求日益增长,本文将围绕Spire.PDFfor.NET这一工具,详解如何通过C#将PDF转换为JPG、PNG等主流图片... 目录引言一、组件部署二、快速入门:PDF 转图片的核心 C# 代码三、分辨率设置 - 清晰度的决定因

Maven中生命周期深度解析与实战指南

《Maven中生命周期深度解析与实战指南》这篇文章主要为大家详细介绍了Maven生命周期实战指南,包含核心概念、阶段详解、SpringBoot特化场景及企业级实践建议,希望对大家有一定的帮助... 目录一、Maven 生命周期哲学二、default生命周期核心阶段详解(高频使用)三、clean生命周期核心阶

Java中HashMap的用法详细介绍

《Java中HashMap的用法详细介绍》JavaHashMap是一种高效的数据结构,用于存储键值对,它是基于哈希表实现的,提供快速的插入、删除和查找操作,:本文主要介绍Java中HashMap... 目录一.HashMap1.基本概念2.底层数据结构:3.HashCode和equals方法为什么重写Has

深度剖析SpringBoot日志性能提升的原因与解决

《深度剖析SpringBoot日志性能提升的原因与解决》日志记录本该是辅助工具,却为何成了性能瓶颈,SpringBoot如何用代码彻底破解日志导致的高延迟问题,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言第一章:日志性能陷阱的底层原理1.1 日志级别的“双刃剑”效应1.2 同步日志的“吞吐量杀手”

Java使用正则提取字符串中的内容的详细步骤

《Java使用正则提取字符串中的内容的详细步骤》:本文主要介绍Java中使用正则表达式提取字符串内容的方法,通过Pattern和Matcher类实现,涵盖编译正则、查找匹配、分组捕获、数字与邮箱提... 目录1. 基础流程2. 关键方法说明3. 常见场景示例场景1:提取所有数字场景2:提取邮箱地址4. 高级

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程