1、数的全排列
求数字 1 ~ n 的全排列,例如 1~3 的全排列,输出 1 2 3, 1 3 2 , 2 1 3, 2 3 1, 3 1 2, 3 2 1
#include<bits/stdc++.h>
using namespace std;
#define runfile freopen("E:/Code/CB/Root/data.txt", "r", stdin)
#define stopfile fclose(stdin)
const int maxn = 100;
int n,vis[maxn],perm[maxn];//标记数组,全排列
void dfs(int step)//全排列,step 为当前选择元素的数量
{
if(step == n+1)//已经选满 n 个数,得到全排列,深搜结束
{
for(int i = 1; i <= n; i++)
{
cout<<perm[i]<<" ";
}
cout<<endl;
}
else
{
//从1~n个选中一个未被选中的元素,然后继续深搜。深搜结束之后回溯
for(int i = 1; i <= n; i++)
{
if(!vis[i])//未被标记
{
vis[i] =1;//标记
perm[step] = i;//记录
dfs(step+1);//深搜下一步
vis[i] = 0;//回溯
}
}
}
}
int main()
{
// runfile;
ios::sync_with_stdio(false);
while(cin>>n)
{
memset(vis, 0, sizeof(vis));
dfs(1);
}
// stopfile;
return 0;
}
2、字符的全排列
#include<bits/stdc++.h>
using namespace std;
#define runfile freopen("E:/Code/CB/Root/data.txt", "r", stdin)
#define stopfile fclose(stdin)
const int maxn = 100;
int n,vis[200];//标记数组,全排列
char s[maxn],perm[maxn];
void dfs(int step)//全排列,step 为当前选择元素的数量
{
if(step == n+1)//已经选满 n 个数,得到全排列,深搜结束
{
for(int i = 1; i <= n; i++)
{
cout<<perm[i]<<" ";
}
cout<<endl;
}
else
{
//从1~n个选中一个未被选中的元素,然后继续深搜。深搜结束之后回溯
for(int i = 0; i < n; i++)
{
int temp = (int)s[i];//注意此处与数字标记的不同
if(!vis[temp])//未被标记
{
vis[temp] =1;//标记
perm[step] = s[i];//记录
dfs(step+1);//深搜下一步
vis[temp] = 0;//回溯
}
}
}
}
int main()
{
// runfile;
ios::sync_with_stdio(false);
while(scanf("%d",&n) != EOF)
{
getchar();
for(int i = 0; i < n; i++)
{
scanf("%c",&s[i]);
}
getchar();
memset(vis, 0, sizeof(vis));
dfs(1);
}
// stopfile;
return 0;
}
3、含重复元素的全排列(首先要强制排序,然后再回溯的过程中记录上一个值的位置,保证相同的元素不会进行互换)
#include<bits/stdc++.h>
using namespace std;
#define runfile freopen("E:/Code/CB/Root/data.txt", "r", stdin)
#define stopfile fclose(stdin)
const int maxn = 100;
int n,vis[maxn],pre;//标记数组,全排列
char s[maxn],perm[maxn];
void dfs(int step)//全排列,step 为当前选择元素的数量
{
if(step == n+1)//已经选满 n 个数,得到全排列,深搜结束
{
for(int i = 1; i <= n; i++)
{
cout<<perm[i]<<"*";
}
cout<<endl;
}
else
{
//从1~n个选中一个未被选中的元素,然后继续深搜。深搜结束之后回溯
int pre = -1;//记录前一个选中的根节点
for(int i = 0; i < n; i++)
{
if(i == 0 || s[i] != s[pre])
{
if(!vis[i])//未被标记
{
vis[i] =1;//标记
perm[step] = s[i];//记录--相当于两个数交换的过程
dfs(step+1);//深搜下一步
vis[i] = 0;//回溯
pre = i;//记录 pre
}
}
}
}
}
int main()
{
// runfile;
ios::sync_with_stdio(false);
while(scanf("%d",&n) != EOF)
{
getchar();
for(int i = 0; i < n; i++)
{
scanf("%c",&s[i]);
}
getchar();
sort(s, s+n);//先强制排序
memset(vis, 0, sizeof(vis));
dfs(1);
}
// stopfile;
return 0;
}