深搜——简单剪枝

说在最前面:

因为马上要 NOIP2020 了,所以菜鸡开始了复习qwq。

pj 组 T1 ,T2 肯定要拿到满分的,然后 T3 , T4 拿部分分, T3 拿部分分最常见的做法就是暴搜,但是暴搜容易 T ,为了拿到更多的分数,应该合理剪枝。

各种剪枝方法

  1. 优化搜索顺序

(随缘)随缘剪枝。

  1. 可行性剪枝

对当前状态进行检查,发现分支无法到达递归边界,回溯。

  1. 最优化剪枝 ☆☆☆ ← 最重要的一种剪枝方法

在最优化问题的搜索过程中,若当前花费的代价已超过前面搜到的最优解,回溯。

  1. 上下界剪枝

按题意,找子节点的上下界。

例题

例一:洛谷 P1135 奇怪的电梯

\(\rm\Large Link\)

这道题当然 bfs 效率是最快的,但是为了练习剪枝,就可以拿 dfs 做。

思路很简单,从起点开始,只要没越界就向上下搜,全部搜完得到答案。

很容易就得到了代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#define line cout << endl
using namespace std;
const int NR = 205;
int n, a, b;
int k[NR];
int ans = 1e9;
bool flag[NR];
void dfs(int x, int step) {
if (x < 1 || x > n || flag[x]) {
return;
}
if (x == b) {
if (step < ans) ans = step;
return;
}
flag[x] = true;
dfs(x + k[x], step + 1);
dfs(x - k[x], step + 1);
flag[x] = false;
}
int main() {
cin >> n >> a >> b;
for (int i = 1; i <= n; i++) {
cin >> k[i];
}
dfs(a, 0);
if (ans == 1e9) cout << "-1";
else cout << ans;
return 0;
}

很好,发现得分 \(80pts\) 。有两个点 T 了。

所以我们就需要剪枝。

怎么剪枝?

我们要球的是最优解,所以就可以用 最优剪枝 ,如果当前的 \(step\) 已经超过了最优解 \(ans\) ,那么就可以结束了,这样就剪枝成功,最后放上 \(dfs\) 代码:

void dfs(int x, int step) {
if (x < 1 || x > n || flag[x] || step >= ans) {
return;
}
if (x == b) {
if (step < ans) ans = step;
return;
}
flag[x] = true;
dfs(x + k[x], step + 1);
dfs(x - k[x], step + 1);
flag[x] = false;
}

当然了,这题如果拿 \(bfs\) 做肯定是不会 T 的,但是为了练习剪枝嘛~ qwq

例二:洛谷 P1731 [NOI1999]生日蛋糕

\(\rm\Large Link\)

这道题是有一定难度的,需要运用各种高科技剪枝(?

如果泥能独立 AC 这道题,就可以拿到 NOI 铜牌了! (不过是1999年的,现在肯定难多了

其实这道题根本不需要考虑 \(\pi\) 因为:

\[\begin{aligned}
V_{\text{圆柱}} & = S_{\text{圆柱}} \times h\\
&= \pi r^2\times h\\
N & = r^2\times h
\end{aligned}\]
\[\begin{aligned}
S_{\text{圆柱侧}} & = 2\pi r \times h\\
S &= 2rh\\
S &= \frac{2N}{r}
\end{aligned}\]

因为为了方便,搜索的参数为 \(5\) 个:

\(\text{dfs(int ceng, int nestv, int r, int h, int s);}\)

\(\text{ceng = 当前层数, nestv = 剩余体积, r = 半径, h = 高度, s = 体积}\)

体积为 \(100\) 的栗子:画张图,更好理解:

去搜每一层蛋糕的半径和高度。因为是整数,所以把所有的半径和高度枚举一遍, \(r\) 的根节点从 \(10\) 开始。从最大值到最小值,如果体积明显超出了,就可以剪枝。

枚举第一层蛋糕的高度。

此时的时间复杂度是 \(O(n^2)\)

因为比较暴力,所以必须用到各种剪枝,在 \(O(n^2)\) 的基础上进行剪枝

  1. 可行性剪枝

  2. 最优化剪枝

  3. 上下界剪枝

  4. 搜索顺序剪枝

    半径从大到小,从小到大。

    高度从大到小,从小到大。

    共 4 种搜索顺序,找到最快的顺序。

最终就能 AC 本题啦~

放上 \(dfs\) 代码,有注释应该很好理解吧/kk:

void dfs(int ceng, int restv, int r, int h, int s) {
//ceng为已用层数,restv为剩余体积,r为当前最高层蛋糕半径,h为当前最高层蛋糕高度,s为已有表面积/π
if(ceng == m && restv == 0) //蛋糕已完成,即层数ceng==m且体积用完 {
ans = min(ans, s); //更新答案为最优解
return;
}
if(restv < 0) return; //剩余体积小于0表示体积超过了预定的值
if(s + 2 * restv / r >= ans) return; //若当前总表面积+该层往上所有表面积的最小和>=目前最优解
//简单一点可以把每一层的侧面积看做最小的1,那么后续剩下部分的侧面积就等于剩余层数m-ceng
//数据严格一点就可以从剩余体积去计算出剩余最小侧面积2 * restv / r,可改为if(s + 2 * restv / r >= ans)
if(r * r * h * (m - ceng) < restv) return; //后续能做出蛋糕的最大体积<当前剩余体积
for(int i = r - 1; i >= m - ceng; i--) //枚举下一层所有可能的半径
for(int j = h - 1; j >= m - ceng; j--) //枚举下一层所有可能的高度
if(ceng != 0) dfs(ceng + 1, restv - i * i * j, i, j, s + 2 * i * j);
else dfs(ceng + 1, restv - i * i * j, i, j, s + 2 * i * j + i * i);
//第一层需要计算上表面积,其他层只需计算侧面积即可,故需分类讨论
}

好啦!窝拿到 NOI 铜牌啦啊!(雾

【笔记】「pj复习」深搜——简单剪枝的更多相关文章

  1. 【笔记】「pj复习」深搜——拿部分分

    说在最前面 众所周知, NOIP pj 的第三题大部分都是 dp ,但是有可能在考场上想不到动态转移方程,所以我们就可以拿深搜骗分. 方法 深搜拿部分分 剪枝 记忆化 看数据范围 有时候发现,写完深搜 ...

  2. 深搜+DP剪枝 codevs 1047 邮票面值设计

    codevs 1047 邮票面值设计 1999年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题目描述 Description ...

  3. 【深搜加剪枝】【HDU1455】【Sticks】

    题目大意:有一堆木棍 由几个相同长的木棍截出来的,求那几个相同长的木棍最短能有多短? 深搜+剪枝 具体看代码 #include <cstdio> #include <cstdlib& ...

  4. hdu 1010 Tempter of the Bone(深搜+奇偶剪枝)

    Tempter of the Bone Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Othe ...

  5. 一本通例题埃及分数—题解&&深搜的剪枝技巧总结

    一.简述: 众所周知,深搜(深度优先搜索)的时间复杂度在不加任何优化的情况下是非常慢的,一般都是指数级别的时间复杂度,在题目严格的时间限制下难以通过.所以大多数搜索算法都需要优化.形象地看,搜索的优化 ...

  6. HDOJ/HDU Tempter of the Bone(深搜+奇偶性剪枝)

    Problem Description The doggie found a bone in an ancient maze, which fascinated him a lot. However, ...

  7. POJ-1190-生日蛋糕(深搜,剪枝)

    生日蛋糕 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 23049 Accepted: 8215 Description 7月1 ...

  8. 深搜的剪枝技巧(三)——Sticks(可行性剪枝、上下界剪枝、最优性剪枝)

    小木棍(最优性剪枝.可行性剪枝) 一.问题描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,已知每段的长都不超过 50 .现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍 ...

  9. DFS-BFS(深搜广搜)原理及C++代码实现

    深搜和广搜是图很多算法的基础,很多图的算法都是从这两个算法中启发而来. 深搜简单地说就是直接一搜到底,然后再回溯,再一搜到底,一直如此循环到没有新的结点. 广搜简单地说就是一层一层的搜,像水的波纹一样 ...

随机推荐

  1. linux tcp/ip 参数解析

    后面整理相关信息/* *     TCP option lengths */#define TCPOLEN_MSS            4 //只能出现在SYN段中#define TCPOLEN_W ...

  2. UNP——第六章,多路转接IO——select

    int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); ...

  3. 痞子衡嵌入式:JLink Script文件基础及其在IAR下调用方法

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是JLink Script文件基础及其在IAR下调用方法. JLink可以说是MCU开发者最熟悉的调试工具了,相比于其他调试器(比如DAP ...

  4. MySQL 连接为什么挂死了?

    摘要:本次分享的是一次关于 MySQL 高可用问题的定位过程,其中曲折颇多但问题本身却比较有些代表性,遂将其记录以供参考. 一.背景 近期由测试反馈的问题有点多,其中关于系统可靠性测试提出的问题令人感 ...

  5. Qt For MacOs环境搭建

    使用VMWARE关于macos镜像搭建,参考https://blog.csdn.net/u011415782/article/details/78505422 关于darwin8.5.5 来安装vmt ...

  6. Tomcat AJP 文件包含漏洞复现(CVE-2020-1938)

    漏洞原理 Tomcat配置了两个Connecto,它们分别是HTTP和AJP. HTTP默认端口为8080,处理http请求:AJP默认端口8009,用于处理 AJP 协议的请求. AJP比http更 ...

  7. 应聘阿里,字节跳动美团90%会问到的JVM面试题! 史上最全系列!

    Java 内存分配 • 寄存器:程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码.• 静态域:static 定义的静态成员.• 常量池:编译时被确定并保存在 .class 文件中的(f ...

  8. Markdown的应知应会

    Markdown介绍 什么是Markdown Markdown是一种纯文本.轻量级的标记语言,常用作文本编辑器使用.和记事本.notepad++相比,Markdown可以进行排版:和Word相比,Ma ...

  9. 脑对u盘不识别的解决方法 一看就会

    u盘可以说是我们日常生活中使用得较为频繁的移动硬盘了,它小巧轻便,便于携带,能够储存大量的文档.因为经常使用的关系,所以就会出现很多问题.比如电脑识别不了u盘怎么办? 接下来,小编想教大家几招面对u盘 ...

  10. centons 7 清机 脚本

    #/bin/bash##################################初始化系统###################setenforce 0 yum install -y yum- ...