标签:style blog http color os io for ar
[问题描述]
列出所有从数字1到数字n的连续自然数的排列,要求所产生的任一数字序列中不允许出现重复的数字。
输入:n(1<=n<=9)
输出:由1~n组成的所有不重复的数字序列,每行一个序列。
[样例输入]
3
[样例输出]
1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1
[问题分析]
这题要求输出n个数的全排列(从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列)。
显然也没有什么好的办法,于是就用回溯+剪枝来处理了。
这里有一个数学公式的,就是全排列数f(n)=n!(定义0!=1)
下面是我写的程序:
var n:integer; a:array[1..10]of integer;//第a[i]个数字的可能情况 f:array[1..10]of boolean;//判断是否重复 procedure find(k:integer); var i:integer; begin if k>n then begin for i:=1 to n do write(a[i],‘ ‘); writeln; end else for i:=1 to n do begin if f[i] then begin a[k]:=i;f[i]:=false; find(k+1); f[i]:=true;//回溯重置条件 end; end; end; procedure init; begin assign(input,‘word.in‘);reset(input); assign(output,‘word.out‘);rewrite(output); readln(n); fillchar(f,sizeof(f),true); end; begin init; find(1); close(input);close(output); end.
下面是标准程序:
var a:array [1..100] of integer; n:integer; procedure print; var i:integer; begin for i:=1 to n do write(a[i]:5); writeln end; function try(k,i:integer):boolean; var m:integer; begin m:=1; while (m<k)and(i<>a[m]) do m:=m+1; if m=k then try:=true else try:=false end; procedure find(k:integer); var i:integer; begin if k>n then print else for i:=1 to n do if try(k,i) then begin a[k]:=i; find(k+1) end end; begin assign(input,‘word.in‘); reset(input); assign(output,‘word.out‘); rewrite(output); readln(n); find(1) end.
真心感觉标准程序不如我写的好,开一个数组判断是否用过,比遍历一遍数组快得多。
全排列问题也有其他的方法,有兴趣的朋友可以去百度百科http://baike.baidu.com/view/1710135.htm看看,也有很多其他的好方法。
另外要说一点,要经常性的阅读一下标程,你会发现有很多小技巧和细节。
当然,有时候标程并不总是最好的,比如上面的例子,注意筛选。
标签:style blog http color os io for ar
原文地址:http://www.cnblogs.com/cuichen/p/3908053.html