题目的Link在这里:
ACM UVa #110 - Meta-Loopless Sort
这道题的关键在于生成全排列的同时也需要确定如何进行比较可以得到此种全排列。生成全排列的方法有很多,但是有一种方法最适合此题:
假设我们获得了1~n的全排列,如何获得1~n+1的全排列?对于每个1~n的全排列x(1), x(2), ... x(n),可以看作该排列中有n+1个空位,即,<slot>, x(1), <slot>, x(2), <slot>, ...., x(n), <slot>,于是把x(n+1)分别放入这n+1个空位可以得到从x(1), ... x(n)生成的所有1~n+1的全排列。同时,放入某个空位的同时也就决定了x(n+1)和每个元素的大小关系:
因为有x(1), x(2), ..., x(n),因此有x(1) <= x(2) <= x(3) .... <= x(n),则
x(n)< x(n+1), 则插入生成的排列为x(1), x(2), ..., x(n), x(n+1)
否则,如果x(n-1)< x(n+1), 则插入生成的排列为x(1), x(2), ..., x(n-1), x(n+1), x(n)
....
否则,(此时x(n+1) < x(1)),因此排列为x(n+1), x(1), ..., x(n)
通过这个关系就很容易生成整个if语句了。
此外,整个if语句比较像一颗二叉树,每个分支对应着Then/Else子句,所以采用类似深度优先的方式遍历生成此if语句是最自然的方法:
代码如下:
//
//
ACMUVaProblem#110
//
http://acm.uva.es/p/v1/110.html
//
//
Author:ATField
//
Email:[email protected]
//
#include
<
iostream
>
#include
<
vector
>
#include
<
cstdlib
>
using
namespace
std;
void
indent(
int
n)
...
{
//outputindent
for(intj=0;j<n;++j)
cout<<"";
}
void
make_prog(
int
n,
int
end,
const
vector
<
int
>
&
seq)
...
{
if(n==end)
...{
//wealreadycometotheend
//justoutputthevector
indent(n);
cout<<"writeln(";
for(inti=0;i<n;++i)
...{
if(i>0)
cout<<",";
cout<<char('a'+seq[i]);
}
cout<<")"<<endl;
}
else
...{
//bigifstatement
for(inti=n;i>=0;--i)
...{
indent(n);
if(i<n)
cout<<"else";
if(i>0)
cout<<"if"<<char('a'+seq[i-1])<<"<"<<char('a'+n)<<"then";
cout<<endl;
vector<int>new_seq=seq;
new_seq.insert(new_seq.begin()+i,n);
make_prog(n+1,end,new_seq);
}
}
}
void
output_program(
int
n)
...
{
vector<int>seq;
seq.push_back(0);//'a'istheinitialsequence
//
//Outputthebeginpartoftheprogram
//
cout<<"programsort(input,output);"<<endl
<<"var"<<endl;
//var
for(inti=0;i<n;++i)
...{
if(i>0)
cout<<",";
cout<<char('a'+i);
}
cout<<":integer;"<<endl;
cout<<"begin"<<endl;
//readln
cout<<"readln(";
for(inti=0;i<n;++i)
...{
if(i>0)
cout<<",";
cout<<char('a'+i);
}
cout<<");"<<endl;
//
//Outputthebigifstatement
//
make_prog(1,n,seq);//outputthewholeprogramfrom1ton
cout<<"end."<<endl;
}
int
main(
int
argc,
char
*
argv[])
...
{
intm;
cin>>m;//totalmprogramstomake
for(inti=0;i<m;++i)
...{
intn;
cin>>n;
output_program(n);
}
return0;
}