枚举全排列

没什么难度,简单的dfs,主要要敢下手,搜索打多了自然通,领悟也就更快

主要思路就是一位一位的试验,某个数用过就试验下一位,没用过就填,然后搜完它打头(或当某一位)之后,跳出内层过程进行回溯,之所以能从小到大生成,是因为dfs里的for循环从小到大,回溯回来也会继续先从小的开始枚举,我开始极其爱犯的错误就是递归类的procedure的传参,一定要分清局部变量和整体变量

program sky;
var
  i,j,n:longint;
  a:array[0..20]of longint;{用于记录最终输出的排列,没有保存原来的值,输出一次,再用到就直接覆盖了}
  v:array[0..20]of boolean;{dfs判断是否用过这个数字,数组大小为20是指是1到20的全排列,可以修改}

procedure open;
  begin
    assign(input,'qpl.in'); reset(input);
    assign(output,'qpl.out'); rewrite(output);
  end;
procedure closed;
  begin
    close(input);close(output);
  end;

procedure print;{打印结果}
  var
    i:longint;
  begin
    for i:=1 to n do write(a[i]);
    writeln;
  end;
procedure doing(x:longint);{传参为现在枚举到了第几位,即第x位之前的已经暂时确定下来}
  var
    i:longint;
  begin
    if x=n+1 then print;{边界,成立即可输出}
    for i:=1 to n do{n是1到20内的,即从1到n的全排列,循环结构是字典序的原因}
      if not v[i] then
        begin
          a[x]:=i;{深搜经典框架,对每个可行的i进行枚举}
          v[i]:=true;{标记}
          doing(x+1);
          v[i]:=false;{释放,以便回溯回来再用,a[x]=0或许不用,可以直接冲掉,赋上没坏处,避免传参过程中出现没考虑到的情况}
          a[x]:=0;
        end;
  end;


begin
  open;
  read(n);
  doing(1);
  closed;
end.

原文地址:https://www.cnblogs.com/skysun/p/qpl.html