第二周
https://www.luogu.com.cn/problem/P3371 单源最短路(弱化版)
Floyd可以,但是只有70分,所以可以用题目所提到的算法Dijkstra
思路:
1.定义ans[100000],ans[i]代表到达i点的最小花费
2.定义bool数组visit,代表是否来过这里
3.ans[起点]=0,其余的赋值为inf
4.定义一个curr变量,visit[current]=1(访问过),代表现在的位置,初始值为起点。
5.列举所有与curr相联通的的点,将这些点(i)的ans值更新:
ans[i]=min(ans[i],ans[curr]+ans[i]=min(ans[i],ans[curr]+到这些点需要的花费 ))
6. 列举所有没有过的的点,找到ans值最小的点,赋值给curr,visit[current]=1(访问过)
7.所有点都访问过(visit[i]都==1),程序结束。此时,ans[i]代表从起点到i的最短路径
https://www.luogu.com.cn/problem/P1229 遍历问题
只有一个儿子 的节点才会在知道前序后序的情况下有不同的中序遍历,所以将题目转化成找 只有一个儿子的节点个数。可以很容易的找出这类节点在前序后序中出现的规律。(前序中出现AB,后序中出现BA,则这个节点只有一个儿子每个这类节点有两种中序遍历(及儿子在左,儿子在右)根据乘法原理中序遍历数为 2^节点个数种
https://www.luogu.com.cn/problem/P4715 淘汰赛
画个图会发现完整的比赛路径像是个二叉树,当前节点的父节点存储值为左右两个兄弟节点中的最大值,但是要注意输出的是位置,所以要注意记录在数组中的位置
https://www.luogu.com.cn/problem/P1827
这里利用到一个最重要的知识点——二叉树遍历。
-
前序遍历:根左右
-
中序遍历:左根右
-
后序遍历:左右根
前序遍历是先遍历根节点,再遍历根节点的左右子树。
那么,前序序列的第一个节点,一定是根节点。
找到根节点,再确定根节点在中序序列中的位置,就可以分出左右两棵子树。
这道题我们不需要建树,只要通过递归不断切割字符串就好了。
字符串切割时应注意的问题
那便是切割位置。STL的string类型自带切割方法substr,但搞不清参数就会导致WA甚至RE。
首先我们搞清楚substr方法的使用方法。
string s;
s.substr(order,k);
参数传入一个order,一个k。
函数将会从下标为order的位置开始,连续截取k个字符。返回截取后的字符串。
order显然不能超出0~s.size()-1
的范围。
但是,如果order+k超过了s.size()-1
,函数会自动只截取到s的末尾。
如果不传入k,那么默认截取到末尾。
这个函数是返回一个字符串,而不是对s进行改动。
那么我们现在就开始寻找参数规律。
很容易发现:
-
中序序列中左子树就是从0开始切割到k-1,也就是切割了k个字符;
-
中序序列中右子树就是从k+1开始,一直切割到最后。
然后找前序序列切割的规律。
中序序列中左子树是ABEDF,右子树是HG,对应在前序序列中就是BADEF(0~4)和GH(5~6)。
那么
-
前序序列中左子树是从0开始切割到k-1,也就是切割了k个字符;
-
前序序列中右子树就是从k开始,一直切割到最后
https://www.luogu.com.cn/problem/P1185
https://www.luogu.com.cn/problem/P1364
这是一道简单的二叉树应用问题,问题中的结点数并不多,数据规模也不大,采用邻接矩阵存储,用Floyed法求出任意两结点之间的最短路径长,然后穷举医院可能建立的n个结点位置,找出一个最小距离的位置即可。
https://www.luogu.com.cn/problem/P2872
首先一起分析一下题目意思, 根据最后一句话使所有农场联通, 求最小和的值, 那么我们会很容易的联想到最小生成树, 是的, 正解之一就是最小生成树。
但是现在有几个问题
1.我们只知道点的坐标并不知道各个点之间的距离
解决办法:循环嵌套枚举求出各个点与其后点的距离。 为什么是其后点, 就是比他编号大的点, 因为是双向边,例如从i到j会存一遍那么j从i也会再存一边, 无形之间, 就会变得更复杂
for(int i = 1; i <= n; i++) {
for(int j = i + 1; j <= n; j++) {
double z = juli(i, j);
add(i, j, z);
}
}
2.怎样处理已知边
解决办法:在枚举完所有的边的距离之后, 在读入已知边, 这时两点之间的距离直接存为零即可, 表示从i到j的花费为零。
for(int i = 1; i <= m; i++) {
int x = read(), y = read();
add(x, y, 0.0);
}
这里需要注意一下, 关于add函数中, 最后一个参数必须是double类型的。
https://www.luogu.com.cn/problem/P3366 普及-模板题hh但是我还是错一个点