[洛谷P1731][NOI1999]生日蛋糕(dfs)(剪枝)
典型的深搜+剪枝策略
我们采用可行性剪枝、上下界剪枝、优化搜索顺序剪枝、最优性剪枝的方面来帮助我们进行剪枝。
也许有人还不知道剪枝,那我就弱弱地为大家补习一下吧qwq:
.优化搜索顺序:
在一些搜索问题中,搜索树的各个层次、各个分支之间的顺序是不固定的。不同的搜索顺序会产生不同的搜索树形态,其规模大小也相差甚远。因此,我们可以采用排序、更改等手段来优化时间或者空间上的复杂度,借此来优化我们的程序。
.排除等效冗余
在搜索过程中,如果我们能够判定从搜索树的当前节点沿着某几条不同的分支到达的子树是等效的,那么只需要对于其中的一条分支进行搜索。这中优化的方法应用的时候十分有效(而且只需要一个"=="qwq)。
.可行性剪枝
在搜索过程中,及时对当前状态进行检查,如果发现分支已经无法到达递归的边界,就执行回溯。这就好比我们在道路上行走时,远远地看到前方是一个死胡同,就应该立即折返绕路,而不是走到这个死胡同的尽头再返回。
某些题目的范围限制是一个区间,此时可行性剪枝也被称为"上下界剪枝"。
.最优性剪枝
在最优化问题的搜索过程中,如果当前花费的代价已经超过当前搜索到的最优解,那么无论采取多么优秀的策略到达递归边界,都不可能更新答案。此时可以停止对当前分支的搜索,执行回溯。
.记忆化
可以记录每个状态的搜索结果,在重复遍历一个状态时直接检索并返回。这好比我们对图进行深度优先遍历时,标记一个节点是否已经被访问过。(类似于visit[],或者像线段树懒标记之类的.我是这么理解的qwq)
题目背景
7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层
生日蛋糕,每层都是一个圆柱体。
设从下往上数第i(1<=i<=M)层蛋糕是半径为Ri, 高度为Hi的圆柱。当i<M时,要求R_i>R_{i+1}Ri>Ri+1且H_i>H_{i+1}Hi>Hi+1。
由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积Q最小。
令Q= Sπ
请编程对给出的N和M,找出蛋糕的制作方案(适当的Ri和Hi的值),使S最小。
(除Q外,以上所有数据皆为正整数)
题目描述

输入输出格式
输入格式:
有两行,第一行为N(N<=20000),表示待制作的蛋糕的体积为Nπ;第二行为M(M<=15),表示蛋糕的层数为M。
输出格式:
仅一行,是一个正整数S(若无解则S=0)。
样例
输入样例:
输出样例:
68
下面我们进行一下这个问题的求解思路:
1.上下界剪枝:
当我们在第dep层的时候,我们只在下面的范围枚举半径和高度即可。
首先,枚举R∈[dep,min($\sqrt{N-v}$,r[dep+1]-1)];
其次,枚举H∈[dep,min($\sqrt{N-v}/R^2$,h[dep+1]-1)];
2.优化搜索顺序
在上面确定的范围中进行倒序枚举。
3.可行性剪枝(画个五角星)
可以预处理出从上往下前i(1≤i≤M)层的最小体积和侧面积。
显然,当第1~i层的半径分别取1,2,3···i时,有最小体积和侧面积。
如果当前体积V加上1~dep-1层的最小体积大于N,则可以剪枝。
4.最优性剪枝(1)
如果当前表面积s加上1~dep-1层的最小侧面积大于已经搜到的结果,剪枝。
5.最优性剪枝(2)
利用h和r数组,1~dep-1层的体积可表示为n-v=∑(dep-1,k=1)h[k]*r[k]^2,1~dep层的表面积可以表示为2∑(dep-1,k=1)h[k]*r[k]。
因为2∑(dep-1,k=1)h[k]*r[k]=2/r[dep]*∑(dep-1,k=1)h[k]*r[k]*r[dep]≥2/r[dep]*∑(dep-1,k=1)h[k]*r[k]^2≥2(n-v)/r[dep]。
所以当2(n-v)/r[dep]+s大于已经搜到的结果时,可以剪枝。
加上以上五个剪枝后,搜索算法就可以快速求出该问题的最优解。
完整代码如下:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int r[],h[],n,m,dep,minn=0x7fffffff;
void dfs(int dep,int leftdep,int leftv,int nowv)
{
if(leftv<)
return ;
if(dep>m+)
return ;
if(nowv>=minn)
return ;
if(leftv==&&dep==m+)
{
nowv+=r[]*r[];
minn=min(nowv,minn);
return ;
}
if(nowv+leftdep+r[]*r[]>minn)
return ;
if(leftv-(r[dep-]*r[dep-]*h[dep-]*leftdep)>)
return ;
for(int i=r[dep-]-;i>=leftdep;i--)
for(int j=h[dep-]-;j>=leftdep;j--)
{
if(leftv-i*i*j>=&&dep<=m)
{
r[dep]=i;
h[dep]=j;
dfs(dep+,leftdep-,leftv-i*i*j,nowv+(*i*j));
r[dep]=;
h[dep]=;
}
}
}
int main()
{
scanf("%d%d",&n,&m);
r[]=sqrt(n);
h[]=sqrt(n);
dfs(,m,n,);
if(minn==0x7fffffff)
{
printf("");
return ;
}
printf("%d",minn);
return ;
}
写完了长长的博文,下面来总结一下心得吧qwq:
1.搜索算法面对的状态我们可以将其理解为一个岔路口的选择问题,也就是可以看作一个多元组,其中每一元都是问题状态空间中的一个"维度"。
这其中每一个维度发生变化,都会移动状态空间中的一个"点"。
而这些维度通常在题目中也会出现,这些便需要大家在做题的时候多留心观察一下我们所需要的条件以及我们根据这些维度的变化能够得到什么,从而得出合理的搜索框架。
2.搜索过程中的剪枝,其实我们就是针对于每一个"维度"与其该维度的边界条件,加以缩放、推导,得出一个相应的不等式,以减少搜索树的扩张从而达到优化复杂度的目的。
3.为了进一步提高我们剪枝的"效率"以及我们的所要求的目的,我们可以除了对当前所花费的代价之外,也对该状态未来的"状态"进行分析,有时我们还可以跨维度进行优化分析,达到我们的要求(也就是全面优化qwq),同时这也更容易接近我们的目的。
手写不易,各位客官点个赞呗(花花)
[洛谷P1731][NOI1999]生日蛋糕(dfs)(剪枝)的更多相关文章
- 洛谷 P1731 [NOI1999]生日蛋糕(搜索剪枝)
题目链接 https://www.luogu.org/problemnew/show/P1731 解题思路 既然看不出什么特殊的算法,显然是搜索... dfs(u,v,s,r0,h0)分别表示: u为 ...
- 洛谷——P1731 [NOI1999]生日蛋糕
P1731 [NOI1999]生日蛋糕 搜索+剪枝 常见的剪枝: 若当前状态+后面所要搜索的最差的状态$>$或是$<$最后的状态,就返回 预处理最差的状态 #include<iost ...
- 【题解】洛谷P1731 [NOI1999] 生日蛋糕(搜索+剪枝)
洛谷P1731:https://www.luogu.org/problemnew/show/P1731 思路 三重剪枝 当前表面积+下一层表面积如果超过最优值就退出 当前体积+下一层体积如果超过总体积 ...
- 洛谷 P1731 [NOI1999]生日蛋糕
P1731 [NOI1999]生日蛋糕 题目背景 7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层 生日蛋糕,每层都是一个圆柱体. 设从下往上数第i(1<=i<=M ...
- C++ 洛谷 P1731 [NOI1999]生日蛋糕
P1731 [NOI1999]生日蛋糕 一本通上也有. 这TM是一道极其简单的深搜剪枝(DP当然可以的了,这里我只讲深搜). 首先圆柱公式:(有点数学基础都知道) V=πR2H S侧=π2RH S底= ...
- 洛谷 P1731 [NOI1999]生日蛋糕 && POJ 1190 生日蛋糕
题目传送门(洛谷) OR 题目传送门(POJ) 解题思路: 一道搜索题,暴力思路比较容易想出来,但是这道题不剪枝肯定会TLE.所以这道题难点在于如何剪枝. 1.如果当前状态答案已经比我们以前某个状态 ...
- POJ1190 洛谷P1731 NOI1999 生日蛋糕
生日蛋糕(蛋糕是谁?) Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 20272 Accepted: 7219 Desc ...
- 洛谷P1731 [NOI1999]生日蛋糕(爆搜)
题目背景 7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层 生日蛋糕,每层都是一个圆柱体. 设从下往上数第i(1<=i<=M)层蛋糕是半径为Ri, 高度为Hi的圆柱 ...
- 洛谷 P1731 [NOI1999]生日蛋糕 题解
每日一题 day53 打卡 Analysis 观察一个蛋糕的俯视图,上表面的面积其实就是最下面那一层的底面积,所以在第一次搜索的时候加入这个底面积,之后就只用考虑侧面积就好啦. 就是每次枚举r和h,如 ...
随机推荐
- Java探针-Java Agent技术-阿里面试题
Java探针参考:Java探针技术在应用安全领域的新突破 最近面试阿里,面试官先是问我类加载的流程,然后问了个问题,能否在加载类的时候,对字节码进行修改 我懵逼了,答曰不知道,面试官说可以的,使用Ja ...
- Linux mmc framework2:基本组件之block
1.前言 本文主要block组件的主要流程,在介绍的过程中,将详细说明和block相关的流程,涉及到其它组件的详细流程再在相关文章中说明. 2.主要数据结构和API 2.1 struct mmc_ca ...
- class_create(),device_create自动创建设备文件结点【转】
本文参考来自CSDN博客,转载请标明出处:http://blog.csdn.net/zhenwenxian/archive/2010/03/28/5424434.aspx 本文转自:http://ww ...
- 在SecureCRT中做make menuconfig乱码
不能在SecureCRT中做(显示为乱码),从高手那里学来一招,解决了这个问题: options--terminal--emulation-- xterm ansi color1.先设置终端为x ...
- Spark学习之Spark安装
Spark安装 spark运行环境 spark是Scala写的,运行在jvm上,运行环境为java7+ 如果使用Python的API ,需要使用Python2.6+或者Python3.4+ Spark ...
- Java基础:整型数组(int[]、Integer[])排序
Windows 10家庭中文版,java version "1.8.0_152",Eclipse Oxygen.1a Release (4.7.1a), 参考链接:http://w ...
- LeetCode(55): 跳跃游戏
Medium! 题目描述: 给定一个非负整数数组,你最初位于数组的第一个位置. 数组中的每个元素代表你在该位置可以跳跃的最大长度. 判断你是否能够到达最后一个位置. 示例 1: 输入: [2,3,1, ...
- C++ code:数组初始化
具有初始化的数组定义,其元素个数可以省略,即方括号中的表达式可以省略.这时候,最后确定的元素个数取决于初始化值的个数.例如: #include<iostream> using namesp ...
- pytest十:用例 a 失败,跳过测试用例 b 和 c 并标记失败 xfail
当用例 a 失败的时候,如果用例 b 和用例 c 都是依赖于第一个用例的结果,那可以直接跳过用例 b 和 c 的测试,直接给他标记失败 xfail用到的场景,登录是第一个用例,登录之后的操作 b 是第 ...
- 你可能不知道的git clean
git clean是干啥的? git clean可以帮你清理workspace中未被git版本控制的文件,比如临时文件,构建出来的二进制文件. 使用方法 如果你的clean.requireForce项 ...