当前位置: 首页 > news >正文

洛谷P1706 全排列题解

P1706 全排列问题

题目描述

按照字典序输出自然数 1 1 1 n n n 所有不重复的排列,即 n n n 的全排列,要求所产生的任一数字序列中不允许出现重复的数字。

输入格式

一个整数 n n n

输出格式

1 ∼ n 1 \sim n 1n 组成的所有不重复的数字序列,每行一个序列。

每个数字保留 5 5 5 个场宽。

输入输出样例 #1

输入 #1

3

输出 #1

	1    2    3
    1    3    2
    2    1    3
    2    3    1
    3    1    2
    3    2    1

说明/提示

1 ≤ n ≤ 9 1 \leq n \leq 9 1n9

这个问题呢,是很明显的DFS(深度优先搜索)的问题,如果你们不了解DFS,可以自己去上网查。我简单的说一下概念:

DFS是一种用于遍历或搜索树或图的算法,其核心思想是"尽可能深"地搜索图的分支。当节点v的所在边都已被探寻过,搜索将回溯到发现节点v的那条边的起始节点。

可能有些人懵了,所以,说白了就是: 不撞南墙不回头 \color{red}不撞南墙不回头 不撞南墙不回头

再简单点:

  • 为了求得问题的解,先选择某一种可能情况向前探索;
  • 在探索过程中,一旦发现原来的选择是错误的,就退回一步重新选择,继续向前探索;
  • 如此反复进行,直至得到解或证明无解。
DFS的操作步骤

1.假设一个数组a[5][5],零代表墙,一代表路,初始点是a[1][1],要到达a[n][n]。

假如数组为:

6

dfs方式如下:
5

大家应该也比较了解DFS了吧,那我们便开始讲题;

做题目的第一步:搞好DFS前要条件

#include<bits/stdc++.h>
using namespace std;
int n, a[15], book[15];
/*我们将题目的输入变量 n 定义出来;
a 数组是排列的结果,book 数组是标记某个数字有没有用 */
int main(){
    cin >> n;

    return 0;
}

做题目的第二步:做好DFS边界处理

#include<bits/stdc++.h>
using namespace std;
int n, a[15], book[15];
/*我们将题目的输入变量 n 定义出来;
a 数组是排列的结果,book 数组是标记某个数字有没有用 */
void dfs(int x){
    if(x > n){//代表已经可以了,所有的数字都排好了
        for(int i = 1; i <= n; i ++){
            cout << setw(5) << a[i];//题目要求5个场宽
        }
        cout << endl;
        return ;//回溯(返回)
    }
    
}
int main(){
    cin >> n;
    
    return 0;
}

做题目的第三步:写好DFS数组排列

#include<bits/stdc++.h>
using namespace std;
int n, a[15], book[15];
/*我们将题目的输入变量 n 定义出来;
a 数组是排列的结果,book 数组是标记某个数字有没有用 */
void dfs(int x){
    if(x > n){//代表已经可以了,所有的数字都排好了
        for(int i = 1; i <= n; i ++){
            cout << setw(5) << a[i];//题目要求5个场宽
        }
        cout << endl;
        return ;//回溯(返回)
    }
    for(int i = 1; i <= n; i ++){
        if(book[i] == 0){//如果这个数没有用过
            a[x] = i;//标记(x 作为第几位)
            book [i] = 1; // 这个数用过了
            dfs(x + 1); //进行下一位的排列
            book [i] = 0; //回溯时因为新的一轮开始,所以没有用过,重新标记
        }
    }
}
int main(){
    cin >> n;
    dfs(1);//进行DFS
    return 0;
}

这时候,代码就写完了,没听懂的同学可以看一下模拟过程,听懂的同学可以一键三联吗:

全排列问题的模拟过程

初始状态

  • n = 3
  • 数组 a = [0, 0, 0, ...] (初始全为0)
  • 标记数组 book = [0, 0, 0, ...] (初始全为0,表示所有数字未被使用)

调用 dfs(1)

dfs(1) - 第一层递归 (x=1)

循环 i 从 1 到 3:

  1. i=1:

    • book[1]==0,可以使用
    • 设置 a[1]=1
    • 标记 book[1]=1
    • 调用 dfs(2)
    dfs(2) - 第二层递归 (x=2)

    循环 i 从 1 到 3:

    1. i=1:

      • book[1]==1,跳过
    2. i=2:

      • book[2]==0,可以使用
      • 设置 a[2]=2
      • 标记 book[2]=1
      • 调用 dfs(3)
      dfs(3) - 第三层递归 (x=3)

      循环 i 从 1 到 3:

      1. i=1:

        • book[1]==1,跳过
      2. i=2:

        • book[2]==1,跳过
      3. i=3:

        • book[3]==0,可以使用
        • 设置 a[3]=3
        • 标记 book[3]=1
        • 调用 dfs(4)
        dfs(4) - 第四层递归 (x=4)

        x>n,输出排列: 1 2 3 (每个数字占5个宽度)

        • 返回
      • 回溯: book[3]=0

      • 循环结束

    • 回溯: book[2]=0
    1. i=3:

      • book[3]==0,可以使用
      • 设置 a[2]=3
      • 标记 book[3]=1
      • 调用 dfs(3)
      dfs(3) - 第三层递归 (x=3)

      循环 i 从 1 到 3:

      1. i=1:

        • book[1]==1,跳过
      2. i=2:

        • book[2]==0,可以使用
        • 设置 a[3]=2
        • 标记 book[2]=1
        • 调用 dfs(4)
        dfs(4) - 第四层递归 (x=4)

        x>n,输出排列: 1 3 2

        • 返回
      • 回溯: book[2]=0
      1. i=3:
        • book[3]==1,跳过
    • 回溯: book[3]=0

    • 循环结束

  • 回溯: book[1]=0
  1. i=2:

    • book[2]==0,可以使用
    • 设置 a[1]=2
    • 标记 book[2]=1
    • 调用 dfs(2)
    dfs(2) - 第二层递归 (x=2)

    循环 i 从 1 到 3:

    1. i=1:

      • book[1]==0,可以使用
      • 设置 a[2]=1
      • 标记 book[1]=1
      • 调用 dfs(3)
      dfs(3) - 第三层递归 (x=3)

      循环 i 从 1 到 3:

      1. i=1:

        • book[1]==1,跳过
      2. i=2:

        • book[2]==1,跳过
      3. i=3:

        • book[3]==0,可以使用
        • 设置 a[3]=3
        • 标记 book[3]=1
        • 调用 dfs(4)
        dfs(4) - 第四层递归 (x=4)

        输出排列: 2 1 3

        • 返回
      • 回溯: book[3]=0
    • 回溯: book[1]=0
    1. i=2:

      • book[2]==1,跳过
    2. i=3:

      • book[3]==0,可以使用
      • 设置 a[2]=3
      • 标记 book[3]=1
      • 调用 dfs(3)
      dfs(3) - 第三层递归 (x=3)

      循环 i 从 1 到 3:

      1. i=1:

        • book[1]==0,可以使用
        • 设置 a[3]=1
        • 标记 book[1]=1
        • 调用 dfs(4)
        dfs(4) - 第四层递归 (x=4)

        输出排列: 2 3 1

        • 返回
      • 回溯: book[1]=0
      1. i=2:

        • book[2]==1,跳过
      2. i=3:

        • book[3]==1,跳过
    • 回溯: book[3]=0

    • 循环结束

  • 回溯: book[2]=0
  1. i=3:

    • book[3]==0,可以使用
    • 设置 a[1]=3
    • 标记 book[3]=1
    • 调用 dfs(2)
    dfs(2) - 第二层递归 (x=2)

    循环 i 从 1 到 3:

    1. i=1:

      • book[1]==0,可以使用
      • 设置 a[2]=1
      • 标记 book[1]=1
      • 调用 dfs(3)
      dfs(3) - 第三层递归 (x=3)

      循环 i 从 1 到 3:

      1. i=1:

        • book[1]==1,跳过
      2. i=2:

        • book[2]==0,可以使用
        • 设置 a[3]=2
        • 标记 book[2]=1
        • 调用 dfs(4)
        dfs(4) - 第四层递归 (x=4)

        输出排列: 3 1 2

        • 返回
      • 回溯: book[2]=0
    • 回溯: book[1]=0
    1. i=2:

      • book[2]==0,可以使用
      • 设置 a[2]=2
      • 标记 book[2]=1
      • 调用 dfs(3)
      dfs(3) - 第三层递归 (x=3)

      循环 i 从 1 到 3:

      1. i=1:

        • book[1]==0,可以使用
        • 设置 a[3]=1
        • 标记 book[1]=1
        • 调用 dfs(4)
        dfs(4) - 第四层递归 (x=4)

        输出排列: 3 2 1

        • 返回
      • 回溯: book[1]=0
      1. i=2:

        • book[2]==1,跳过
      2. i=3:

        • book[3]==1,跳过
    • 回溯: book[2]=0
    1. i=3:
      • book[3]==1,跳过
    • 循环结束
  • 回溯: book[3]=0

到了这里,大家应该听懂了,记得一键三连哦!

d

相关文章:

  • 【redis】持久化之RDB与AOF
  • 前后前缀
  • Windows下在IntelliJ IDEA 使用 Git 拉取、提交脚本出现换行符问题
  • 比较4点结构和4次函数
  • C++编程语言:抽象机制:一个矩阵的设计(Bjarne Stroustrup)
  • 探索:如何构建一个自我的AI辅助的开发环境?
  • DeepSeek API集成开发指南——Flask示例实践
  • Python实现将字典中键相同的值合并
  • python学习笔记(1)
  • 二层综合实验
  • Pycharm运行时报“Empty suite”,可能是忽略了这个问题
  • C语言基础知识09---文件操作
  • ai画图comfyUI 选中替换inpaint。
  • JavaScript的作用域
  • Python @property 装饰器深度使用教程
  • 基于python的汽车行业大数据分析系统
  • Causal Effect Inference withDeep Latent-Variable Models
  • Docker安装MySql 8.0
  • 暴力搜索算法详解与TypeScript实战
  • JavaScript 性能优化实战:突破瓶颈,打造极致 Web 体验
  • 流散千年的金印归藏故里,实证晋代册封高句丽
  • 国家文物局副局长罗文利履新中国国家博物馆馆长
  • 中英举行人工智能对话
  • 广东7月起施行:不得以任何方式强制购买中小学校服或捆绑销售
  • 【社论】鸿蒙破壁,向最难处攻坚
  • 国家发改委谈整治“内卷式”竞争:加力破除地方保护和市场分割,遏制落后产能无序扩张