CSP初赛复习-31-阅读程序-递归-DFS
DFS 全称为深度优先搜索(Depth-First Search)
是一种用于遍历或搜索图或树的算法。它从图或树的根节点开始,沿着一条路径尽可能深入地搜索,直到到达不能再继续前进的节点,然后回溯到前一个节点,继续搜索其他路径。
具体如下
1 从起始节点开始,标记该节点为已访问。
2 对于当前节点的每个未访问过的相邻节点,递归或使用栈将其作为新的当前节点,并重复步骤1。
3 如果当前节点没有未访问的相邻节点,回溯到上一个节点,并重复步骤2。
阅读程序 CSP-J 2020
01 #include <algorithm>
02 #include <iostream>
03 using namespace std;
04 int n;
05 int d[50][2];
06 int ans;
/*
递归2个参数 n和sum
n 计算前n行第1列的2个数的和+第2列2个数差的绝对值
sum 结果累加到sum
1~n-1 累加到sum
2~n-1 累加到sum
3~n-1 累加到sum
...
n-1~n-1累加到sum
上述sum取最大值 赋值给ans
*/
07 void dfs(int n, int sum) {
08 if (n == 1) {//一次累加结束 取sum的最大值给ans
09 ans = max(sum, ans);
10 return;
11 }
12 for (int i = 1; i < n; ++i) {
13 int a = d[i - 1][0], b = d[i - 1][1]; //a为i-1行的第0列 b为i-1行的第1列
14 int x = d[i][0], y = d[i][1];//x第i行的第0列 y为第i行的第1列
15 d[i - 1][0] = a + x;//第i行和i-1行第0列相加存放到i-1行第0列
16 d[i - 1][1] = b + y;//第i行和i-1行第1列相加存放到i-1行第1列
17 for (int j = i; j < n - 1; ++j)//i行开始,后面一行覆盖前面一行
18 d[j][0] = d[j + 1][0], d[j][1] = d[j + 1][1];
19 int s = a + x + abs(b - y);//i-1行第0列+i行第0列 + abs(i-1行第1列-i行第1列)
20 dfs(n - 1, sum + s);//缩一行后,继续计算
21 for (int j = n - 1; j > i; --j)//回溯 i+1行开始,前面一行覆盖后面一行(i+1~n-1) 对第17~18行进行回退
22 d[j][0] = d[j - 1][0], d[j][1] = d[j - 1][1];
23 d[i - 1][0] = a, d[i - 1][1] = b;//回溯 对第15~16行进行回退
24 d[i][0] = x, d[i][1] = y;//回溯 同21~22行一起对第17~18行进行回溯 回溯第i行
25 }
26}
27 int main() {
28 cin >> n;//读入正整数n
29 for (int i = 0; i < n; ++i)//读入n个输入放入第1列
30 cin >> d[i][0];
31 for (int i = 0; i < n;++i)//读入n个输入放入第2列
32 cin >> d[i][1];
33 ans = 0;
34 dfs(n, 0);//
35 cout << ans << endl;
36 return 0;
37 }
假设输入的 n是不超过 50 的正整数,d[i][0]、d[i][1] 都是不超过10000 的正整数,完成下面的判断题和单选题:
判断题
1 若输入n 为 0,此程序可能会死循环或发生运行错误。( )
答案 F
n为0时,程序不会发生死循环也不会允许错误
n为0时,dfs函数条件都不满足,直接退出dfs函数,ans输出0
2 若输入n 为 20,接下来的输入全为 0,则输出为 0。( )
答案 T
第0列计算涉及本列数相加,第1列计算涉及本列数相减取绝对值,输入全为0无论上述规则怎么运算都是0
3 输出的数一定不小于输入的 d[i] [0] 和 d[i] [1] 的任意一个。( )
答案 F
不一定可以找反例
//输入 1 2
2
1 2
99 100
//输出
4
单选题
4 若输入的 n 为 20,接下来的输入是 20 个9 和 20 个 0,则输出为( )
A 1890
B 1881
C 1908
D 1917
答案 B
第0列都是整数,第1列都为0
只需考虑第0列,最大的应该是第0列从0~19行累加
n=20时 s=9+9 累加到sum
n=19时 s=9+9+9 累加到sum
...
n=2时 s=9*20 累加到sum
即为每次加9然后在求和
(9+9)+(9+9+9)+(9*20)=(2+3+4+...20)*19
根据等比数列求和
Sn=(a1+an)/2 *n
S20=(2+20)/2 *19=209
209 * 9 = 1881
5 若输入的 n 为 30,接下来的输入是 30 个 0 和 30 个 5,则输出为( )
A 2000
B 2010
C 2030
D 2020
答案 C
第0列都是0,第1列为整数
只需考虑第1列,最大的应该是第0列从0~30行累加
n=30时 s=0 累加到sum
n=29时 s=5 累加到sum
...
n=2时 s=9*28 累加到sum
即为每次加9然后在求和
(5)+(5+5)+(5+5+5)+(5*28)=(1+2+3+...+28)*5
根据等比数列求和
Sn=(a1+an)/2 *n
S20=(1+28)/2 *28=406
209 * 5 = 2030
6(4 分)若输入的 n 为 15,接下来的输入是 15 到 1,以及 15 到 1,则输出为( )
A 2440
B 2220
C 2240
D 2420
答案 C
第0列都是整数,第1列为整数
分别考虑第0列,第1列
第0列
n=15时 s=15+14=(15+15-1) 累加到sum
n=14时 s=15+14+13=(15+15+15-1-2) 累加到sum
n=13时 s=15+14+13+12=(15+15+15+15-1-2-3) 累加到sum
...
n=2时 s=15+14+13+...+1=15*15-1-2-3-4-5-6-7-8-9-10-11-12-13-14 累加到sum
上述计算转换为
(15+15)+(15+15+15)+(15+15+15+15)+...+15*15 -1-3-6-10-...105
(2+3+...+15)*15-560
根据等差数列求和
(2+15)*14/2*15=560=1785-560=1225
第1列
n=15时 s=|15-14|
n=14时 s=|15+14-13|
n=13时 s=|15+14+13-12|
...
n=2时 s=|15+14+13+...+2-1| 累加到sum
上述计算转换为
15+(15+15)+(15+15+15)+...15*14-(1+3+6+...91)-(14+13+12+...1)
根据等差数列求和
(1+14)*14/2*15=1575
(1+3+6+...91)=455
(14+13+12+...1)=105
所以
1575-455-105=1015
第0列和第1列相加
1225+1015=2240
补充
如下数列
1 2 3 4 5 6 7
1 3 6 10 15 21 ?
上面数列通项公式为 n*(n+1)/2
因此第7项为7*8/2=28
前n项和公式
Sn=n*(n+1)*(2n+1)/12 + n*(n+1)/4=n*(n+1)*(n+2)/6
前14项之和
S14=14*15*16/6=560
S13=13*14*15/6=455
S7=7*8*9/6=84
作者:newcode 更多资源请关注纽扣编程微信公众号

从事机器人比赛、机器人等级考试、少儿scratch编程、信息学奥赛等研究学习

浙公网安备 33010602011771号