2020解题记录
11.15 树
- 小球-drop
- 大事化小,n层化n-1层,计算进入该结点的次数
- 二叉树遍历-flist
- 中序+层序==前序
- 递归+按层遍历=前序遍历
- rank表,寻找最小结点
- 子树上结点号最小的结点是子树的根结点
- FBI树
- 同时进行递归计算FBI和后序遍历
- 猜数字
cout<<(min+max)/2<<endl;
- 人以群分
- 单调序列
- 最小环
- gcd多个最小环
- 物以类聚(如1、3、5、6、4、2)
11.17 树+堆
超级对拍程序
rem Name: Batch For Check rem Copyright: All Right Reserved rem Author: Chen Jie rem Date: 2020/10/17 rem Description: RENAME the *.bat file and run it. rem The batch will consider succesive spaces as one. @echo off ::no parameter then begin for loop if "%1"=="" goto loop set BAT_NAME=%~nx0 ::BAT_NAME=TFILE_NAME.bat set FILE_NAME=%BAT_NAME:~0,-4% ::if no exist the corresponding input file, then end the batch if not exist %FILE_NAME%%1.in ( goto end ) if exist %FILE_NAME%%1.out ( set ANS_NAME=%FILE_NAME%%1.out ) if exist %FILE_NAME%%1.ans ( set ANS_NAME=%FILE_NAME%%1.ans ) copy %FILE_NAME%%1.in %FILE_NAME%.in >nul echo Problem Test Data %1 time<enter %FILE_NAME% < %FILE_NAME%.in > %FILE_NAME%.out time<enter ::if exist error, then pause for showing the difference fc %FILE_NAME%.out %ANS_NAME% /w /n if errorlevel 1 ( pause>nul ) del %FILE_NAME%.in del %FILE_NAME%.out ::end the batch goto end :loop ::call the corresponding data batch for %%i in (0 1 2 3 4 5 6 7 8 9 10 11) do call %0 %%i echo Press Any Key To Exit ... pause>nul :end
就地建堆函数
- make_heap(),pop_heap(),push_heap()
C++中的make_heap(), pop_heap()的头文件为<algorithm>。作用与priority_queue<>;中的成员函数相同,可以单独使用。
make_heap(begin,end,greater<int>());
在容器范围内,就地建堆,保证最大值在所给范围的最前面,其他值的位置不确定pop_heap(begin,end,greater<int>());
将堆顶(所给范围的最前面)元素移动到所给范围的最后,并且将新的最大值置于所给范围的最前面push_heap(begin,end,greater<int>());
当已建堆的容器范围内有新的元素插入末尾后,应当调用push_heap将该元素插入堆中。
code到word带格式复制
- 二叉树输出(btout)
- 一个数组能解决的事不要用结构体
- 查找二叉树(tree_a)
- 对称二叉树(tree_c)
- 合并果子(fruit)
11.18 堆+图
最小字典序Euler回路(逆序)
- 骑马修栅栏(fence)
void find(int now) { for (int k = mi; k <= ma; k++) if (available[now][k] > 0) { available[now][k]--; available[k][now]--; find(k); } c[++cnt] = now; }
命令参数
-
VS2019-项目-属性-调试-命令参数
- 命令行格式指定输入文件
< $(ProjectDir)$(Configuration)\$(ProjectName).in
- 命令行格式指定输入文件
-
基于红黑树的可重复集合
multiset<int>st; st.insert(a); cout << *st.begin() << ' '; st.erase(st.begin()); cout << *(--st.end()) << endl; st.erase(--st.end());
-
看病-hp
- release比debug快,约
4~6~9倍 - 简单的程序倍数高
0.11-0.96 0.7-4 1.4-5.77
- release比debug快,约
-
小明的账单-bill
- heap不会错
- multiset太慢
-
铲雪车(snow)
- 加起来就好了,别多想
-
珍珠(bead)
- 不允许指向引用的指针、迭代器,即不允许定义
vector<typename&>vec;
- 不允许指向引用的指针、迭代器,即不允许定义
11.19 第三节 最短路径算法
FloyedΘ(N3)Floyed \Theta(N^3)FloyedΘ(N3)
- 适用于出现负边权的情况
初始化:点u、v如果有边相连,则dis[u][v]=w[u][v]。 如果不相连则dis[u][v]=INT_MAX
for (k = 1; k <= n; k++) for (i = 1; i <= n; i++) for (j = 1; j <= n; j++) if (dis[i][j] > dis[i][k] + dis[k][j]) dis[i][j] = dis[i][k] + dis[k][j];
- 牛的旅行-travel
这两个牧场都在John的农场上。John将会在两个牧场中各选一个牧区,然后用一条路径连起来,使得连通后这个新的更大的牧场有最小的直径。注意,如果两条路径中途相交,我们不认为它们是连通的。只有两条路径在同一个牧区相交,我们才认为它们是连通的。 现在请你编程找出一条连接两个不同牧场的路径,使得连上这条路径后,这个更大的新牧场有最小的直径。 用Floyed求出任两点间的最短路,然后求出每个点到所有可达的点的最大距离,记做mdis[i]。(Floyed算法) r1=max(mdis[i]); 然后枚举不连通的两点i,j,把他们连通,则新的直径是mdis[i]+mdis[j]+(i,j)间的距离。 r2=min(mdis[i]+mdis[j]+dis[i,j]); re=max(r1,r2);//旧最大与新直径的最小的最大 re就是所求。
DijkstraΘ(N2)Dijkstra \Theta(N^2)DijkstraΘ(N2)
- 不能处理存在负边权的情况
设起点为s,dis[v]表示从s到v的最短路径,pre[v]为v的前驱节点,用来输出路径。 a)初始化:dis[v]=∞(v≠s); dis[s]=0; pre[s]=0; b)For (i = 1; i <= n ; i++) 1.在没有被访问过的点中找一个顶点u使得dis[u]是最小的。 2.u标记为已确定最短路径 3.For与u相连的每个未确定最短路径的顶点v if (dis[u] + w[u][v] < dis[v]) { dis[v] = dis[u] + w[u][v]; pre[v] = u; } c)算法结束:dis[v]为s到v的最短距离;pre[v]为v的前驱节点,用来输出路径。
for (int i = 1; i <= n; ++i) { int k = 0; for (int j = 1; j <= n; ++j) if (!ok[j] && ans[j] < ans[k]) k = j; if (!k)break; ok[k] = true; for (int j = 1; j <= n; ++j) if (!ok[j] && ratio[j][k]) ans[j] = std::min(ans[j], ans[k] * ratio[j][k]); }
Bellman−FordΘ(NE)Bellman-Ford \Theta(NE)Bellman−FordΘ(NE)
- 能够处理存在负边权的情况,但无法处理存在负权回路的情况
设s为起点,dis[v]即为s到v的最短距离,pre[v]为v前驱。w[j]是边j的长度,且j连接u、v。 初始化:dis[s]=0, dis[v]=∞(v≠s),pre[s]=0 For (i = 1; i <= n-1; i++) For (j = 1; j <= E; j++)//注意要枚举所有边,不能枚举点。 if (dis[u] + w[j] < dis[v])//u、v分别是这条边连接的两个点。 { dis[v] = dis[u] + w[j]; pre[v] = u; }
for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j) { dis[f[j].y] = std::min(dis[f[j].y], dis[f[j].x] + f[j].w); dis[f[j].x] = std::min(dis[f[j].x], dis[f[j].y] + f[j].w); }
SPFAΘ(kE)SPFA \Theta(kE)SPFAΘ(kE)
- Bellman−FordBellman-FordBellman−Ford算法的队列实现
- kkk的平均值是2
dis[i]记录从起点s到i的最短路径,w[i][j]记录连接i,j的边的长度。pre[v]记录前趋。 team[1..n]为队列,头指针head,尾指针tail。 布尔数组exist[1..n]记录一个点是否现在存在在队列中。 初始化:dis[s]=0,dis[v]=∞(v≠s),memset(exist,false,sizeof(exist)); 起点入队team[1]=s; head=0; tail=1;exist[s]=true; do { 1、头指针向下移一位,取出指向的点u。 2、exist[u]=false;已被取出了队列 3、For与u相连的所有点v//注意不要去枚举所有点,用数组模拟邻接表存储 if (dis[v]>dis[u]+w[u][v]) { dis[v]=dis[u]+w[u][v]; pre[v]=u; if (!exist[v])//队列中不存在v点,v入队。 { //尾指针下移一位,v入队; exist[v]=true; } } } while (head < tail);
dis[i] = 0; team[0] = i; int head = 0, tail = 1; exist[i] = true; do { int u = team[head]; if (++head == 2 * 牧场)head = 0; exist[u] = false; for (int j = 1; j <= num[u]; ++j) { int v = a[u][j]; if (dis[v] > dis[u] + w[u][v]) { dis[v] = dis[u] + w[u][v]; if (!exist[v]) { team[tail] = v; if (++tail == 2 * 牧场)tail = 0; exist[v] = true; } } } } while (head != tail);
11.20
int a[5] = { 1,2,3,4,5 }; int* p = a; &(p + 2);//“&”要求左值 &*(p + 2);//等于a + 2
11.21 第四节 图的连通性问题
一、判断图中的两点是否连通
- Floyed算法
- 时间复杂度:Θ(N3)\Theta(N^3)Θ(N3)
- 遍历算法
- 时间复杂度:Θ(N2)\Theta(N^2)Θ(N2)
二、最小环问题
最小环就是指在一张图中找出一个环,使得这个环上的各条边的权值之和最小。在Floyed的同时,可以顺便算出最小环。 记两点间的最短路为dis[i][j],g[i][j]为边<i,j>的权值。 for (k = 1; k <= n; k++) { for (i = 1; i <= k - 1; i++) for (j = i + 1; j <= k - 1; j++) answer = min(answer, dis[i][j] + g[j][k] + g[k][i]); for (i = 1; i <= n; i++) for (j = 1; j <= n; j++) dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]); } answer即为这张图的最小环。 一个环中的最大结点为k(编号最大),与它相连的两个点为i,j,这个环的最短长度为g[i][k]+g[k][j]+(i到j的路径中,所有结点编号都小于k的最短路径长度)。 根据Floyed的原理,在最外层循环做了k-1次之后,dis[i][j]则代表了i到j的路径中,所有结点编号都小于k的最短路径。 综上所述,该算法一定能找到图中最小环。
三、求有向图的强连通分量
Kosaraju算法可以求出有向图中的强连通分量个数,并且对分属于不同强连通分量的点进行标记。它的算法描述较为简单: (1) 第一次对图G进行DFS遍历,并在遍历过程中,记录每一个点的退出顺序。 (2)倒转每一条边的方向,构造出一个反图G’。然后按照退出顺序的逆序对反图进行第二次DFS遍历。 每次遍历得到的那些点即属于同一个强连通分量。
凭本事打的表!!
- 组合数
11.22
- B. Deadline Management
- 输入不保证有序
pair<int, int>t[N];
- 输入不保证有序
- C. 撕纸条
- 与顺序无关
- 不用保存数组
- 与顺序无关
- F. 加减乘除
- 函数指针数组
- 4个if也可
- 用一张牌去匹配另一张牌
bool (*check[4])(int, int) = { check1,check2,check3,check4 };
- 函数指针数组
QQ截图复制色号
- 按C复制色号dd,dd,dd,Ctrl+C复制16进制色号#hhhhhh
浙公网安备 33010602011771号