洛谷P1706及algorithm库的第一步探索
先放题目,不多BB
题目描述
输出自然数 1 到 n 所有不重复的排列,即 n 的全排列,要求所产生的任一数字序列中不允许出现重复的数字。
输入格式
一个整数 n。
输出格式
由 1~n 组成的所有不重复的数字序列,每行一个序列。
每个数字保留 5 个场宽。
输入输出样例
输入#1:
3
输出#1:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
Hint
1<=n<=9
憨憨代码:
//Create by EaKal7
#include <stdio.h> //这种方法在n=9||8是直接超过了2E
#include <algorithm>
#include <string.h>
#include <time.h>
#include <bits/stdc++.h>
using namespace std;
int a[50] = {0};
int n, num, p;
int r;
int flag[10];
int start;
int end_n;
int pailie(int n)
{
for (int i = 1; i <= n; i++)
{
if (flag[i] == 0)
{
return 0;
}
}
return 1;
}
void Pritn(int e)
{
int temp[10];
int k = 0;
while (e)
{
temp[k++] = e % 10;
e /= 10;
}
for (int i = k - 1; i >= 0; i--)
{
printf("%5d", temp[i]);
}
printf("\n");
}
int main()
{
scanf("%d", &n);
r = n - 1;
start = 1;
end_n = 9;
while (r--)
{
start = start * 10 + 1;
end_n = end_n * 10 + 9;
}
for (int i = start; i < end_n; i++)
{
for (int j = 1; j <= n; j++)
{
flag[j] = 0;
}
r = i;
flag[r % 10] = 1;
while (r /= 10)
{
flag[r % 10] = 1;
}
if (pailie(n) == 1)
{
Pritn(i);
}
}
return 0;
}
运行正常但是运算量太大,直接爆了,而且思想过于复杂,考虑到dfs想到应该可以dfs
DFS版本:
#include<bits/stdc++.h>
using namespace std;
int n,pd[100],used[100];
void printt()
{
int i;
for(i=1;i<=n;i++)
printf("%5d",used[i]);
cout<<endl;
}
void dfs(int k)//深搜函数,当前是第k格
{
int i;
if(k==n) //填满
{
printt();
return;
}
for(i=1;i<=n;i++)
{
if(!pd[i])
{
pd[i]=1;//标记一下
used[k+1]=i;//把这个数填入数组
dfs(k+1);//填下一个
pd[i]=0;//回溯
}
}
}
int main()
{
cin>>n;
dfs(0);//注意,这里是从第**0**格开始的!
return 0;
}
这里就考虑dfs会不会大题小作,或者过于麻烦,所以蒟蒻查阅blog,发现了一个有序全排序的神器,algorithm库里的next_permutation,可产生1~n的全排列有如下代码:
#include <stdio.h>
#include <algorithm>
using namespace std;
int main(){
int n;
while(scanf("%d",&n)&&n){
int a[1000];
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
sort(a,a+n);//可以自行测试一下删除后的结果
do{
for(int i=0;i<n;i++)
printf("%d ",a[i]);
printf("\n");
}while(next_permutation(a,a+n));
}
return 0;
}
next_permutation这个函数直接对1~n的全排列,并且是从数组中当前的字典序开始依次增大直至到最大字典序。注:这个函数是直接改变数组地址里的数值的。
所以直接贴上改动后的代码:
next_permutation版本:
//Create by EaKal7
//next_permutation的debug nice!!!!
#include <stdio.h>
#include <algorithm>
using namespace std;
int main()
{
int n, p, temp[9];
while (scanf("%d", &n) != EOF)
{
for (int i = 0; i < n; i++)
{
temp[i] = i + 1;
printf("%5d", temp[i]);
}
printf("\n");
while (next_permutation(temp, temp + n))
{
for (int i = 0; i < n; i++)
{
printf("%5d", temp[i]);
}
printf("\n");
}
}
return 0;
}
总结:这个函数直接将全排序有序输出,将一些代码浓缩,有一点sort和排序的味道了。
PS:algorithm这个库里还有好多挺好用的函数建议一一探讨
PPS:第一篇博客 by EaKal7 2020.12.3
参考博客:
关于全排列 next_permutation() 函数的用法