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
posted @ 2023-09-11 22:28  new-code  阅读(168)  评论(0)    收藏  举报