Nguồn đề bài: http://vn.spoj.com/problems/QBHV/
1. Đề bài QBHV spoj
Cho một xâu S chỉ gồm các chữ cái in hoa, 1 <= độ dài <= 9.
Yêu cầu:
1: Có bao nhiêu cách hoán vị các chữ cái của xâu S
2: Liệt kê các hoán vị đó theo thứ tự từ điển
Input
Gồm 1 dòng duy nhất chứa xâu S
Output
Dòng 1: Ghi số lượng hoán vị tìm được (K)
K dòng tiếp theo, mỗi dòng ghi một xâu hoán vị của xâu S theo đúng thứ tự từ điển
Example
Input: ABAB Output: 6 AABB ABAB ABBA BAAB BABA BBAA
2. Hướng dẫn QBHV spoj
– đầu tiên bạn sắp xếp xâu theo thứ tự chữ cái ABC…
– tính trước số hoán vị không lặp. phần này bạn có thể tham khảo bên toán
– sử dụng quay lui, vừa quay vừa xuất :)) trong quá trình quay lui bạn có thể đặt nhánh cận. so sánh với kết quả đã write trước đó. bạn có thể tham khảo code. ở dòng:
if ch>kq[spt] then try(i+1);
code tham khảo chưa thật sự tối ưu phần lưu trữ cũng như tính k, vì vậy bạn có thể cải tiến tốt hơn
Đã bổ sung code chuẩn bằng PP sinh (26/3/2015)
3. code tham khảo QBHV spoj pascal
a. Code tham khảo 1
program bt;
const fi='';
fo='';
var
s:string[10];
f:text;
DD:array[1..9] of boolean;
kq:array[0..362880] of string[9];
spt:LONGINT;
ch:string[9];
GT:array[0..9] of longint=(1,1,2,6,24,120,720,5040,40320,362880);
procedure docfile;
begin
assign(f,fi); reset(f);
readln(f,s);
close(f);
end;
procedure init;
begin
fillchar(dd,sizeof(dd),false);
spt:=0;
ch:='';
kq[0]:=chr(ord('a')-1);
end;
procedure sapxep;
var min,i,j:byte;
tam:char;
begin
for i:=1 to length(s)-1 do
begin
min:=i;
for j:=min+1 to length(s) do
if s[min]>s[j] then
min:=j;
tam:=s[min];
s[min]:=s[i];
s[i]:=tam;
end;
end;
procedure try(i:byte); // lan chon thu i
var j:byte;
begin
if i-1=length(s) then
begin
begin
inc(spt);
kq[spt]:=ch;
writeln(f,ch);
end;
end
else
for j:=1 to length(s) do
if not dd[j] then
begin
dd[j]:=true;
ch:=ch+s[j];
if ch>kq[spt] then
try(i+1);
delete(ch,length(ch),1);
dd[j]:=false;
end;
end;
procedure hvlap;
var i,vt:byte;
sum:longint;
phanmau:longint;
begin
vt:=1; phanmau:=1;
while vt<=length(s) do
begin
i:=1;
while (s[vt]=s[vt+1]) and (vt<=length(s)) do
begin
inc(i);
inc(vt);
end;
phanmau:=phanmau*gt[i];
inc(vt);
end;
sum:=gt[length(s)] div phanmau;
writeln(f,sum);
end;
begin
docfile;
assign(f,fo); rewrite(f);
sapxep;
hvlap;
try(1);
close(f);
end.b. Code tham khảo 2
Code bổ sung (26/4/15):
const
maxn = 9;
gt : array[0..maxn] of longint =
(1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880);
var
n : longint;
s : string;
fi : text;
tmp : char;
procedure resort;
var i, j : longint;
tmp : char;
begin
for i:= 1 to n-1 do
for j:= i+1 to n do
if s[i] > s[j] then
begin
tmp:= s[i]; s[i]:= s[j]; s[j]:= tmp
end
end;
procedure count;
var i, c, t : longint;
begin
i:= 1; t:= 1;
while i <= n do
begin
c:= 1;
while ((s[i]=s[i+1]) and (i <= n)) do
begin
inc(i); inc(c)
end;
t:= t * gt[c];
inc(i)
end;
writeln(fi, gt[n] div t)
end;
procedure swap(var a, b : char); inline;
var
tmp : char;
begin
tmp:= a; a:= b; b:= tmp
end;
procedure generate;
var i, j, k, a, b : longint;
begin
repeat
writeln(fi, s);
i:= n-1;
while (i>0) and (s[i] >= s[i+1]) do
dec(i);
if i>0 then
begin
k:= n;
while (k>0) and (s[k] <= s[i]) do
dec(k);
if k=0 then
exit;
swap(s[i], s[k]);
a:= i+1; b:= n;
while a<b do
begin
swap(s[a], s[b]); inc(a); dec(b)
end
end;
until i=0;
end;
begin
readln(s);
n:= length(s);
resort;
assign(fi, ''); rewrite(fi);
count;
generate;
close(fi);
readln
end.