洛谷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() 函数的用法

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页