全排列问题
题目描述
按照字典序输出自然数 1 1 1 到 n n n 所有不重复的排列,即 n n n 的全排列,要求所产生的任一数字序列中不允许出现重复的数字。
输入格式
一个整数 n n n。
输出格式
由 1 ∼ n 1 \sim n 1∼n 组成的所有不重复的数字序列,每行一个序列。
每个数字保留 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 1≤n≤9。
思路
这道题很简单,一道
普及
−
普及-
普及−难度的题。没有什么可以讲得,就是一个简单地一个
D
F
S
DFS
DFS的暴力搜索。这道题暴力是可以Ac的,但是如果你想(抢最优解 ) 优化,优化起来的过程还是很难的。
第一种解法(较慢, 66 m s 66ms 66ms)
直接暴力搜索,放心,真的不会 T L E TLE TLE。最高也才只有 47 m s 47ms 47ms。
C o d e 1 Code1 Code1:
#include<bits/stdc++.h>
using namespace std;
const int N=100+5;
int n;
bool vis[N];
int used[N];
void out(){
for(int i=0;i<n;i++){
printf("%5d", used[i]);
}
cout<<endl;
return ;
}
void dfs(int x){
if(x==n){
out();
return ;
}
for(int i=1;i<=n;i++){
if(!vis[i]){
vis[i]=1;
used[x]=i;
dfs(x+1);
vis[i]=0;
}
}
}
int main(){
scanf("%d",&n);
dfs(0);
return 0;
}
第二种解法(很快,37 m s ms ms)
优化思路:通过 l o w b i t ( x ) lowbit(x) lowbit(x)和 log 2 x \log_2 x log2x来直接快速定位x中的二进制1,加速寻找没有选择的数字。
C o d e 2 Code2 Code2
#include <bits/stdc++.h>
using namespace std;
int n;
int rk[10];
int Log[1030];
int all;
int lowbit(int x){
return x&(-x);
}
void dfs(int state,int d){
if(n==d){
for(int i=1;i<=n;i++){
printf("%5d",rk[i]);
}
printf("\n");
return ;
}
//翻转状态
//使用lowbit进行加速 取反~
int vis=all&(~state);
while(vis){
int x=lowbit(vis);
rk[d+1]=Log[x]+1;
dfs(state|x,d+1);
vis-=x;
}
}
int main(){
scanf("%d",&n);
all=(1<<n)-1;
for(int i=2;i<=all;i++){
Log[i]=Log[i/2]+1;
}
dfs(0,0);
return 0;
}