CSP-S 2025 提高级 第一轮(初赛) 阅读程序(1)

CSP-S 2025 提高级 第一轮(初赛) 阅读程序(1)

【题目】

cpp 复制代码
01 #include <algorithm>
02 #include <cstdio>
03 #include <cstring>
04 bool flag[27];
05 int n;
06 int p[27];
07 int ans = 0;
08 void dfs(int k) {
09     if (k == n + 1){
10         ++ ans;
11         return;
12     }
13     for (int i = 1; i <= n; ++i) {
14         if (flag[i]) continue;
15         if (k > 1 && i == p[k - 1] + 1) continue;
16         p[k] = i;
17         flag[i] = true;
18         dfs(k + 1);
19         flag[i] = false;
20     }
21     return;
22 }
23 int main() {
24     scanf("%d", &n);
25     dfs(1);
26     printf("%d\n", ans);
27     return 0;
28 }

判断题

  1. (1 分)当输入的 n=3n=3n=3 的时候,程序输出的答案为 333。

    A. 正确

    B. 错误

  2. 在 dfs 函数运行过程中,kkk 的取值会满足 1≤k≤n+11\le k\le n+11≤k≤n+1。

    A. 正确

    B. 错误

  3. 删除第 191919 行的 "flagi=false;",对答案不会产生影响。

    A. 正确

    B. 错误

单选题

  1. 当输入的 n=4n=4n=4 的时候,程序输出的答案为( )。

    A. 11

    B. 12

    C. 24

    D. 9

  2. 如果因为某些问题,导致程序运行到第 252525 行的 dfsdfsdfs 函数之前,数组 ppp 的初值并不全为 000,则对程序的影响是( )。

    A. 输出的答案比原答案更小

    B. 无法确定能输出的答案

    C. 程序可能陷入死循环

    D. 没有影响

  3. 假如删去第 141414 行的 "if(flagi) continue;",输入 333,得到的输出答案是( )。

    A. 27

    B. 3

    C. 16

    D. 12

【题目难度】:D

【题目考点】

1. 深搜回溯

【题目解析】

cpp 复制代码
23 int main() {
24     scanf("%d", &n);
25     dfs(1);
26     printf("%d\n", ans);
27     return 0;
28 }

输入nnn,而后调用深搜函数,从111开始进行深搜,搜索结束后最后输出结果ansansans。

cpp 复制代码
13     for (int i = 1; i <= n; ++i) {
14         if (flag[i]) continue;
15         if (k > 1 && i == p[k - 1] + 1) continue;
16         p[k] = i;
17         flag[i] = true;
18         dfs(k + 1);
19         flag[i] = false;
20     }

看dfs中的一般情况,iii从1循环到nnn,如果flag[i]为真,则continue,即直接开始下一次循环。先不看第15行,下面就是深搜求全排列的模板。当前在确定ppp数组中的第kkk个数,flag[i]表示数值iii是否已使用过。

  • 如果数值iii已经使用过,则接下来不用iii,这是一个可行性剪枝。
  • 否则就将p[k]设为iii,而后将iii设为已使用过,即flag[i] = true,继续搜索确定ppp数组第k+1k+1k+1个数,递归调用dfs(k+1),调用结束后,将状态还原,再将iii设为未使用过,即flag[i] = false

第15行也是一项剪枝,如果k>1k > 1k>1而且i == p[k-1]+1,就不将p[k]设为iii,限定k>1k>1k>1的原因是后面要取ppp数组下标k−1k-1k−1位置,如果k=1k=1k=1,那么k−1k-1k−1为0,p[0]不是已确定的ppp序列中的元素。当前要确定的是p[k],那么p[k-1]就是当前这一项的前一项。iii是p[k]待设定的值。那么这句话的意思是:如果当前这一项的值iii比前一项p[k-1]大1,那么就不将p[k]设为iii,也就是说在搜索全排列的过程中,排除了相邻两数后面的数比前面的数大1的情况

cpp 复制代码
09     if (k == n + 1){
10         ++ ans;
11         return;
12     }

递归出口,当kkk为n+1n+1n+1时,p[1]~p[k]都已经设好了值,存在一个满足条件的排列,ansansans计数增加。

该题求解的问题是:输入nnn,求1∼n1\sim n1∼n的排列中,不存在下一项比前一项大1的情况的排列的数量。

判断题

16. 当输入的 n=3n=3n=3 的时候,程序输出的答案为 333。
A. 正确
B. 错误

正确答案:A

按照字典序依次写出1∼31\sim 31∼3的全排列,排除其中存在下一项比前一项大1的排列:
1,2,31,2,31,2,3:不可行。
1,3,21,3,21,3,2:可行。
2,1,32,1,32,1,3:可行。
2,3,12,3,12,3,1:不可行。
3,1,23,1,23,1,2:不可行
3,2,13,2,13,2,1:可行

共3个可行的排列,因此程序会输出3,本题叙述正确。

17. 在 dfs 函数运行过程中,kkk 的取值会满足 1≤k≤n+11\le k\le n+11≤k≤n+1。
A. 正确
B. 错误

正确答案:A

开始调用时传入实参1,形参kkk的值为1。kkk为1∼n1\sim n1∼n时都会进行递归调用dfs(k+1),kkk为n+1n+1n+1时进入递归出口。因此kkk 的取值满足 1≤k≤n+11\le k\le n+11≤k≤n+1,本题叙述正确。

18. 删除第 191919 行的 "flagi=false;",对答案不会产生影响。
A. 正确
B. 错误

正确答案:B

如果删除flag[i] = false,则深搜回溯缺少了回溯的过程,已经如果使用过数iii,在不使用iii时,不会将iii设为未使用过,下一次可以使用iii时就无法再使用iii。

比如当输入nnn为3时,首先dfs(1)中确定了p[1]=1flag[1]=true。而后递归调用dfs(2),确定了p[2]=2, flag[2]=true,接着递归调用dfs(3),确定了p[3]=3, flag[3] = true,而后调用dfs(4),进入递归出口。回退到dfs(3),此时没有将flag[3]设为flase。再回退到dfs(2),这时iii变为3,判断flag[3]为真,直接进行下一次循环,无法将p[2]设为3。这样就无法找到可行的1,3,21,3,21,3,2这一排列,会导致计数减少,影响最值答案。因此本题叙述错误。

单选题

  1. 当输入的 n=4n=4n=4 的时候,程序输出的答案为( )。
    A. 11
    B. 12
    C. 24
    D. 9

正确答案:A

按照字典序依次查看1∼41\sim 41∼4的全排列,筛选出其中不存在下一项比前一项大1的排列。

可以先枚举前两个数的排列,再看后两个数可行的方案

第1、2个数 第3、4个数
1,2 不可行
1,3 4,2
1,4 3,2
2,1 4,3
2,3 不可行
2,4 1,3或3,1
3,1 4,2
3,2 1,4或4,1
3,4 不可行
4,1 3,2
4,2 1,3
4,3 2,1

共11种可行的排列,本题选A。

  1. 如果因为某些问题,导致程序运行到第 252525 行的 dfsdfsdfs 函数之前,数组 ppp 的初值并不全为 000,则对程序的影响是( )。
    A. 输出的答案比原答案更小
    B. 无法确定能输出的答案
    C. 程序可能陷入死循环
    D. 没有影响

正确答案:D

每次确定第kkk位置的值,都会使用当前确定的值iii覆盖p[k]的值。在确定p[k]时,可能用到的p[k-1]位置的值是这一次dfs中先前确定的值,与ppp数组的初值无关,因此ppp的初值是否为000并不影响程序,选D。

  1. 假如删去第 141414 行的 "if(flagi) continue;",输入 333,得到的输出答案是( )。
    A. 27
    B. 3
    C. 16
    D. 12

正确答案:C

如果删去if(flag[i]) continue;,那么即便数值iii在先前已经使用过,还可以再次使用。ppp数组中可以同时存在相同的数值,但还是要满足不存在下一项比前一项大1的情况。

按字典序枚举所有由1∼31\sim 31∼3生成的可能存在重复元素的序列,排除存在下一项比前一项大1的序列,得到的可行的排列有:
1,1,11,1,11,1,1
1,1,31,1,31,1,3
1,3,11,3,11,3,1
1,3,21,3,21,3,2
1,3,31,3,31,3,3
2,1,12,1,12,1,1
2,1,32,1,32,1,3
2,2,12,2,12,2,1
2,2,22,2,22,2,2
3,1,13,1,13,1,1
3,1,33,1,33,1,3
3,2,13,2,13,2,1
3,2,23,2,23,2,2
3,3,13,3,13,3,1
3,3,23,3,23,3,2
3,3,33,3,33,3,3

共16个可行的排列,选C。

相关推荐
小羊在睡觉30 分钟前
力扣84. 柱状图中最大的矩形
后端·算法·leetcode·golang·go
3DVisionary44 分钟前
蓝光三维扫描:医疗制造的精度焦虑怎么解
人工智能·算法·制造·蓝光三维扫描·医疗制造·三维检测·义齿检测
好评笔记1 小时前
机器学习面试八股——常用损失函数
人工智能·深度学习·算法·机器学习·校招
weixin_468466851 小时前
全局与局部注意力机制新手实战指南
人工智能·python·深度学习·算法·自然语言处理·transformer·注意力机制
_日拱一卒1 小时前
LeetCode:994腐烂的橘子
java·数据结构·算法·leetcode·深度优先
珂朵莉MM2 小时前
第七届全球校园人工智能算法精英大赛-算法巅峰赛产业命题赛第3赛季优化题--束搜索
人工智能·算法
Omics Pro3 小时前
首个!外源天然产物综合性代谢图谱
数据库·人工智能·算法·机器学习·r语言
voidmort3 小时前
3. 微调(Fine-tuning)与强化学习(RL)的核心思想
python·深度学习·算法
人道领域3 小时前
【LeetCode刷题日记】669.修剪二叉搜索树
开发语言·python·算法
QiLinkOS4 小时前
【从实验室到商业战场:发明专利如何重塑科技与企业的共生生态】
大数据·c语言·数据结构·c++·人工智能·单片机·算法