传送门:P1706 全排列问题
题目描述
按照字典序输出自然数 1 到 所有不重复的排列,即
的全排列,要求所产生的任一数字序列中不允许出现重复的数字
输入格式
一个整数 。
输出格式
由 1~ 组成的所有不重复的数字序列,每行一个序列。
每个数字保留 5 个场宽。
输入输出样例
输入 #1
3
输出 #1
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
说明/提示
。
----------------------------------------------------------分割线--------------------------------------------------------------
知识点
STL或DFS
方法1(STL)
在algorithm头文件中有一个叫next_permutation()的函数,该函数会从序列的末尾开始向前查找,找到第一对相邻的元素 (i, i+1),使得 i 位置的元素小于 i+1 位置的元素。如果找不到这样的元素对,说明序列已经是字典序上最大的排列,此时会将序列反转。当 next_permutation 在无法生成当前排列的下一个字典序排列时立即返回 false。
对于该题,先输入n,并输出第一个排列1~n,之后利用while循环不断反转该序列,每反转一次输出一次排列。
AC代码
#include<iostream>
#include<algorithm>
#include<iomanip>
using namespace std;
int n;
int main() {
cin >> n;
int a[15];
for (int i = 1; i <= n; i++) {
a[i] = i;
cout << setw(5) << a[i];
}
cout << endl;
while (next_permutation(a+1, a + n+1))
{
for (int i = 1; i <= n; i++) {
cout << setw(5) << a[i];
}
cout << endl;
}
return 0;
}
方法2(DFS)
仔细分析该题,可以发现此题也可以用DFS的思想来解决。第一次搜索时,第一个数从1开始,接着搜索第二个数,因为不能与第一个数相同,故第二个数可以为2或3,接着搜索第三个数,若第二个数为2,则第三个数为3,反之为2。在搜索到底(即到达n)时,第一个数加1,从2开始再次搜索。故可以使用DFS的思想来解决该题
AC代码
#include<iostream>
#include<algorithm>
#include<iomanip>
using namespace std;
int n,num[15],judge[15];//使用num数组存储每个排列,judge数组判断是否选择过该数
void dfs(int k) {
if (k == n) {//搜索到底时输出该排列
for (int i = 1; i <= n; i++) {
cout << setw(5) << num[i];
}
cout << endl;
}
for (int i = 1; i <= n; i++) {
if (judge[i] == 0) {
judge[i] = 1;
num[k + 1] = i;
dfs(k + 1);
judge[i] = 0;
}
}
}
int main() {
cin >> n;
dfs(0);
return 0;
}