题目来源:全排列问题 - 洛谷
参考书目:《深入浅出程序设计竞赛(基础篇)》
解题思路:这道题主要是考察next_permutation函数的使用,这个函数可以应用于数组或容器(如 vector
),使得原地生成给定序列的下一个排列。如果序列已经处于最大可能的排列(即没有下一个更大的排列),则该函数返回 false
并将序列重置为最小可能的排列(即升序排列),否则返回 true
。
例如,对于序列 [1, 2, 3]
,下一个排列是 [1, 3, 2]
,依此类推,直到 [3, 2, 1]
,这是这组元素的最大排列。之后,再次调用 next_permutation
会返回到最小排列 [1, 2, 3]
并返回 false
。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int a[10], n; // 定义一个全局数组 a,最多存放 10 个元素,以及一个整型变量 n
int main() {
cin >> n; // 从标准输入读取一个整数 n
for (int i = 1; i <= n; i++) // 初始化数组 a 的前 n 个元素,值为其索引值(1 到 n)
a[i] = i;
do {
for (int i = 1; i <= n; i++) // 遍历并打印当前排列的每个元素
printf("%5d", a[i]); // 打印每个元素,宽度为 5,这样做是为了对齐输出
puts(" "); // 在当前排列输出完毕后打印一个换行符,以分隔不同的排列
} while (next_permutation(a + 1, a + n + 1)); // 生成并检查是否还有下一个排列,如果有,则继续循环
return 0; // 程序正常结束
}
程序的工作流程如下:
- 首先,读取用户输入的整数
n
,这个整数指定了要生成排列的大小。 - 使用
for
循环初始化数组a
,使其包含从 1 到n
的连续整数。 - 使用
do-while
循环和next_permutation
函数生成数组a
的所有可能排列。在每次迭代中:- 通过一个内部的
for
循环,打印当前的排列(数组a
中的元素)。 - 使用
printf
函数以固定宽度(5个字符)打印每个元素,以便排列整齐。 - 使用
puts
函数在每个排列后打印一个新行,以便区分不同的排列。
- 通过一个内部的
next_permutation(a + 1, a + n + 1)
调用检查数组a
(从第一个元素开始到最后一个元素)是否可以被重排为下一个字典序更大的排列。如果可以,它会进行重排并返回true
;否则,返回false
并重置为最小排列(这里不会发生,因为循环结束时已经是最后一个排列)。