- 整理例题(主要口胡,全凭自己瞎说),例题比较多,有兴趣可以自己尝试一下,没兴趣看个思路也好。
例题1:
P1036 [NOIP2002 普及组] 选数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P1036题意:
- 有n个数,从中取k个,求这k个数之和,求这k个数之和是素数的个数。
题解:
- 这个题一开始我采用的回溯的方法(后来发现大佬们都没有用回溯的方法来做),大体框架还是有一个判断函数判断素数,dfs里面有三个参数,第一个是目前选择了几个数,第二个是求和,第三个是目前走到数组下标的位置,返回条件是当选择个数与题目给出的条件个数相同时,判断sum是否是素数,是素数ans++,不是素数继续搜索,然后最后输出ans的值即可。
例题2:
- 给定奶牛维生素的需求,以及现在有的总和种类,求最少需要的维生素种类,以及它们的编号。
题解:
- 三个函数:1.判断是否符合题目所给条件>奶牛所需的维生素总量。
- 2.dfs两个参数,一个参数记录搜到了第几个,另一个参数记录当前参数究竟选还是不选。符合条件的不断更新最小值即可。
- 有点类似于背包的那种思想,但是需要回溯,这个种类的装入进入下一次递归,不装入的情况进入下一次循环。
- 3.判断函数该怎么写,新开一个数组记录哪一些种类,这些种类的是否每一种都满足奶牛所需的维生素总量,满足true,不满足false。
例题3:
P1451 求细胞数量 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P1451题意:
- 细胞的定义为沿细胞数字上下左右若还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数,就是搜索某一个位置的上下左右,如果有细胞数字则视为同一细胞。
题解:
- 虽然个人觉得还是用BFS更加方便,但是在DFS题单中还是尝试用DFS进行求解。
- 分四个方向设两个数组dx,dy,然后还要有一个测试数组vis来记录已经访问过的点,dfs写法访问上下左右四个点,如果没有扫描过,并且不是0的话就继续进行搜索,直到扩展区域周围都是0,即这是一个细胞,然后继续扫描剩余还未扫描过的点(即将图中所有的点全部扫描一遍后(除了0点,因为0不算作细胞))得出ans即个数的值,输出即可。注意判断条件为未扫描过的点,以及该点不是0即可。
- 从大佬的题解中还学习到了scanf("%1d",&a[i][j]),是一个数只读取1位数。
例题4:
01背包问题的深搜解决方案
这次的思路我直接写在代码里面了->
#include <iostream>
#include <cstdio>
using namespace std;
#define MAX 1000
int val[MAX], weight[MAX], n;
int res;
//首先要搞清楚01背包问题的实质,就是每一个种类我都只有一个,要么放,要么不放
void dfs(int nowweight, int nowval, int nowpos)//现在目前背包剩余的重量,现在的价值,现在目前扫描到的背包的哪一件物品了
{
if (nowpos == n)//当扫描到最后一个物品时,res用来记录最大价值的
{
if (res < nowval)//剩余价值<现有价值;那肯定不是最优解;
res = nowval;//更新最大价值啊
return;
}
int temp = 0;
//剪枝的用法
for (int i = nowpos; i < n; i++)
temp += val[i];//我剩余物品所有的价值相加的和用temp记录
if (temp + nowval < res) //现在搜索到的物品价值加上剩余所有物品的价值都无法超过现有记录的最大价值res
return;
if (nowweight >= weight[nowpos])//只有我背包里面的剩余容量大于这个物品的重量的时候,我才可以把该物品放入背包中去
dfs(nowweight - weight[nowpos], nowval + val[nowpos], nowpos + 1);//那该物品既然放进了背包里,背包容积减少,现有价值增加,继续搜索下一个物品
dfs(nowweight, nowval, nowpos + 1);//如果不符合该条件,那就不放入该物品,当仍需要继续扫描下一个物品
}
int main()
{
int i, maxweight;
res = 0;
while (scanf("%d%d", &n, &maxweight) && n && maxweight)
{
for (i = 0; i < n; i++)
{
scanf("%d%d", &weight[i], &val[i]);
}
dfs(maxweight, 0, 0);//背包最大容积,初始价值0,初始位置0
printf("%d\n", res);//输出res即是满足背包容积的最大价值
}
return 0;
}
例题5:
P1331 海战 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P1331题意:
- 观察是否有船相撞,如果有船相撞,输出Bad placement,如果没有船相撞,则输出船的只数。
题解:
- 1.首先什么情况下判断船相撞,即就是不完全矩形,例子看一看,假设是2*2的矩阵
-
## #. .# ## #. ## ## .#
- 这些都是相撞的情况(需要理解)。
- 2.大体框架:判断是否越界,判断是否有不是矩形的情况(即有船只相撞),dfs函数4个方向进行搜索(该点是#,这个点没有被扫描,并且不能越界)
- 3.和例题3一样,搜索每一个点(符合该点为#并且该点没有被扫描),计算船只的个数。撒花就行了。
例题6:
- 典型的孤岛问题,w的附近如果还是就这两个都视为同一个水坑,计算水坑的个数。
题解:
- 1.就和上一个例题一样甚至比上一个例题还要简单,就是搜索w的八个方向,如果八个方向里面还有w就视为同一水坑,搜索到的w直接替换成”.",防止二次搜索,然后直到扫描完所有的点即可。
- 2.还是三个限制条件,该点未被扫描,该点为w,该点不能越界即可
例题7:
P1498 南蛮图腾 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/solution/P1498题意:
- 给定n,输出图形(每一个图形的小三角,宽度为4,高度为2),利用逆序存图。
题解:
- 1.递归图形,每次扩大的时候,向右复制一个,向上复制一个,倒置输出。
- 2.注意一点一个“\"不能输出\,必须要用”\\"才行。
- 3.需要用一个三重循环因为要复制n-1次才行,(逆序存图,逆序输出)(分治递归的思想)。
例题8:
找到满足条件的序列(输出元素个数,序列里面的数都是素数,相邻两个数的差也是素数)。
题解:
- 全网一共就找到了3篇题解(我这个题确实确实不会)说一下大佬们的思路吧。
- 1.大体分为这几种情况,特判的话就是这两个数都是素数,它们的差正好也是素数,那就输出2+A+B即可,相邻两个素数无非两种情况就是一奇数一偶数,(这个偶数还只能是2),要么是两个奇数(还得保证它们的差值是2),两个偶数都不需要判断,因为除了2肯定都不符合素数的判断条件,所以dfs就是去枚举这两种情况进行分析。
- 2.主函数里面先筛一遍,保证进入枚举的数都已经是素数了,然后枚举差值,不符合条件的直接return,符合条件的输出,结束程序。
- 3.如果一直没有符合条件的输出,最后输出-1。
- 4.还需要注意的点就是该数的数量比较大,需要开到 long long,需要进行去重操作,需要素数筛来降低时间复杂度。
- 这个题的思路还是挺难的,毕竟也是划在了提高里面的题目,还是之后需要好好琢磨一下子。
例题9:
- 求一个长度为 n 的
OX
串的全排列: - 1. 第一行排列必须全部都是
O
。2. 除最后一个排列外,每一个排列都不能重复。3. 相邻的上下排列只能有一个位置不一样。4. 遍历完所有排列后,还要能回到第一个排列。
题解:
- 该题利用二进制数表来进行深搜,还是标记,回溯操作(因为本菜菜不会位运算)所以具体的题解等我熟练掌握后再更新,举个例子:
OOO
O1O
O11
OO1
1O1
111
11O
1OO
OOO
例题10:
P1506 拯救oibh总部 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P1506题意:
- 个人觉得和P1596是一个类型的题目啊,搜索它的上下左右如果没有0,即都被围墙筑起的话,就不会被淹没,个数加1。
题解:
- 1.还是扫描所有的点,如果该点为0的话,再搜索它的上下左右的点,看是否也是为0,dfs从(0,0)点开始扫描,扫描过的0点记为"*"即可,最后遍历一遍,看有几个0点,即未被淹没的城市个数。
- 2.注意的点是必须要从最外面一圈进行扫描,保证让它不能越界即可。
例题11:
P1030 [NOIP2001 普及组] 求先序排列 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P1030题意:
- 给出二叉树的中序遍历以及后序遍历,求前序遍历(找出根节点,分成左右子树,前序遍历是根左右)
题解:
- 充分了解二叉数的遍历,因为后序遍历的最后一个就是根节点,然后在中序遍历中找到这个根节点,然后分成左子树和右子树,然后继续分割,直到递归结束。
持续更新中...感谢观看,欢迎指导和交流!