没什么难度,简单的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.