最基础的深搜全排列
#include <bits/stdc++.h>
using namespace std;
int n, a[10];
bool vis[10];
//准备给第cnt个位置安排数字
void dfs(int cnt)
{
//准备给第n+1个位置安排数的时候, 说明前n个位置都安排好了
if(cnt==n+1){
for(int i=1; i<=n; ++i){
printf("%5d", a[i]);
}
printf("\n");
return;
}
//准备给第cnt个位置安排
for(int i=1; i<=n; ++i){
if(!vis[i]){ //i这个数没被前面的位置使用
a[cnt]=i;
vis[i]=true;
dfs(cnt+1);
vis[i]=false;
}
}
}
int main()
{
scanf("%d", &n);
dfs(1); //准备给第一个位置安排数字
return 0;
}
#include <bits/stdc++.h>
using namespace std;
int n, a[10006], total;
bool vis[1006];
//当前是填第几个数
void dfs(int cnt)
{
if(cnt==n+1){
for(int i=1; i<=n; ++i){
printf("%d ", a[i]);
}
printf("\n");
total++;
return;
}
for(int i=1; i<=n; ++i){
if(vis[i]==false){
vis[i]=true;
a[cnt]=i;
dfs(cnt+1);
vis[i]=false;
}
}
}
int main()
{
scanf("%d", &n);
for(int i=1; i<=n; ++i){
vis[i]=true;
a[1]=i;
dfs(2);
vis[i]=false;
}
printf("%d", total);
return 0;
}
用next_permutation(a+1, a+n+1);函数
#include <bits/stdc++.h>
using namespace std;
int n, a[10], tot=1;
int main()
{
scanf("%d", &n);
for(int i=1; i<=n; ++i){
tot*=i;
a[i]=n+1-i;
}
while(tot--){
next_permutation(a+1, a+n+1);
for(int i=1; i<=n; ++i){
printf("%5d", a[i]);
}
printf("\n");
}
return 0;
}
P1088 [NOIP2004 普及组] 火星人
基于某个排列状态,找出其后面第m个全排列
//搜索和排列的一道好题
//基于当前的start[i]这一状态, 继续往后找m个全排列
#include <bits/stdc++.h>
using namespace std;
int n, m, a[10006], start[10006], total=-1; //因为初始状态会再找一遍, 所以total初始化为-1
bool vis[10006];
//基于当前的start[i]这一状态, 继续往后找m个全排列
//当前是填第几个数
void dfs(int cnt)
{
if(cnt==n+1){ //n个数全部排列完了
total++; //方案数++
if(total==m){ //当前找到的为初始状态后面的第m个排列
for(int i=1; i<=n; ++i){
printf("%d ", a[i]);
}
exit(0); //结束程序
}
return;
}
//flag为false表示前cnt-1位均未发生改变, 仍为start[]初始状态
bool flag=false;
for(int i=1; i<=cnt-1; ++i){
if(a[i]!=start[i]){ //只要前面有发生改变的, 就置为true
flag=true;
}
}
if(flag==false){ //前面的位数都没变, 这一位只能从start[cnt]变到n
for(int i=start[cnt]; i<=n; ++i){
if(vis[i]==false){
vis[i]=true;
a[cnt]=i;
dfs(cnt+1);
vis[i]=false;
}
}
}
else{ //前面的位数有改变, 这一位可以取1~n, 只要vis[]满足前面没取过即可
for(int i=1; i<=n; ++i){
if(vis[i]==false){
vis[i]=true;
a[cnt]=i;
dfs(cnt+1);
vis[i]=false;
}
}
}
}
int main()
{
scanf("%d", &n);
scanf("%d", &m);
for(int i=1; i<=n; ++i){
scanf("%d", &start[i]);
}
//a[1]可能的取值范围为: start[1]~n, 基于a[1]去搜索a[2~n]
for(int i=start[1]; i<=n; ++i){
vis[i]=true;
a[1]=i;
dfs(2);
vis[i]=false;
}
return 0;
}
方法二:直接调用next_permutation(a+1, a+n+1)函数来计算全排列
//搜索和排列的一道好题
//基于当前的start[i]这一状态, 继续往后找m个全排列
//调用库函数
#include <bits/stdc++.h>
using namespace std;
int n, m, a[10006];
int main()
{
scanf("%d", &n);
scanf("%d", &m);
for(int i=1; i<=n; ++i){
scanf("%d", &a[i]);
}
while(m--){
next_permutation(a+1, a+n+1);
}
for(int i=1; i<=n; ++i){
printf("%d ", a[i]);
}
return 0;
}