大模型应用开发标准化:从技术到商业价值的实践框架
2026/7/24 3:38:28
#include<bits/stdc++.h> using namespace std; int path[15]; bool vis[15]; int n; void dfs(int cnt){ if(cnt>n){ for(int i=1;i<=n;i++) cout<<" "<<path[i]; cout<<"\n"; return; } for(int i=1;i<=n;i++){ if(vis[i]==0){ vis[i]=1; path[cnt]=i; dfs(cnt+1); vis[i]=0; } } } int main(){ ios::sync_with_stdio(false); cin.tie(0); cin>>n; dfs(1); return 0; }题目传送门https://www.luogu.com.cn/problem/P1706
我是一名专注信奥赛(CSP-J/S、NOIP)的教练。
- 如果你觉得这篇题解对你有帮助,欢迎点击关注我的CSDN账号,我会持续更新高质量算法解析。
- 我深知算法思维的构建远比单纯通过题目更重要,本系列题解不局限于AC代码的堆砌,而是致力于拆解题目背后的逻辑链条与核心知识点
- 备赛路上若遇瓶颈,欢迎随时评论或私信,我将甄选典型疑难问题,通过视频讲解或撰写专项文章的形式,为你提供深度答疑。
这道题是一道非常经典的深度优先搜索(DFS)与回溯算法入门题。
问题转化(排列树模型):
生成 1∼n 的全排列,本质上是在构建一棵深度为 nn 的“排列树”。我们在树的每一层(对应排列中的每一个位置),从 1∼n中选择一个还没有被使用过的数字填入。
算法设计(DFS + 状态标记):
path来记录当前正在构建的排列序列。vis来记录哪些数字已经被用过了(避免重复)。path中,标记为已用,然后进入下一层递归。vis[i] = 0),以便在后续的循环中尝试其他数字。#include<bits/stdc++.h> using namespace std; int path[15]; bool vis[15]; int n;path数组用来存放当前正在生成的排列序列;vis数组(visit的缩写)是一个状态标记数组,vis[i] == 1表示数字 ii 已经在当前排列中被使用过,0表示未使用。由于题目保证 n≤9n≤9 ,数组开 15 足够。void dfs(int cnt){ if(cnt > n){ for(int i = 1; i <= n; i++) cout << " " << path[i]; cout << "\n"; return; } for(int i = 1; i <= n; i++){ if(vis[i] == 0){ vis[i] = 1; path[cnt] = i; dfs(cnt + 1); vis[i] = 0; // 回溯:撤销选择,恢复现场 } } }cnt > n时,说明前 nn 个位置都已经填满了数字,一个完整的排列已经生成。此时按照题目要求的“每个数字保留 5 个场宽”(即前面加 4 个空格)输出path数组。cnt,我们尝试枚举 1∼n1∼n 的所有数字。if(vis[i] == 0)保证了我们只会选择那些尚未被使用的数字。i后,将其标记为已用(vis[i] = 1),存入路径(path[cnt] = i),然后进入下一层dfs(cnt + 1)去填充下一个位置。dfs(cnt + 1)执行完毕返回时,说明以当前数字i为起点的所有排列都已经生成完了。为了尝试下一个数字,我们必须把i的状态恢复为未使用(vis[i] = 0),这就是回溯的核心。int main(){ ios::sync_with_stdio(false); cin.tie(0); cin >> n; dfs(1); return 0; }dfs(1)开始,表示从排列的第 1 个位置开始填数。由于我们是从 1 到 n 顺序枚举数字的,所以生成的排列天然就是字典序的。| 代码模块 | 核心变量/操作 | 精炼作用 | 解决的痛点 |
|---|---|---|---|
| 路径记录 | path[cnt] = i | 记录当前正在构建的排列序列 | 保证了在到达叶子节点时,能够完整地输出整个排列 |
| 状态标记 | vis[i] = 1 | 标记数字 i 已被使用 | 保证了“所产生的任一数字序列中不允许出现重复的数字” |
| 回溯恢复 | vis[i] = 0 | 撤销对数字 i 的使用标记 | 使得数字 ii 可以在其他分支中被再次使用,是生成全排列的关键 |
| 字典序保证 | for(int i = 1; i <= n; i++) | 从小到大枚举数字 | 保证了输出的排列序列天然符合字典序要求,无需额外排序 |
| 格式化输出 | cout << " " << path[i] | 每个数字前输出4个空格 | 完美契合题目“每个数字保留 5 个场宽”的格式要求 |