题目描述
把 1~n 这 n 个整数排成一行后随机打乱顺序,输出所有可能的次序。
输入格式
一个整数n。
输出格式
按照从小到大的顺序输出所有方案,每行1个。
首先,同一行相邻两个数用一个空格隔开。
其次,对于两个不同的行,对应下标的数一一比较,字典序较小的排在前面。
数据范围
1≤n≤9
输入样例:
3
输出样例:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
联想之前的输出排列的dfs算法
void dfs(int d){
if(d == n){
for(int i = 0;i < t.size();i++){
cout<<t[i]+1<<" ";
}
cout<<endl;
return;
}
dfs(d+1);
t.push_back(d);
dfs(d+1);
t.pop_back();
}
这题是输出全排列的所有序列,之前的排列是只用确定某个数选与不选,而这里需要判断的是是否已经被选了,可用标志数组,也可以用状态压缩。原来dfs的一个参数d是已判断数的个数,达到n则终止,这里的d则是已选择数的个数,st表示哪些已被选择。对于这种都要被选择,只是选择时间有先后顺序的问题,一般在dfs里要加上循环。而与之前算法的另外的不同就是当某数还未被选择时,选择该数,不用在考虑不选择该数的情况,一方面是因为全排列每个数都要被选择;另一方面是在递归返回时会自动的改变数选择的顺序。
#include <iostream>
#include <vector>
using namespace std;
int n;
vector<int> t;
void dfs(int d,int st){
if(d == n ){
for(int i = 0;i < t.size();i++){
cout<<t[i]+1<<" ";
}
cout<<endl;
return;
}
for(int i = 0;i < n;i++){
if(!(st >> i & 1)){
t.push_back(i);
dfs(d+1,st | 1 << i );
t.pop_back();
}
}
}
int main(){
cin>>n;
dfs(0,0);
return 0;
}