You are on page 1of 282

T SCH TRI THC DUY TN

NGUY N XU N HUY




SNG TO
TRONG THUT TON
V
LP TR NH

v i ng n ng Pa s c a l v C#
T p 1


T u y n c c b i t o n T i n n n g c a o
c h o h c s i n h v s i n h v i n g i i

Sng to trong Thut ton v Lp trnh Tp I

2



MC L C

Li ni u i
Chng I GII MT BI TON TIN 1
Bi 1.1. S thn thin 2
Bi 1.2. S cp cng 8
Bi 1.3. S cp nhn 11
Bi 1.4. Mng ngu nhin 13
Bi 1.5. Chia mng t l 1:1 16
Bi 1.6. Chia mng t l 1:k 21
Chng II SINH D LIU VO V RA 27
Bi 2.1. Sinh ngu nhin theo khong 27
Bi 2.2. Sinh ngu nhin tng 29
Bi 2.3. Sinh hon v ngu nhin 31
Bi 2.4. Sinh ngu nhin u 33
Bi 2.5. Sinh ngu nhin t l 36
Bi 2.6. Sinh ngu nhin tp tng 40
Bi 2.7. Sinh ngu nhin tp cp s cng 42
Bi 2.8. Sinh ngu nhin mng i xng 43
Bi 2.9. S cao h 46
Bi 2.10. Tp cc hon v 49
Bi 2.11. c d liu t tp vo mng bit hai kch thc 53
Bi 2.12. c d liu t tp vo mng bit mt kch thc 56
Bi 2.13. c d liu t tp vo mng i xng 60
Bi 2.14. m tu 62
Bi 2.15. Sp on 65
Chng III BN PHM V MN HNH 79
Bi 3.1. Bng m ASCII 79
Bi 3.2. B T l kh 80
Bi 3.3. Hm GetKey 88
Bi 3.4. Tr chi 15 90
Bi 3.5. Bng nhy 95
Chng IV T CHC D LIU 107
Bi 4.1. Cm 107
Bi 4.2. Bi gp 112
Bi 4.3. Chui ht 120
Sng to trong Thut ton v Lp trnh Tp I

3



Bi 4.4. Sp mng ri ghi tp 129
Bi 4.5. abc - sp theo ch dn 133
Bi 4.6. Xu mu 141
Chng V PHNG PHP THAM LAM 153
Bi 5.1. Bng nhc 153
Bi 5.2. Xp vic 158
Bi 5.3. Xp ba l 165
Bi 5.4. Cy bao trm ngn nht 170
Bi 5.5. Trn hai tp 177
Chng VI PHNG PHP QUAY LUI 193
Bi 6.1. Tm Hu 195
Bi 6.2. T chun 207
Bi 6.3. Tm ng trong m cung 216
Chng VII QUY HOCH NG 227
Bi 7.1. Chia thng 228
Bi 7. 2. Palindrome 235
Bi 7.3. Cm hoa 243
Bi 7.4. Tm cc ng ngn nht 253
Chng VIII SUY NGM 267
Bi 8.1. Lt nn 267
Bi 8.2. Ch s cui khc 0 276
Bi 8.3. Hnh ch nht ti i trong ma trn 0/1 281
Bi 8.4. Ma phng 291
Bi 8.5. Thp H Ni c 308
Bi 8.6. Thp H Ni xui 311
Bi 8.7. Thp H Ni ngc 316
Bi 8.8. Thp H Ni thng 321
Bi 8.9. Thp H Ni sc mu (H Ni Cu vng) 325


Sng to trong Thut ton v Lp trnh Tp I

4



Li ni u

Th theo yu cu ca ng o bn c, chng ti bin son li cun Sng
to trong Thut ton v Lp trnh vi cc bi Ton Tin nng cao cho hc sinh
v sinh vin nhm cung cp nhng k thut lp trnh c bn gii nhng bi
ton kh trn my tnh.
Mt bi ton tin c hiu l kh nu ta s dng thut gii mi ny sinh
trong u khi va bit ni dung bi ton th hoc l ta thu c kt qu sai
hoc l li gii thu c s khng hu hiu theo ngha chng trnh i hi
qu nhiu b nh hoc/v chy qu lu. Nhng thut gii ny sinh lp tc
trong u nh vy thng c gi l thut gii t nhin. D nhin, khi nim
ny ch l tng i. Nu bn nm vng nhiu dng thut gii v tng
th sc vi nhiu bi ton kh th n mt lc no cc thut gii t nhin
ca bn s ng tin cy. cng chnh l mc ch ca s hc tp v rn luyn
v cng l c m ca ngi vit tp sch ny.
c sch khng i hi bn phi c tri thc g c bit. tip thu tt
v ng gp cho vic hiu chnh v ci tin ni dung cun sch ch cn bn bit
s dng mt trong cc ngn ng lp trnh: Pascal trong mi trng Turbo hoc
Free Pascal hoc C#.
Cc k thut lp trnh c minh ho qua nhng bi ton c th tng
ng vi trnh nng cao ca hc sinh v sinh vin. Hnh thc pht biu bi
ton suy cho cng l khng quan trng. Cc k thut lp trnh v phng php
xy dng thut gii cho nhng bi ton thng c dng rng ri trong qu
trnh thit k v ci t cc phn mm ng dng trong thc tin, cho nn vic
sm lm ch cc tri thc ny mi tht s l cn thit. Chnh v vy m chng
ti cho rng ni dung cun sch c th ph hp vi cc bn hc sinh, sinh vin
cc trng i hc v nhng bn c mun t hon thin tri thc trong lnh
vc gii thut v lp trnh. Thit ngh cun sch cng c th c dng lm ti
liu tham kho dy cc lp chuyn tin ca cc trng ph thng. Ni dung
sch gm hai phn. Phn th nht gii thiu vn tt v bn cht cc phng
php v k thut lp trnh v cc ton cc bn th sc. Phn th hai trnh
by v phn tch chi tit li gii cng vi nhng bnh lun v xut x ca cc
bi ton.
Trong tp sch ny cng cung cp ton vn cc chng trnh vit bng
ngn ng lp trnh Pascal v C# bn c tin so snh vi li gii ca mnh.
C hai phn u cp n ni dung ca tm chng nh sau.
Chng th nht trnh by s chung gii mt bi ton tin. Cc bi
tp chng ny hu ht thuc loi d gii. Chng th hai gii thiu cc k
thut sinh d liu mt cch t ng nhm phc v cho vic kim th (test)
chng trnh. Chng th ba trnh by cc k thut qun l bn phm v mn
hnh. Chng th t cp n cch thc t chc d liu cho mt bi ton tin.
Ba chng tip theo gii thiu ba trong s cc phng php kh ph bin
thng c vn dng trong thit k thut gii. l phng php tham lam,
phng php quay lui v quy hoch ng. Cc phng php ny u l khng
vn nng theo ngha khng th dng chng gii mi bi ton tin. Trong thc
Sng to trong Thut ton v Lp trnh Tp I

5



t, mt phng php vn nng nh vy l khng hu hiu. Tu theo ni dung
bi ton m ta chn phng php ph hp. cng l im kh, i hi bn
c mt qu trnh tm ti v tch lu kinh nghim.
Ring chng cui cng ca cun sch, chng th tm gii thiu mt s
bi ton tin bn c t pht hin phng php gii.
Nhng ni dung trong tp sch ny c tp hp v chnh l t cc bi
ging v thut ton v lp trnh, t cc cun sch Tm ng trong m cung,
Bn tu trn bin v t cc bi vit ca tc gi ng trong tp ch Tin hc v
nh trng v mt s li gii hay ca cc bn hc sinh.
Ln xut bn ny chng ti trnh by thm cc bi gii vit trong mi
trng ngn ng C# cc bn sinh vin cng tham kho. Hi vng rng trong
cc dp khc chng ti s cung cp thm cc phng n gii vi bn c. Tuy
nhin, suy cho cng, mi trng lp trnh ch mang tnh minh ho. Khi bit
thut ton, vic th hin thut ton trong mi trng lp trnh c th chc
chn l vic lm quen thuc ca bn c.
Xin c chn thnh cm n cc em hc sinh, sinh vin, cc thy c gio,
bn b v ng nghip chia s kinh nghim v tr gip ti liu, nhn xt v
bnh lun hnh thnh ni dung c bn ca cun sch.
Chng ti hi vng s tip tc nhn c nhng kin ph bnh ca bn c
v ni dung, cht lng v hnh thc trnh by c th nh hng cho cc
tp tip theo.
H Ni, L Hi p Thanh - 2008
N.X.H



Sng to trong Thut ton v Lp trnh Tp I

6



CHNG 1
GII MT BI TON TIN








Phn ny s gii thiu mt s bc thng vn dng trong qu trnh gii cc bi
ton tin.
1. Bc u tin v l bc quan trng nht l hiu r ni dung bi ton.
y l yu cu quen thuc i vi nhng ngi lm ton. hiu bi ton theo
cch tip cn ca tin hc ta phi gng xy dng mt s th d phn nh ng cc
yu cu ra ca u bi ri th gii cc th d hnh thnh dn nhng hng
i ca thut ton.
2. Bc th hai l dng mt ngn ng quen thuc, tt nht l ngn ng ton hc c
t cc i tng cn x l mc tru tng, lp cc tng quan, xy dng cc
h thc th hin cc quan h gia cc i lng cn x l.
3. Bc th ba l xc nh cu trc d liu biu din cc i tng cn x l cho
ph hp vi cc thao tc ca thut ton.
Trong nhng bc tip theo ta tip tc lm mn dn cc c t theo trnh t t trn
xung, t tru tng n c th, t i th n chi tit.
4. Bc cui cng l s dng ngn ng lp trnh chn vit chng trnh hon
chnh. bc ny ta tin hnh theo k thut i t di ln, t nhng thao tc nh
n cc thao tc t hp.
Sau khi nhn c chng trnh ta cho chng trnh chy th vi cc d liu ly t
cc th d xy dng bc u tin.
iu quan trng l xy dng cc th tc mt cch khoa hc v c ch ch nhm
kim tra tnh tin cy ca chng trnh thu c v thc hin mt s ci tin.
Chng ta s vn dng cch tip cn trn gii mt s bi ton c th.
Nhng phn trnh by di y c th s dng mt vi k php quen thuc ca tin hc,
th d:
x = abc s t nhin x c to bi ba ch s a, b v c.
a, b = 0..9 hai s a v b c th nhn cc gi tr t 0 n 9.
Sng to trong Thut ton v Lp trnh Tp I

7



S d ta khng s dng cc k hiu ton hc v trn bn phm my tnh khng c
cc k hiu . Chn cc k hiu c sn trong cc ngn ng lp trnh gip chng ta c
th vit cc ch thch ngay trong chng trnh.
Bi 1.1. S thn thin
Tm tt c cc s t nhin hai ch s m khi o trt t ca hai ch s s thu
c mt s nguyn t cng nhau vi s cho.
Hiu u bi
Ta k hiu (a, b) l c chung ln nht (ucln) ca hai s t nhin a v b. Hai s t
nhin a v b c gi l nguyn t cng nhau khi v ch khi (a, b) = 1. Khi ,
chng hn:
a. (23, 32) = 1, vy 23 l mt s cn tm. Theo tnh cht i xng, ta c ngay 32
cng l mt s cn tm.
b. (12, 21) = 3, vy 12 v ng thi 21 khng phi l nhng s cn tm.
c t: Gi hai ch s ca s t nhin cn tm x l a v b, ta c:
(1) x = ab.
(2) a, b = 0..9 (a v b bin thin trong khong 0..9).
(3) a > 0 v x l s c hai ch s.
(4) (ab, ba) = 1.
Ta k hiu x' l s i xng ca s x theo ngha ca u bi, khi ta c c t nh
sau:
(5) x = 10..99 (x bin thin t 10 n 99, v x l s c hai ch s).
(6) (x, x') = 1.
Nu x = ab th x' = ba. Ta c th tnh gi tr ca x' theo cng thc:
x' = (ch s hng n v ca x) * 10 + (ch s hng chc ca x).
K hiu n(x) l ton t ly ch s hng n v ca s t nhin x v k hiu
Chc(x) l ton t ly ch s hng chc ca x, ta c:
x' = n(x)*10 + Chc(x).
Tng hp li ta c c t:
S cn tm x phi tho cc tnh cht sau:x = 10..99 (x nm trong khong t 10 n
99).
(7) x' = n(x)*10 + Chc(x).
(8) (x, x') = 1 (c chung ln nht ca x v x' bng 1).
c t trn c th hin qua ngn ng phng trnh ta Pascal nh sau:
(9) for x:=10 to 99 do
if ucln(x, n(x)*10+Chc(x))=1 then Ly(x);
trong , ucln(a,b)l hm cho c chung ln nht ca hai s t nhin a v b;
Ly(x) l ton t hin th x ln mn hnh hoc ghi x vo mt mng no vi mc
ch s dng li, nu cn.
Ta lm mn c t (10):
ucln(a, b): Thut ton Euclid l chia lin tip, thay s th nht bng d ca n
khi chia cho s th hai ri hon v hai s.
(*-----------------------------------
Tim uoc chung lon nhat cua hai so
a va b. Thuat toan Euclid
--------------------------------------*)
function Ucln(a,b: integer): integer;
Sng to trong Thut ton v Lp trnh Tp I

8



var r: integer;
begin
while b > 0 do
begin
r:= a mod b; a:= b; b:= r;
end;
Ucln:= a;
end;
n(x) = (x mod 10): s d ca php chia nguyn x cho 10, th d:
n(19) = 19 mod 10 = 9.
Chc(x) = (x div 10): thng nguyn ca php chia x cho 10, th d:
Chc(19) = 19 div 10 = 1.
Ly(x): write(x) hoc np gi tr x vo mng s theo cc thao tc sau:
n := n + 1;
s[n] := x;
n m s phn t hin np trong mng s.
Biu din d liu
Ta dng mng s lu cc s tm c. D thy s phi l mt mng nguyn cha
ti a 90 phn t v cc s cn kho st nm trong khong t 10 n 99.
var s: array[1..90] of integer;
Phng n 1 ca chng trnh s hot ng theo hai bc nh sau:
1. n := Tim;
2. Xem(n);
Bc 1. Tm v ghi vo mng s cc s tho iu kin u bi, n l s lng cc s
tm c.
Bc 2. Hin th cc phn t ca mng s[1..n] cha cc s tm c.
Ton t x' c vit di dng hm cho ta s to bi cc ch s ca x theo trt t
ngc li. Ta t tn cho hm ny l SoDao (s o). Hm c th nhn gi tr vo l
mt s t nhin c nhiu ch s.
to s o y ca s x cho trc, hm SoDao ly dn cc ch s hng n v ca
x ghp vo bn phi s y:
y := y*10 + (x mod 10)
Sau mi bc, ch s hng n v ly c loi hn khi x bng ton t:
x := x div 10
Ch th {$B-} trong chng trnh NTCN (nguyn t cng nhau) di y t ch
kim tra biu thc lgic va . Khi xc nh c gi tr chn l cn thit th
khng tin hnh tnh tip gi tr ca biu thc na. Th d, vi cc lnh
x := 1; y := 5;
if (x > 5) and (x + y < 7)then y := y + 1
else y := y-1;
trong ch {$B-}, sau khi tnh c gi tr chn l (x > 5) = false, chng
trnh s b qua nhn t logic (x + y < 7), v tch lgic ca false vi gi tr tu
cho ta false. Trong trng hp ny lnh y := y - 1 s c thc hin. Ngc li,
nu ta t ch th {$B+} th chng trnh, sau khi tnh c (x > 5) = false vn
tip tc tnh gi tr ca (x + y < 7) ri ly tch ca hai gi tr tm c (false
and true = false) lm gi tr ca biu thc iu kin trong cu trc r nhnh ni
Sng to trong Thut ton v Lp trnh Tp I

9



trn. Cui cng ton t y := y - 1 cng c thc hin ging nh trng hp trn
nhng khi lng tnh ton li nhiu hn.
(* Pascal *)
(*----------------------------------
So than thien (xy,yx) = 1
----------------------------------*)
program SoThanThien;
{$B-}
uses Crt;
const MN = 90;
var s: array[1..MN] of integer;
function Ucln(a,b: integer): integer; t vit
function SoDao(x: integer): integer;
var y: integer;
begin
y := 0;
repeat
{ ghep chu so hang don cua x vao ben phai y }
y := 10*y + (x mod 10);
x := x div 10; { loai chu so hang don }
until (x = 0);
SoDao := y;
end;
(*--------------------------------------
Tim cac so thoa dieu kien dau bai
ghi vao mang s.
Output: so luong cac so tim duoc
----------------------------------------*)
function Tim: integer;
var x,d: integer;
begin
d := 0; {So luong cac so can tim }
for x := 10 to 99 do
if Ucln(x,SoDao(x)) = 1 then
begin
d := d + 1; s[d]:= x;
end;
Tim := d;
end;
(*------------------------------------
Hien thi mang s[1..n] tren man hinh.
--------------------------------------*)
procedure Xem(n: integer);
var i: integer;
begin
writeln;
for i := 1 to n do write(s[i]:4);
writeln;
end;
BEGIN
n := Tim; Xem(n); writeln;
Sng to trong Thut ton v Lp trnh Tp I

10



write(' Tong cong ',n,' so'); readln;
END.
// C#
using System;
namespace SangTao1
{
/***********************************
So Than Thien: (xy, yx) = 1
**********************************/
class SoThanThien
{
static int mn = 90;
static int [] s = new int[mn];
static void Main(string[] args)
{ Run();
Console.ReadLine();
}
static void Run()
{ int n = Find();
for (int i=0;i<n;++i)
Console.Write(s[i] + " ");
Console.WriteLine("\n Tong cong: "+n+" so");
}
static int Find()
{ int d = 0;
for (int x = 10; x < 100; ++x)
if (Ucln(x,SoDao(x))==1) s[d++] = x;
return d;
}
static int Ucln(int a, int {}b)
{ int r;
while (b != 0){ r = a%b;a = b;b = r; }
return a;
}
static int SoDao(int x)
{ int y = 0;
do { y = y*10+(x%10); x /= 10; } while (x!=0);
return y;
}
} // SoThanThien
} // SangTao1
Ci tin
Ta vn dng tnh i xng nhn xt phn trn ci tin chng trnh. Nh
vy ch cn kho st cc s x = ab, vi a > b > 0. Trng hp a = b ta khng
xt v khi x' = x v do Ucln(x, x) = x > 10 = 1.
Nu b = 0 ta c x = 10a v x' = a. Ta thy Ucln(10a, a) = a = 1 khi v ch
khi a = 1. Do ta xt ring trng hp ny. Khi ab = 10 ta c (10, 1) = 1.
Vy 10 chnh l mt s cn tm v l s u tin.
Sng to trong Thut ton v Lp trnh Tp I

11



Mi khi tm c hai ch s a v b tho iu kin a > b v Ucln(a*10 + b, b*10 +
a) = 1 ta a a*10 + b vo kt qu, nu b > 0 ta a thm s o b*10 + a vo kt qu.
(* Pascal *)
(*-------------------------------------
So Than thien: Phuong an 2
---------------------------------------*)
function Tim2: integer;
var a,b,d: integer;
begin
d:= 1; {So luong cac so can tim}
s[d] := 10;
for a := 1 to 9 do
for b := 1 to a-1 do
if Ucln(a*10+b,b*10+a)=1 then
begin
d := d + 1; s[d] := a*10 + b;
d := d + 1; s[d] := b*10 + a;
end;
Tim2 := d;
end;
// C#
// Phuong an 2
static int Find2()
{ int a,b, d = 0;
s[d++] = 10;
for (a = 1; a <= 9; ++a)
for (b = 1; b < a; ++b)
if (Ucln(10*a + b, 10*b + a) == 1)
{ s[d++]=10*a+b; s[d++]=10*b+a; }
return d;
}
Bi 1.2. S cp cng
Tm cc s t nhin l c ba ch s. Ba ch s ny, theo trt t t tri qua phi
to thnh mt cp s cng.
c t
1. x l s t nhin c ba ch s: x = 100*a + 10*b + c.
2. x l s l nn ch s hng n v c phi l s l: c = 1, 3, 5, 7, 9.
3. Ch s hng trm ca x phi khc 0: a = 1..9.
4. Nu dy a, b, c lp thnh mt cp s cng th s ng gia b l trung bnh
cng ca hai s u v cui: b = (a + c)/2 hay 2b = a+c.
T (4) ta suy ra (a + c) l s chn. Do c l, (a + c) chn nn a l.
Nu bit a v c ta tnh c x = 100a +10(a + c) / 2 + c
= 100a + 5(a + c) + c = 105a + 6c.
V ch c 5 ch s l l 1, 3, 5, 7 v 9 nn t hp ca a v c s cho ta 25 s.
T chc d liu
Sng to trong Thut ton v Lp trnh Tp I

12



Ta to sn mng nguyn 5 phn t ChuSoLe[1..5] v gn trc cc gi tr 1, 3,
5, 7, 9 cho mng ny. Trong Turbo Pascal (TP) vic ny c thc hin thng qua khai
bo:
const ChuSoLe: array[1..5] of integer = (1,3,5,7,9);
Ch rng khai bo ny phi t trong mc const l ni khai bo hng.
Trong C# ta khai bo nh sau:
int [] ChuSoLe = {1,3,5,7,9};
ngha ca dng khai bo trn l nh sau: Xin cp pht mt bin mng kiu
nguyn c 5 phn t vi ch dn t 1 n 5, tn bin l ChuSoLe. 5 phn t ca bin
c gn trc cc tr 1, 3, 5, 7 v 9.
Sau , mi khi cn, ta ch vic duyt mng ChuSoLe l thu c ton b cc
ch s l theo trt t khai bo trc.
Ch
Th tc inc(d) trong chng trnh TP di y tng gi tr ca bin d ln thm 1 n
v, tc l tng ng vi cu lnh d := d + 1 v ++d (C#). Tng t, th tc
dec(d) s gim gi tr ca bin d xung 1 n v, tng ng vi cu lnh d := d
1 v --d (C#).
Tng qut hn, ta c th vit:
inc(d,n) tng ng vi d := d + n v
dec(d,n) tng ng vi d := d n.
Khi n = 1 th c th b qua tham s th hai.
(* Pascal *)
(---------------------------------------
Cac so tu nhien le 3 chu so
lap thanh cap so cong
---------------------------------------*)
program CapCong;
uses crt;
const
ChuSoLe: array [1..5] of integer = (1,3,5,7,9);
var s: array [1..25] of integer;
n: integer;
(*-----------------------------------
Phat sinh cac so dang
105a+6c; a,c = 1,3,5,7,9
------------------------------------*)
Function Tim: integer;
var a,c,d,x: integer;
begin
d := 0;
for a := 1 to 5 do
begin
x := 105*ChuSoLe[a];
for c := 1 to 5 do
begin
inc(d); s[d] := x + 6*ChuSoLe[c];
end;
end;
Tim := d;
end;
Sng to trong Thut ton v Lp trnh Tp I

13



(*---------------------------------------
Hien thi mang s[1..n] moi dong 20 so
-----------------------------------------*)
procedure Xem(n: integer); t vit
BEGIN
n := Tim; Xem(n); writeln;
write('Tong cong ',n,' so'); readln;
END.
// C#
using System;
namespace SangTao1
{
class SoCapCong
{
static void Main(string[] args)
{
Show(Find());
Console.WriteLine("\n fini");
Console.ReadLine();
}
static int[] Find()
{
int d = 0;
int [] ChuSoLe = {1,3,5,7,9};
int []s = new int[25];
int x;
for (int i = 0; i < 5; ++i)
{
x = 105 * ChuSoLe[i];
for (int j = 0; j < 5; ++j)
s[d++] = x + 6 * ChuSoLe[j];
}
return s;
}
static void Show(int[] s)
{
foreach (int x in s)
Console.Write(x + " ");
}
} // SoCapCong
} // SangTao1
Ch thch
1. Trong C# mt hm c th cho ra gi tr l mt mng nh hm Find trong chng
trnh trn.
2. Lnh foreach (int x in a) P(x) thc hin thao tc P(x) trn mi phn
t x ca mng, t phn t u tin a[0] n phn t cui cng a[a.Length] vi
a.Length l chiu di (s phn t) ca mng a.
Ch
Sng to trong Thut ton v Lp trnh Tp I

14



1. Da vo nhn xt: dy ba s a, b, c to thnh cp s cng khi v ch khi b l
trung bnh cng ca a v c, tc l 2b = a + c ta c th gii bi ton trn bng phng
php vt cn dng ba vng for nh sau:
for a := 1 to 9 do
for b := 0 to 9 do
for c := 0 to 9 do
if odd(c) and (2*b=a+c) then
Ghi nhn s 100*a+10*b+c;
Hm odd(c) kim tra tnh l ca s nguyn c.
Phng php vt cn i hi khong 10*10*10 = 1000 ln duyt trong khi ch c
25 s, tc l mt phn bn mi cc s tho mn iu kin ca u bi. Phng php
m t trong chng trnh c gi l phng php sinh: n sinh ra ng 25 s cn tm.
2. Ta cn ghi nhn phng php sinh
Phng php sinh

Thay v duyt tm cc i tng
hy sinh ra chng.

Bi 1.3. S cp nhn
Tm cc s t nhin c ba ch s. Ba ch s ny, theo trt t t tri qua phi
to thnh mt cp s nhn vi cng bi l mt s t nhin khc 0.
c t
Ch rng ta ch xt cc cp s trn dy s t nhin vi cng bi d l mt s
nguyn dng. Gi x l s cn tm, ta c:
1. x l s c ba ch s: x = 100*a + 10*b + c.
2. a = 1..9; b = a*d; 0 < c = a*d*d s 9.
H thc 2 cho php ta tnh gii hn trn ca d:

V d l s nguyn nn ta phi c d s trunc(sqrt(9 div a)), trong
sqrt l hm tnh cn bc hai, trunc l hm ly phn nguyn.
Ta cho a bin thin trong khong 1..9 ri cho cng bi d bin thin trong khong t
1 n trunc(sqrt(9 div a)). Vi mi cp s a v d ta tnh
x = 100*a+10*a*d+a*d*d = a*(100+10*d+d*d)
Tuy nhin, ta c th nhm tnh trc cn trn ca d th s phi gi cc hm trunc v
sqrt l nhng hm thao tc trn s thc do s tn thi gian.

a 1 2 3 4 5 6 7 8 9
Cn trn d 3 2 1 1 1 1 1 1 1
(* Pascal *)
(*----------------------------
Cac so tu nhien 3 chu so
lap thanh cap nhan
a d
ad
/ 9
9
2
s
s
Sng to trong Thut ton v Lp trnh Tp I

15



------------------------------*)
program CapNhan;
uses crt;
const MN = 30;
cd: array[1..9] = (3,2,1,1,1,1,1,1,1);
var s: array [1..MN] of integer;
n: integer;
function Tim: integer;
var a,d,n: integer;
begin
n:= 0;
for a:= 1 to 9 do
for d:=1 to cd[a]do
begin
inc(n); s[n]:= a*(100+10*d+d*d);
end;
Tim:= n;
end;
procedure Xem(n: integer): t vit
BEGIN
clrscr; n:= Tim; Xem(n);
writeln; write('Tong cong ',n,' so'); readln;
END.
// C#
using System;
using System.Collections;
namespace SangTao1
{
class SoCapNhan
{
static void Main(string[] args)
{
Show(Find());
Console.WriteLine("\n fini");
Console.ReadLine();
}
static ArrayList Find()
{
ArrayList s = new ArrayList();
int[] cd = {0,3,2,1,1,1,1,1,1,1};
for (int a = 1; a <= 9; ++a)
{
for (int d = 1; d <= cd[a]; ++d)
s.Add(a * (100 + 10 * d + d * d));
}
return s;
}
static void Show(ArrayList s) t vit
} // SoCapNhan
} SangTao1
Ch thch
Sng to trong Thut ton v Lp trnh Tp I

16



- Trong C# mt hm c th cho ra gi tr l mt mng - danh sch kiu
ArrayList nh hm Find trong chng trnh.
- Khi khng bit c bao nhiu phn t c sinh ra trong qu trnh tm kim th
nn dng kiu mng - danh sch cha kt qu.
- Mng cd cha cc cn ca d ng vi mi tr ca a = 1..9, ta thm cho cd phn
t 0 tin truy nhp.

Bi 1.4. Mng ngu nhin
Sinh ngu nhin n s nguyn khng m cho mng nguyn a.
c t
Trong TP hm random(n) sinh mt s ngu nhin kiu nguyn nm trong
khong t 0 n n - 1. Hy tng tng c mt qun sc sc n mt m s cc mt t
0 n n - 1. Khi ta gi hm random(n) th my tnh s gieo qun sc sc v
cho ta gi tr xut hin trn mt nga.
Trong C# phng thc Next(n) ca lp Random hot ng tng t nh
random(n) ca TP.
Ch
1. Trc khi gi hm random ta cn gi th tc randomize my tnh khi
ng c ch pht sinh s ngu nhin.
2. Th tc Gen(m) trong chng trnh di y sinh ngu nhin m s nguyn
trong khong t 0 n m - 1. Ta c th ci tin vit th tc Gen(n,d,c) -
sinh ngu nhin n s nguyn trong khong t d n c (d < c) nh sau.
rng random(cd+1) bin thin trong khong t 0 n cd, do
d+random(cd+1) s bin thin trong khong t d n d+cd = c.
(* Pascal *)
program RandomGen;
(*------------------------------------------
Sinh ngau nhien n so nguyen
khong am cho mang a
------------------------------------------- *)
{$B-}
uses crt;
const MN = 500;
var
a: array [1..MN] of integer;
n: integer;
Procedure Gen(m: integer);
var i: integer;
begin
randomize; n := m;
for i := 1 to n do a[i] := random(m);
end;
procedure Xem: t vit;
BEGIN
Gen(200); Xem;
END.
Sng to trong Thut ton v Lp trnh Tp I

17



// C#
using System;
namespace SangTao1
{
class RandomGen
{
static void Main(string[] args)
{ Show(Gen(200));
Console.WriteLine("\n Fini ");
Console.ReadLine();
}
static int [] Gen(int n)
{ int [] a = new int[n];
Random r = new Random();
for (int i = 0; i < n; ++i)
a[i] = r.Next(n);
return a;
}
static void Show(int [] s): t vit
} // RandomGen
} // SangTao1
Bi 1.5. Chia mng t l 1:1
Tm cch chia dy s nguyn khng m a
1
, a
2
,...,a
n
, n > 1 cho trc thnh hai
on c tng cc phn t trong mi on bng nhau.
c t
Ta quy c vit #E l "tn ti" v #V l "vi mi". K hiu sum(a[d..c]) l tng cc
phn t lin tip nhau t a[d] n a[c] ca dy a:
sum(a[d..c]) = a[d] + a[d +1]+ ... + a[c].
Gi t l tng cc phn t ca mng: t = sum(a[1..n]).
Mun chia a thnh hai on a[1..i] v a[i+1..n] c tng bng nhau ta phi c:
1. t l s chn (t chia ht cho 2). t t2 = t div 2.
2. (#E i: 1 <= i <= n): sum(a[1..i]) = t2.
Chng trnh
Hm Chia cho gi tr i nu mng a chia c thnh a[1..i] v a[i+1..n].
Trong trng hp v nghim Chia = -1. Ta gi i l im chia v dng bin tr (tng
ring) tch lu tng cc phn t ca on ang xt a[1..i]. Khi tr = t2 bi ton c
nghim i. Ngc li, khi tr > t2 bi ton v nghim.
Ta khi tr ngu nhin cho mng a. Tuy nhin ta mun s ln c nghim (mng a
chia c thnh hai phn c tng bng nhau) xp x bng s ln v nghim. Ta s thc
hin mc tiu ra nh sau:
Mi ln khi tr ta tung ng xu hai mt. Nu gp mt sp (random(2)=0), ta s
khi tr ty cho mng a, ngc li, nu gp mt nga (random(2)=1) ta khi tr a
l mng c nghim.
khi tr sao cho mng a c nghim ta li chn ngu nhin mt im ct d trong
khong 1..(n/2). Sau ta khi tr ngu nhin cho cc phn t a[1..d]. Vi cc
phn t cn li ta cng khi tr ngu nhin trong khong hp l sao cho tng cc gi tr
Sng to trong Thut ton v Lp trnh Tp I

18



ca chng ng bng tng t ca on a[1..d]. Bn c xem chi tit th tc Gen
trong chng trnh.
(* Pascal *)
(*-----------------------------------------
Chia mang nguyen a thanh 2 doan
co tong bang nhau
------------------------------------------- *)
program ChiaTiLe11;
{$B-}
uses crt;
const MN = 500; Esc = #27;
var a: array [1..MN] of integer;
n: integer;
(*-------------------------------------------
Sinh ngau nhien n so nguyen khong am
cho mang a
------------------------------------------- *)
procedure Gen(m: integer);
var i,d,t: integer;
begin
randomize; n := m;
if random(2)=0 then
begin {khoi tri tuy y}
for i := 1 to n do a[i]:=random(m);
exit;
end;
{ Khoi tri mang co tong d phan tu dau
bang tong cac phan tu con lai }
d := random(n div 2)+ 1; { diem chia }
t := 0;
for i := 1 to d do
begin
a[i] := random(n);
t := t + a[i];
end; { t = sum(a[1..d]) }
for i := d+1 to n-1 do
begin { sum(a[d+1..i]) + t = sum(a[1..d]) }
a[i] := random(t);
t := t-a[i];
end;
a[n] := t; { sum(a[1..d]) = sum(a[d+1..n]) }
end;
procedure Xem: Hin th mng a, t vit
function Chia: integer;
var i, t, t2, tr: integer;
begin
Chia := -1; t := 0;
for i:=1 to n do t:=t+a[i]; {t=sum(a[1..n]}
if Odd(t) then exit; { vo nghiem }
t2 := t div 2; tr := 0;
for i:=1 to n do
begin
Sng to trong Thut ton v Lp trnh Tp I

19



tr := tr + a[i];
if tr > t2 then exit; {vo nghiem }
if tr = t2 then { co nghiem i }
begin Chia:= i; exit; end;
end;
end;
procedure Test;
var i: integer;
begin
repeat
Gen(10); Xem; i := Chia;
if i = -1 then writeln('Khong chia duoc')
else
begin
writeln('Doan thu nhat: a[1..',i,']');
writeln('Doan thu hai: a[',i+1,'..',n,']');
end;
until ReadKey=Esc;
end;
BEGIN
Test;
END.
Ch
1. Mun dng chng trnh hy nhn phm Esc c m ASCII l #27.
2. Nu mng a c cha mt s gi tr 0 th bi ton c th c nhiu nghim
(nhiu cch chia).
// C#
using System;
namespace SangTao1
{
class ChiaMangTiLe1_1
{
static void Main()
{
do {
Run(20);
Console.Write("\n Bam phim ENTER +
de tiep tuc, ");
Console.Write("\n Bam phim T de thoat: ");
} while (Console.ReadLine() == "");
}
static public void Run(int n)
{ int[] a = new int[n];
Gen(a, n); // sinh ngau nhien 1 test
Print(a, n);
int t = 0, d = Chia(a, n, ref t);
if (d < 0)
Console.WriteLine("\n Khong chia duoc");
else if (KiemTra(a, n, d))
{ Console.WriteLine("\n Doan thu nhat: 1..{0} ",d);
Console.WriteLine("\n Doan thu hai: {0}..{1} ",
Sng to trong Thut ton v Lp trnh Tp I

20



d+1, n);
Console.WriteLine("\n Tong moi doan: " + t);
}
else Console.WriteLine("\n Loi giai sai!");
} // end Run
// Kiem tra sum(a[1..d] == sum(a[d+1..n]) ?
static public bool KiemTra(int[] a, int n, int d)
{ if (d < 0 || d >= n) return false;
int t = 0;
for (int i = 0; i < d; ++i) t += a[i];
for (int i = d; i < n; ++i) t -= a[i];
return (t == 0) ? true : false;
}
static public int Chia(int[] a, int n, ref int t)
{ int sum = 0; // sum = tong(a[1..n])
for (int i = 0; i < n; ++i) sum += a[i];
if (sum % 2 != 0) return -1;
t = sum / 2; // tong moi doan
int tr = 0; // tong rieng
// doan 1: tr = sum a[1..i]
for (int i = 0; i < n; ++i)
{ tr += a[i];
if (tr == t) return i+1;
}
return -1;
}
// sinh ngau nhien n so ghi vao mang a
static public void Gen(int[] a, int n)
{
Random r = new Random();
if (r.Next(2) == 0)
{ // 1/2 so test la vo nghiem
for (int i = 0; i < n; ++i) a[i]=r.Next(n);
return;
}
// sinh mang a: sum(a[0..d-1])=sum(a[d..n-1])
int d = r.Next(n / 2) + 1; // diem chia
int t = 0;
// sinh doan a[0..d-1]
for (int i = 0; i < d; ++i)
{ a[i] = r.Next(n); t += a[i]; }
// sinh tiep doan a[d..n-1]
int n1 = n-1;
for (int i = d; i < n1; ++i)
{ a[i] = r.Next(t); t -= a[i]; }
a[n-1] = t; // phan tu cuoi
}
static public void Print(int[] a, int n): t vit
} // SoCapNhan
} // SangTao1
Sng to trong Thut ton v Lp trnh Tp I

21



Bi 1.6. Chia mng t l 1:k
Tm cch chia dy s nguyn khng m a
1
, a
2
,...,a
n
, n > 1 cho trc thnh hai
on c tng cc phn t trong mt on gp k ln tng cc phn t trong
on kia, k nguyn dng.
c t
Gi t l tng cc phn t ca dy a, t = sum(a[1..n])
Mun chia a thnh hai on a[1..i] v a[i + 1..n] c tng gp nhau k ln ta phi c:
1. t chia ht cho (k + 1). t t1 = t div (k + 1) v tk = t - t1.
2. (#E i: 1 <= i <= n): sum(a[1..i]) = t1 hoc sum(a[1..i]) = tk.
rng nu k = 1 th t1 = tk; nu k > 1 th t1 < tk, do bi ny l trng hp
ring ca bi trc khi k = 1.
Trong chng trnh di y, hm Chia(k) cho gi tr i nu mng a chia c
thnh hai on a[1..i] v a[(i + 1)..n] c tng gp k ln nhau. Trong trng hp v
nghim Chia = -1. Ta gi i l im chia v dng bin tr (tng ring) tch lu
tng cc phn t ca on ang xt a[1..i]. Khi tr = t1 bi ton c nghim I, ngc li,
khi tr > t1 ta cha th kt lun l bi ton v nghim. Trng hp ny ta phi tip tc
tch lu tr hi vng t c tng tr = tk. Nu sau khi tch lu ta thu c tr = tk th
bi ton c nghim i, ngc li, khi tr > tk ta kt lun l bi ton v nghim.
Function Chia(n,k: integer): integer;
var i: integer;
t, t1, tk, tr: longint;
begin
Chia := -1;
t := 0; { t = sum(a[1..n]) }
for i := 1 to n do t := t+a[i];
if (t mod (k+1) <> 0) then exit; { vo nghiem }
{ Xu li truong hop co nghiem }
t1 := t div (k+1); { doan tong nho }
tk := t - t1; { tk = k * t1}
tr := 0; { tong rieng tr = sum(a[1..i]) }
for i := 1 to n do
begin
tr := tr + a[i];
if (tr = t1) or (tr = tk) then
begin { lay nghiem i }
Chia:= i; exit;
end;
end;
end;
Ta gi th tc Gen sinh d liu kim th. Cng ging nh bi trc, ta s sinh
ngu nhin d liu kim th cho hai trng hp: chc chn c nghim v c th v
nghim. Vi trng hp c th v nghim ta sinh ngu nhin nh bnh thng,
for i := 1 to n do a[i] := random(n);
Vi trng hp c nghim, ta sinh ngu nhin mng a gm hai on:
on th nht a[1..d] v on th hai a[d + 1..n] trong d l mt im chia c
sinh ngu nhin
d := random(n div 2)+1; {diem chia}
Ta li chn ngu nhin mt trong hai trng hp:
Sng to trong Thut ton v Lp trnh Tp I

22



Trng hp th nht: on th nht gp k ln on th hai.
Trng hp th hai: on th hai gp k ln on th nht.
(* Pascal *)
(*-------------------------------------------
Chia mang nguyen a thanh 2 doan
co tong ti le 1:k
------------------------------------------ *)
{$B-}
uses Crt;
const MN = 500;
Esc = #27;{ dau thoat }
bl = #32; { dau cach }
nl = #13#10; { xuong dong }
var a: array [0..MN] of integer;
n: integer;
(*----------------------------------------------
Sinh ngau nhien n so nguyen khong am cho mang a
----------------------------------------------- *)
Procedure Gen(m,k: integer);
var i,d: integer; t: longint;
begin
n := m; t := 0;
if random(2) = 0 then { vo nghiem }
begin
for i := 1 to n do a[i]:= random(n);
exit;
end;
{ co nghiem }
d := random(n div 2)+1; { diem chia }
for i := 1 to d do
begin
a[i] := random(n); t := t+a[i];
end;
if (random(2) = 0) then
{ doan a[1..d] gap k lan doan cuoi }
a[d] := a[d]+(k-1)*t
else { doan cuoi gap k lan doan a[1..d] }
t := k*t;
for i := d+1 to n-1 do
begin
a[i] := random(t); t := t-a[i];
end;
a[n] := t;
end;
Procedure Xem; Hin th mng a, t vit
Function Chia(n,k: integer): integer; T vit
Procedure Test;
var j,i,k: integer; t: longint;
begin
randomize;
repeat
Sng to trong Thut ton v Lp trnh Tp I

23



n := 10 + random(10);
k := random(5)+1;
writeln(nl,' n = ',n,' k = ',k);
Gen(n,k); Xem; i := Chia(n,k);
if i < 0 then writeln('Khong chia duoc')
else
begin
t := 0;
for j := 1 to i do t := t+a[j];
write('Doan 1: a[1..',i,'].');
writeln(' Tong = ',t);
t := 0;
for j:=i+1 to n do t := t+a[j];
write('Doan 2: a[',i+1,'..',n,'].');
writeln(' Tong = ',t);
end;
until ReadKey = Esc;
end;
BEGIN
Test;
END.
// C#
using System;
using System.Collections.Generic;
using System.Text;
namespace SangTao1
{
/*-------------------------------------------
* Chia Mang Ti Le 1:k
* Chia mang nguyen khomng am a[1..] thanh
* hai doan ti le 1:k hoac k:1
* ------------------------------------------*/
class ChiaMangTiLe1_k
{
static void Main(string[] args)
{
do
{
Run(10, 3);
Console.Write("\n Bam RETURN de tiep tuc, ");
Console.Write("\n Bam T de thoat: ");
} while (Console.ReadLine() != "T");
}
static public void Run(int n, int k)
{
if (n < 0 || n > 1000000 || k < 1) return;
int[] a = Gen(n, k);
Print(a);
int d = Chia(a, k);
if (d < 0)
{
Sng to trong Thut ton v Lp trnh Tp I

24



Console.WriteLine("\n Vo nghiem");
return;
}
Console.WriteLine("\n + Test(a, d, k));
}
// Kiem tra k*Sum(a[1..d]) = Sum(a[d+1..n]) ?
// hoac Sum(a[1..d]) = k*Sum(a[d+1..n])
static public bool Test(int[] a, int d, int k)
{
Console.WriteLine("\n\n Test, k = " + k);
Console.WriteLine(" Diem Chia = " + d);
int t1 = 0;
for (int i = 0; i < d; ++i) t1 += a[i];
int t2 = 0;
for (int i = d; i < a.Length; ++i) t2 += a[i];
Console.WriteLine("Sum1 = {0}, Sum2 = {1}",
t1, t2);
return (t1 == k * t2 || t2 == k * t1);
}
static public int Chia(int[] a, int k)
{
int t = 0;
foreach (int x in a) t += x;
if (t % (k + 1) != 0) return -1;
int t1 = t / (k + 1); // tong 1 phan chia
int t2 = t - t1; // tong phan con lai
int tr = 0; // tong rieng
for (int i = 0; i < a.Length; ++i)
{
tr += a[i];
if (tr == t1 || tr == t2) return i+1;
}
return -1;
}
static public int[] Gen(int n, int k)
{
Random r = new Random();
int[] a = new int[n];
if (r.Next(2) == 0)
{ // khoang 1/2 so test la vo nghiem
for (int i = 0; i < n; ++i)
a[i] = r.Next(n);
return a;
}
int d = r.Next(n / 2) + 1; //diem chia
int t = 0;
int d1 = d - 1;
for (int i = 0; i < d1; ++i)
{ a[i] = r.Next(n); t += a[i]; }
if (r.Next(2) == 0)
// doan dau a[1..d]
// gap k lan doan cuoi a[d+1..n]
a[d1] += (k - 1) * t;
Sng to trong Thut ton v Lp trnh Tp I

25



else t *= k; // doan cuoi gap k lan doan dau
int n1 = n - 1;
for (int i = d; i < n1; ++i)
{ a[i] = r.Next(t); t -= a[i]; }
a[n1] = t;
return a;
}
static public void Print(int[] a) t vit
} // ChiaMangTiLel_k
} // SangTao1

Sng to trong Thut ton v Lp trnh Tp I

26



CHNG 2
SINH D LIU VO V RA







Hu ht cc bi ton tin u i hi d liu vo v ra. Ngi ta thng dng ba
phng thc sinh v np d liu sau y:
1. Np d liu trc tip t bn phm. Phng thc ny c dng khi d liu
khng nhiu.
2. Sinh d liu nh hm random (xem chng 1). Phng thc ny nhanh chng v
tin li, nu kho t chc c th sinh ngu nhin c cc d liu p ng c mt s
iu kin nh trc.
3. c d liu t mt tp, thng l tp vn bn. Phng thc ny kh tin li khi
phi chun b trc nhng tp d liu phc tp.
Kt qu thc hin chng trnh cng thng c thng bo trc tip trn mn
hnh hoc ghi vo mt tp vn bn.
Bi 2.1. Sinh ngu nhin theo khong
Sinh ngu nhin cho mng nguyn a n phn t trong khong -M..M; M > 0.
c t
Ta vit th tc tng qut Gen(n,d,c) - sinh ngu nhin n s nguyn trong
khong t d n c (d < c) (xem bi gii 1.4). gii bi 2.1 ta ch cn gi
Gen(n,-M,M).
rng random(cd+1) bin thin trong khong t 0 n c-d do
d+random(cd+1) s bin thin trong khong t d n d+c-d = c.
(*-----------------------------------------
sinh ngau nhien n so nguyen trong khoang
d den c va ghi vao mang a
----------------------------------------- *)
Procedure Gen(n,d,c: integer);
var i,len: integer;
begin
randomize;
len := c-d+1;
for i:=1 to n do a[i]:= d+random(len);
end;
Sng to trong Thut ton v Lp trnh Tp I

27



(* Pascal *)
(*------------------------------------------
Sinh ngau nhien cho mang nguyen a
n phan tu trong khoang -M..M; M > 0.
-------------------------------------------*)
program RGen;
uses crt;
const MN = 1000;
var a: array[1..MN] of integer;
(*--------------------------------------------
sinh ngau nhien n so nguyen trong khoang
d den c va ghi vao mang a
------------------------------------------ *)
Procedure Gen(n,d,c: integer); t vit
procedure Xem(n: integer); Hin th mng a, t vit
procedure Test;
var n: integer;
begin
n := 20;
{ sinh ngau nhien 20 so trong khoang -8..8 }
Gen(n,-8,8);
Xem(n);
readln;
end;
BEGIN
Test;
END.
// C#
using System;
using System.Collections.Generic;
using System.Text;
namespace SangTao1
{
/*--------------------------------------
* Sinh ngau nhien n so
* trong khoang d..c
* -----------------------------------*/
class RGen
{
static void Main(string[] args)
{
Print(Gen(20, -8, 8));
Console.ReadLine();
}
static public int[] Gen(int n, int d, int c)
{
Random r = new Random();
int len = c-d+1;
int [] a = new int[n];
for (int i = 0; i < n; ++i)
a[i] = d + r.Next(len);
Sng to trong Thut ton v Lp trnh Tp I

28



return a;
}
static public void Print(int [] a)
{
Console.WriteLine();
foreach (int x in a)
Console.Write(x + " ");
Console.WriteLine();
}
} // RGen
} // SangTao1
Bi 2.2. Sinh ngu nhin tng
Sinh ngu nhin n phn t c sp khng gim cho mng nguyn a.
Thut ton
1. Sinh ngu nhin phn t u tin: a[1] := random(n);
2. T phn t th hai tr i, tr c sinh bng tr ca phn t st trc n cng
thm mt i lng ngu nhin:
(i = 2..n): a[i] := a[i - 1] + random(n), do a[i] >= a[i - 1].
(* Pascal *)
(*-------------------------------------------
Sinh ngau nhien cho mang nguyen a
n phan tu sap khong giam
-------------------------------------------*)
program IncGen;
uses crt;
const MN = 1000;
var a: array [1..MN] of integer;
(*----------------------------------------
Sinh ngau nhien day tang gom n phan tu
-----------------------------------------*)
procedure Gen(n: integer);
var i: integer;
begin
randomize;
a[1]:= random(5); {khoi tao phan tu dau tien }
for i:= 2 to n do a[i]:= a[i-1]+random(10);
end;
procedure Xem(n: integer); t vit
procedure Test;
var n: integer;
begin
n := 200; { test voi 200 phan tu }
Gen(n); Xem(n); readln;
end;
BEGIN
Test;
END.
// C#
Sng to trong Thut ton v Lp trnh Tp I

29



using System;
using System.Collections.Generic;
using System.Text;
namespace SangTao1
{
/*-------------------------------------
* Sinh ngau nhien n so
* tao thanh day khong giam
* ----------------------------------*/
class IncGen
{
static void Main(string[] args)
{
Print(Gen(200));
Console.ReadLine();
}
static public int[] Gen(int n)
{
Random r = new Random();
int [] a = new int[n];
a[0] = r.Next(5);
for (int i = 1; i < n; ++i)
a[i] = a[i-1] + r.Next(10);
return a;
}
static public void Print(int [] a) t vit
} // IncGen
} // SangTao1
Bi 2.3. Sinh hon v ngu nhin
Sinh ngu nhin cho mng nguyn a mt hon v ca 1..n.
c t
Xut pht t hon v n v a = (1, 2,..., n) ta i ch a[1] vi mt phn t tu (c
chn ngu nhin) a[j] s c mt hon v. Ta c th thc hin vic i ch nhiu ln.
(* Pascal *)
(*-----------------------------------------
Sinh ngau nhien cho mang nguyen a
mot hoan vi cua 1..n
------------------------------------------*)
program GenPer;
const MN = 1000; { so luong toi da }
Esc = #27; { dau thoat }
BL = #32; { dau cach }
var a: array[1..MN] of integer;
(*-----------------------
Sinh du lieu
-----------------------*)
procedure Gen(n: integer);
var i,j,x: integer;
begin
{ Khoi tao hoan vi don vi }
Sng to trong Thut ton v Lp trnh Tp I

30



for i:= 1 to n do a[i]:= i;
for i:= 1 to n do
begin
j := random(n)+1;
x := a[1]; a[1] := a[j]; a[j] := x;
end;
end;
procedure Xem(n: integer); t vit
procedure Test;
var n: integer;
begin
randomize;
repeat {chon ngau nhien kich thuoc n = 10..39}
n := random(30)+10; Gen(n); Xem(n);
until ReadKey = Esc; { Nhan ESC de thoat }
end;
BEGIN
Test;
END.
// C#
using System;
using System.Collections.Generic;
using System.Text;
namespace SangTao1
{
/*---------------------------------
* Sinh ngau nhien hoan vi
* 1..n
* -------------------------------*/
class GenPer
{
static void Main(string[] args)
{
Print(Gen(20));
Console.ReadLine();
}
static public int[] Gen(int n)
{
Random r = new Random();
int[] a = new int[n];
for (int i = 0; i < n; ++i)
a[i] = i+1;
for (int i = 0; i < n; ++i)
{
int j = r.Next(n);
int t = a[0];
a[0] = a[j]; a[j] = t;
}
return a;
}
static public void Print(int [] a) t vit
Sng to trong Thut ton v Lp trnh Tp I

31



} // IncGen
} // SangTao1
Bi 2.4. Sinh ngu nhin u
Sinh ngu nhin n phn t cho mng nguyn a tho iu kin n phn t to
thnh k on lin tip c tng cc phn t trong mi on bng nhau v bng
gi tr t cho trc.
Thut ton
1. Chn s lng cc phn t trong mi on l random(n div k) + 1, khi
s lng cc phn t c pht sinh ngu nhin s khng vt qu
k*(n div k) n
Sau ta s chnh sao cho s lng cc phn t ng bng n.
2. Gi s a[d..c] l on th j cn c sinh ngu nhin sao cho
a[d] + a[d + 1] + ... + a[c] = t
Ta sinh on ny nh sau:
2.1. Gn tr := t; { tr - gi tr cn li ca tng }.
2.2. Gn tr ngu nhin 0..tr-1 cho cc phn t a[d..(c - 1)]
(i = d..c ): a[i] := random(tr)
2.3. ng thi chnh gi tr cn li ca tr:
tr := tr - a[i]
Ta c:
a[d] < t
a[d+1] < t - a[d]
a[d+2] < t - a[d+1] - a[d]
...
a[c - 1] < t - a[d] - a[d + 1] - ... - a[c - 2]
Chuyn v cc phn t a[*] trong biu thc cui cng, ta thu c
a[d] + a[d + 1] + ... + a[c 1] < t
2.4. Ta t gi tr cn li ca tng ring vo phn t cui on: a[c] :=
tr s thu c a[d] + a[d + 1] + ... + a[c] = t.
(* Pascal *)
(*-----------------------------------------
Sinh ngau nhien cho mang nguyen a
n phan tu tao thanh k doan lien tiep
co tong bang nhau
------------------------------------------*)
program KGen;
uses crt;
const MN = 1000; {kich thuoc toi da cua mang a}
Esc = #27; {dau thoat}
BL = #32; {dau cch}
var a: array[1..MN] of integer;
(*---------------------------
Sinh du lieu
-----------------------------*)
procedure Gen(n,k,t: integer);
var i,j,p,tr,s: integer;
Sng to trong Thut ton v Lp trnh Tp I

32



begin
if (k < 1) or (k > n) then exit;
s := n div k;{s - so toi da phan tu trong moi doan}
i := 0; {chi dan lien tuc cho cac phan tu moi sinh}
for j := 1 to k do {sinh doan thu j}
begin
tr := t;
for p := 1 to random(s) do
{ random(s)+1 = so phan tu trong 1 doan }
begin
inc(i);
a[i] := random(tr);
tr := tr a[i]; {gia tri con lai cua tong}
end;
inc(i); {i phan tu cuoi cung cua doan j}
a[i] := tr;
end;
{bu 0 cho cac phan tu con lai}
for i := i+1 to n do a[i] := 0;
end;
procedure Xem(n: integer); Hin th mng a, t vit
procedure Test;
var n,k: integer;
begin
randomize;
repeat
n := random(30) + 1;
k := random(8) + 1;
t := random(30)+10;
writeln('n = ',n,' k = ',k,' t = ',t);
Gen(n,k,t); Xem(n);
until ReadKey = Esc;
end;
BEGIN
Test;
END.
// C#
using System;
using System.Collections.Generic;
using System.Text;
using System;
namespace SangTao1
{
class KGen
{
static void Main(string[] args)
{
Random r = new Random();
int n, k, t;
do
{
n = r.Next(30) + 1;
Sng to trong Thut ton v Lp trnh Tp I

33



t = r.Next(30) + 1;
k = r.Next(8) + 1;
Console.WriteLine("\n n = " + n +
" k = " + k + " t = " + t);
Print(Gen(n, k, t));
Console.Write("\n Bam RETURN de tiep tuc: ");
} while (Console.ReadLine() == "");
}
// sinh n phan tu chia thanh k doan,
// moi doan co tong t
static public int[] Gen(int n, int k, int t)
{
if (k < 1 || k > n) return new int[0];
Random r = new Random();
int[] a = new int[n];
int s = n / k; // so phan tu trong 1 doan
int i = 0;
for (int j = 0; j < k; ++j)
{ // sinh doan thu j
int tr = t;
int endp = r.Next(s);
for (int p = 0; p < endp; ++p,++i)
{ a[i] = r.Next(tr); tr -= a[i]; }
a[i++] = tr;
}
// dien 0 cho du n phan tu
for (; i < n; ++i) a[i] = 0;
return a;
}
static public void Print(int[] a) t vit
} // KGen
} // SangTao1
Bi 2.5. Sinh ngu nhin t l
Sinh ngu nhin cho mng nguyn a c n phn t to thnh hai on lin tip
c tng cc phn t trong mt on gp k ln tng cc phn t ca on kia.
Thut ton
1. Sinh ngu nhin tng t1 := random(n) + 1.
2. Tnh t2 := k*t1.
3. Gieo ng xu bng cch gi random(2) xc nh tng no trong s t1
v t2 c chn trc.
4. Sinh random(n div 2)+1 phn t cho on th nht sao cho tng cc
phn t ca on ny bng t1 (xem bi 2.4).
5. Sinh nt cc phn t cho on th hai sao cho tng cc phn t ca on ny
bng t2.
(* Pascal *)
program K2gen;
uses crt;
const MN = 1000;
Sng to trong Thut ton v Lp trnh Tp I

34



var a: array[1..MN] of integer;
(*---------------------------
Sinh du lieu
-----------------------------*)
procedure Gen(n,k:integer);
var i,j,t1,t2:integer;
begin
if (k < 1) OR (k > n) then exit;
t1 := random(n) + 1;
{tong mot doan; tong doan con lai = k*t1 }
{chon ngau nhien doan co tong lon dat truoc hay sau
}
if random(2)= 0 then t2 := k*t1
else
begin
t2 := t1; t1 := k*t2;
end;
i := 0; {sinh doan thu nhat}
for j := 1 to random(n div 2) do
begin
inc(i); a[i] := random(t1);
t1 := t1 a[i];
end;
inc(i); a[i] := t1;
while i < n do {sinh doan thu hai }
begin
inc(i); a[i]:= random(t2);
t2 := t2 a[i];
end;
a[n] := a[n] + t2;
end;
procedure Xem(n: integer); t vit
procedure Test;
var n,k: integer;
begin
randomize;
repeat
n := random(30) + 1;
k := random(8) + 1;
write(' n = ',n,' k = ',k);
Gen(n,k); Xem(n);
until ReadKey = #27;
end;
BEGIN
Test;
Sng to trong Thut ton v Lp trnh Tp I

35



END.
// C#
using System;
using System.Collections.Generic;
using System.Text;
namespace SangTao1
{
class K2Gen
{
static void Main(string[] args)
{
Random r = new Random();
int n, k;
do
{
n = r.Next(30) + 2;
k = r.Next(8) + 1;
Console.WriteLine("\n n = " + n +
" k = " + k);
int [] a = new int [n];
int n1 = Gen(a,n,k);
Print(a);
Test(a, n1, k);
Console.Write("\n Bam RETURN " +
" de tiep tuc: ");
} while (Console.ReadLine() == "");
}
// Kiem tra ket qua
static void Test(int[] a, int n1, int k)
{
int t1 = 0;
for (int i = 0; i < n1; ++i)
t1 += a[i];
Console.WriteLine("\n Doan thu nhat: " +
"sum(a[0.." + (n1 - 1) + "]) = " + t1);
int t2 = 0;
for (int i = n1; i < a.Length; ++i)
t2 += a[i];
Console.WriteLine("\n Doan thu hai: " +
"sum(a["+n1+".."+(a.Length - 1)+"]) = "+t2);
if ((t1 == k * t2) || (t2 == k * t1))
Console.WriteLine("\n DUNG");
else Console.WriteLine("\n SAI");
}

Sng to trong Thut ton v Lp trnh Tp I

36



static public int Gen(int [] a, int n, int k)
{
Random r = new Random();
int i = 0; // phan tu thu i trong a
// n1 - so phan tu trong doan 1
int n1 = r.Next(n / 2) + 1;
int t1 = 0; // tong doan 1
// sinh doan thu 1
for (; i < n1; ++i) //
{
a[i] = r.Next(10); t1 += a[i];
}
int t2 = k* t1;
int tt = t1;
// xac dinh ngau nhien
// 0. t2 gap k lan t1, hoac
// 1. t1 gap k lan t2
if (r.Next(2)==1)
{ // t1 gap k lan t2
t1 = t2; t2 = tt; a[i-1] += (t1-t2);
}
// sinh doan 2
for (; i < n; ++i) //
{
a[i] = r.Next(t2); t2 -= a[i];
}
a[n-1] += t2;
return n1;
}

static public void Print(int[] a)
{
Console.WriteLine();
foreach (int x in a)
Console.Write(x + " ");
Console.WriteLine();
}
} // K2Gen
} // SangTao1
Bi 2.6. Sinh ngu nhin tp tng
Sinh ngu nhin n s t nhin sp tng v ghi vo mt tp vn bn c tn cho
trc.
Thut ton
Bn c xem trc tip chng trnh v gii thch cch lm.
Sng to trong Thut ton v Lp trnh Tp I

37



(* Pascal *)
(*---------------------------------------
Sinh ngau nhien n so tu nhien sap tang
va ghi vao tep van ban co ten cho truoc
----------------------------------------*)
program FincGen;
uses crt;
const BL = #32; { dau cach }
(*---------------------------
Sinh du lieu
-----------------------------*)
procedure Gen(fn: string; n: integer);
var f: text; i: integer; x: longint;
begin
assign(f,fn); {fn: file name (ten tep)}
rewrite(f); randomize;
x := 0;
for i:= 1 to n do
begin
x := x+random(10); write(f,x,BL);
{ moi dong trong file chua 20 so }
if i mod 20 = 0 then writeln(f);
end;
if i mod 20 <> 0 then writeln(f);
close(f);
end;
procedure Test;
begin
Gen('DATA.INP',200);
write('Ket'); readln;
end;
BEGIN
Test;
END.
// C#
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace SangTaoT1
{
class FincGen
{
static void Main(string[] args)
{
string fn = "Data.txt";
GenToFile(fn, 81);
Show(fn); Console.ReadLine();
}
static public void GenToFile(string fn, int n)
Sng to trong Thut ton v Lp trnh Tp I

38



{
StreamWriter f = File.CreateText(fn);
Random r = new Random();
int x = r.Next(10);
for (int i = 0; i < n; ++i)
{
f.Write(x + " ");
// Moi dong 20 so
if (i % 20 == 19) f.WriteLine();
x += r.Next(10);
}
if (n % 20 != 19) f.WriteLine();
f.Close();
}
static public void Show(string fn)
{
Console.WriteLine(File.ReadAllText(fn));
}
} // FincGen
} // SangTao1
Bi 2.7. Sinh ngu nhin tp cp s cng
Sinh ngu nhin mt cp s cng c n s hng v ghi vo mt tp vn bn c
tn cho trc.
Thut ton
1. Sinh ngu nhin s hng th nht a[1] v cng sai d.
2. Sinh cc phn t a[i], i = 2..n
for i:=2 to n do a[i]:= a[i1]+ d;
3. Ghi file
phc tp: n.
(* Pascal *)
program FCapCong;
uses crt;
const BL = #32;
procedure Gen(fn: string; n: integer);
var f: text; i,d: integer; x: longint;
begin
assign(f,fn); rewrite(f);
randomize;
d := random(n div 4)+1; {cong sai }
x := random(20); write(f,x,BL);
for i:= 2 to n do
begin { mi dng ghi 20 s }
x:= x + d; write(f,x,BL);
if i mod 20 = 0 then writeln(f);
end;
if i mod 20 <> 0 then writeln(f);
close(f);
end;
BEGIN
Sng to trong Thut ton v Lp trnh Tp I

39



Gen('DATA.INP',200); write('Ket'); readln;
END.
// C#
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace SangTao1
{
class FCapCong
{
static void Main(string[] args)
{
string fn = "Data.txt";
GenToFile(fn, 81);
Show(fn); Console.ReadLine();
}
static public void GenToFile(string fn, int n)
{
StreamWriter f = File.CreateText(fn);
Random r = new Random();
int s = r.Next(n), d = r.Next(10)+1;
for (int i = 0; i < n; ++i)
{
f.Write(s + " ");
if (i % 20 == 19) f.WriteLine();
s += d;
}
if (n % 20 != 19) f.WriteLine();
f.Close();
}
static public void Show(string fn)
{
Console.WriteLine(File.ReadAllText(fn));
}
} // FcapCong
} // SangTao1
Bi 2.8. Sinh ngu nhin mng i xng
Sinh ngu nhin cc gi tr ghi vo mt mng hai chiu a[1..n, 1..n] sao cho
cc phn t i xng nhau qua ng cho chnh, tc l
a[i, j] = a[j, i], 1 i, j N.
Thut ton
1. Sinh ngu nhin cc phn t trn ng cho chnh a[i,i],i=1..n.
2. Sinh ngu nhin cc phn t nm pha trn ng cho chnh a[i,j],
i=1..n, j=i+1..n ri ly i xng: a[j,i]:= a[i,j].
phc tp: n
2
.
(* Pascal *)
Sng to trong Thut ton v Lp trnh Tp I

40



program GenMatSym;
uses crt;
const MN = 100;
var a = array[1..MN,1..MN] of integer;
procedure Gen(n: integer);
var i, j: integer;
begin
randomize;
for I := 1 to n do
begin
a[i,i] := random(n);
for j := i+1 to n do
begin
a[i,j]:=random(n); a[j,i]:=a[i,j];
end;
end;
end;
procedure Xem(n: integer);
var i, j: integer;
begin
writeln;
for i:= 1 to n do
begin
writeln;
for j:= 1 to n do write(a[i,j]:4);
end;
end;
BEGIN
Gen(20); Xem(20); readln;
END.
// C#
using System;
using System.Collections.Generic;
using System.Text;
namespace SangTao1
{
class GenMatSym
{
static void Main(string[] args)
{
int n = 20;
int[,] a = Gen(n);
Print(a, n);
Console.WriteLine("\n Fini ");
Console.ReadLine();
}
static public int [,] Gen(int n)
{
int[,] a = new int[n, n];
Random r = new Random();
for (int i = 0; i < n; ++i)
Sng to trong Thut ton v Lp trnh Tp I

41



{
a[i, i] = r.Next(100);
for (int j=i+1; j<n; ++j)
{ a[i, j] = r.Next(100);
a[j, i] = a[i, j];
}
}
return a;
}
// hin th mng a[0..(n-1]
static public void Print(int [,] a,int n) t
vit
} // GenMatSym
} // SangTao1
Bi 2.9. S cao h
cao ca mt s t nhin l tng cc ch s ca s . Sinh ton b cc s
t nhin c ti a ba ch s v c cao h cho trc. Ghi kt qu vo mt tp
vn bn c tn cho trc.
Thut ton
Bi ton ny c cch pht biu khc v tng qut nh sau: c n cc nc dung tch
9 tha mi cc. Cho mt bnh ng h tha nc. Hy xc nh mi phng n chia
nc vo cc cc.
Ta xt li gii vi n = 3. Ta c h = 0..27.
1. Cc s cn tm y c dng y = abc, a + b + c = h v a bin thin t mina n maxa,
trong mina l lng nc t nht trong cc u tin a, maxa l lng nc ln nht trong
cc a. Nu y hai cc b v c, mi cc 9 tha nc th lng nc cn li s l ti thiu
cho cc a. Ngc li, nu tng cng ch c h < 9 tha nc th lng nc ti a trong cc a
phi l h. Ta c
if h s 18 then mina := 0 else mina := h-18;
if h > 9 then maxa := 9 else maxa := h;
2. Vi mi a = mina..maxa ta tnh
2.1. bc = h-a (bin bc cha tng cc ch s b v c).
2.2. Gii bi ton nh vi n = 2.
if bc s 9 then minb := 0 else minb := bc-9;
if bc > 9 then maxb := 9 else maxb := bc;
2.3. Vi mi b = minb..maxb ta tnh
y = 100*a + 10*b + (bc b).
Ghi s ny vo tp.
(* Pascal *)
(*-=-----------------------------
Sinh cac so khong qua 3 chu so
co do cao h va ghi vao tep fn
--------------------------------*)
program HGen;
uses crt;
Sng to trong Thut ton v Lp trnh Tp I

42



function Gen(fn:string;h:integer): integer;
var f: text;
a,b,bc,mina,maxa,minb,maxb: integer;
x,y,d: integer;
begin {tong 3 chu so toi da la 27, toi thieu la 0 }
if (h < 0) OR (h > 27) then exit;
assign(f,fn); rewrite(f);
d:= 0; {dem so luong cac so do cao h}
if h <= 18 then mina := 0 else mina := h-18;
if h >= 9 then maxa := 9 else maxa := h;
for a := mina to maxa do
begin
x := 100*a;
bc := h-a;
if bc <= 9 then minb := 0 else minb := bc-9;
if bc >= 9 then maxb := 9 else maxb := bc;
for b := minb to maxb do
begin
y := x + 10*b + (bc - b);
write(f,y:4);
inc(d); { Ghi moi dong 10 so }
if d mod 10 = 0 then writeln(f);
end;
end;
close(f);
Gen := d;
end;
procedure Test;
var n: integer;
begin
n := Gen('HEIGHT.NUM',10);
write('Tong cong ,n,' so');
readln;
end;
BEGIN
Test;
END.
// C#
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace SangTao1
{
class HGen
{
static void Main(string[] args)
{
string fn = "HGen.txt";
int h = 10;
Console.WriteLine("\n File " + fn);
Sng to trong Thut ton v Lp trnh Tp I

43



Console.WriteLine(" H = " + h);
int d = Gen(fn,10);
Test(fn,d);
Console.WriteLine("\n Fini ");
Console.ReadLine();
}
static public int Gen(string fn, int h)
{
int a, b, mina, maxa, minb, maxb,
bc, x, y, d = 0;
StreamWriter f = File.CreateText(fn);
mina = (h <= 18) ? 0 : h-18;
maxa = (h <= 9) ? h : 9;
for (a = mina; a <= maxa; ++a)
{
x = 100*a; bc = h - a;
minb = (bc <= 9) ? 0 : bc-9;
maxb = (bc >= 9) ? 9 : bc;
for (b = minb; b <= maxb; ++b)
{
++d; y=x+10*b+(bc-b); f.Write(y+" ");
if (d % 10 == 0) f.WriteLine();
}
}
f.Close();
return d;
}
// Doc lai file de kiem tra
static public void Test(string fn,int d)
{
Console.WriteLine("\n Tong cong " +
d + " so");
Console.WriteLine(File.ReadAllText(fn));
}
} // HGen
} // SangTao1
Ch
1. C th gii bi ton trn bng phng php vt cn dng ba vng for nh sau:
for a := 0 to 9 do
for b := 0 to 9 do
for c := 0 to 9 do
if a+b+c = h then
write(f,a,b,c,#32);
2. Phng php vt cn i hi 10*10*10 = 1000 ln duyt trong khi vi h = 10 ch
c 63 s tho mn iu kin ca u bi. Dng phng php sinh ta nhn c ng 63
s cn tm, khng phi duyt tha s no.
Bi 2.10. Tp cc hon v
Sng to trong Thut ton v Lp trnh Tp I

44



Vi mi s n cho trc trong khong 1..9, ghi vo mt tp vn bn c tn cho
trc ton b cc hon v ca 1..n. Hon v c sp xp tng theo th t t
in, th d 21345 < 21354.
Thut ton
1. Khi to v ghi hon v nh nht l hon v n v s [1..n] =
(1,2,...,n).
2. Gi s ta ghi c hon v s[1.n] vo tp. Hon v tip theo c to t s
thng qua hm Next nh sau:
2.1 Tm im gy: Tm ngc t s[n] tr v trc n v tr i u tin tho
iu kin s[i] < s[i + 1].
- Nu khng tm c i tc l s l hon v ln nht, s[1..n] = (n,n-
1,..,1). t tr false cho hm Next v dng thut ton. Next =
false c ngha l khng tn ti hon v st sau hon v s hay s l hon v
ln nht.
- Nu tm c: thc hin bc 2.2.
2.2 Tm im vt: Tm ngc t s[n] tr v trc n v tr j u tin tho
iu kin s[j] > s[i].
2.3. i ch s[i] vi s[j].
2.4. Lt: o li trt t ca dy s[i + 1..n] ta s thu c hon v ng
st sau hon v s.
3. t tr true cho hm Next. Next = true c ngha l tm c hon v st
sau hon v s.
Ch
Khi khi tr hon v n v ta s dng phn t s[0] = 0 lm lnh canh. Nh vy, khi
duyt ngc tm im gy ta khng phi kim tra gii hn mng. Thay v vit
i := n-1;
while (i > 0) and (s[i] > s[i+1]) do i:= i-1;
ta ch cn vit
i := n-1;
while (s[i] > s[i+1]) do i := i-1;
Hm Next c m t nh sau:
function Next(n: integer): Boolean;
var i, j, t: integer;
begin
Next := false; i := n-1;
while (s[i] > s[i+1]) do i:= i-1;
if i = 0 then exit;
{ s[i] < s[i+1], i l im gy }
j := n; { Tm im vt a[j] > a[i] }
while (s[j] < s[i]) do j := j-1;
{ i ch s[i] , s[j] }
t:= s[i]; s[i]:= s[j]; s[j]:= t;
{ Lt s[i+1..n] } i:= i+1; j:= n;
while i < j do
begin
t:= s[i];s[i]:= s[j]; s[j]:= t;
i:= i+1; j:= j-1;
Sng to trong Thut ton v Lp trnh Tp I

45



end;
Next:= true;
end;
Th d, vi n = 8, gi s ta ghi c hon v s = 74286531, khi hon v st
sau s s c xy dng nh sau:


C O C C O
S 7 4 2 8 6 5 3 1
Tm im gy: i = 3, v s[3] < s[4] 7 4 2 8 6 5 3 1
Tm im vt: j = 7, v s[7] > s[3] 7 4 2 8 6 5 3 1
i ch im gy v im vt: s[3] s[7] 7 4 3 8 6 5 2 1
Lt on s[4..8] 7 4 3 1 2 5 6 8
Quy trnh hot ng ca hm Next
74286531 74312568
(* Pascal *)
program GenAllPer;
{$B-}
uses crt;
const MN = 9; {max n} BL = #32; {dau cach}
var s: array[0..MN] of integer;
function Next(n: integer): Boolean; t vit
procedure Gen(n: integer);
const
fn = 'HoanVi.dat'; {ten tep ket qua}
var
d: longint; {dem so luong hoan vi}
i: integer;
f: text; {tep ket qua}
begin
if (n < 1) or (n > MN) then exit;
assign(f,fn); rewrite(f);
d := 0; {dem so hoan vi}
{Sinh hon v n v. t lnh canh s[0] = 0}
for i := 0 to n do s[i]:= i;
repeat
d := d+1; {Ghi hoan vi thu d, s vao tep}
for i:= 1 to n do write(f, s[i], BL);
writeln(f);
until not (next(n));
writeln(f,' Tong cong ',d, ' hoan vi');
close(f);
end;
BEGIN
Gen(5); write('fini'); readln;
END.
// C#
using System;
using System.Collections.Generic;
using System.Text;
Sng to trong Thut ton v Lp trnh Tp I

46



using System.IO;
namespace SangTao1
{
class GenAllPer
{
static void Main(string[] args)
{
string fn = "HoanVi.txt";
int d = Gen(fn,5);
Test(fn,d); // Xem kt qu
Console.WriteLine("\n Fini ");
Console.ReadLine();
}
// Sinh cc hon v, ghi file fn
static public int Gen(string fn, int n)
{
if (n < 1 | n > 9) return 0;
int d = 0; // dem so hoan vi d = n!
StreamWriter f = File.CreateText(fn);
int[] a = new int[n + 1];
for (int i=0; i <= n; ++i) a[i]=i;
do { // Ghi file
for (int i=1; i <= n; ++i)
f.Write(a[i] + " ");
f.WriteLine(); ++d;
} while (Next(a));
f.Close();
return d;
}
static bool Next(int[] a)//Hon v tip
{
int i, j, t, n = a.Length-1;
for (i=n-1; a[i] > a[i+1];--i) ;
if (i == 0) return false;
for (j = n; a[j] < a[i]; --j) ;
t = a[i]; a[i] = a[j]; a[j] = t;
for (++i, j = n; i < j; ++i, --j)
{ t = a[i]; a[i] = a[j]; a[j] = t; }
return true;
}
static public void Test(string fn, int d)
{
Console.WriteLine("\n Tong cong "
+ d + " so");
Console.WriteLine(File.ReadAllText(fn));
}
} // GenAllPer
} // SangTao1
Bi 2.11. c d liu t tp vo mng bit hai kch thc
c d liu kiu nguyn t mt tp vn bn vo mt mng hai chiu.
Tp c cu trc nh sau:
- Hai s u tin n, m l kch thc ca mng gm n dng v m ct.
Sng to trong Thut ton v Lp trnh Tp I

47



- Tip n l cc d liu ghi lin tip nhau theo tng dng ca mng.
- Cc s cch nhau t nht mt du cch.
Th d:
2 3 -1 4 5 3 7 1
cho bit mng c n = 2 dng v m = 3 ct vi d liu nh sau:
-1 4 5
3 7 1
c t
Ta vit hm Doc cho gi tr true nu c c d liu. Ch rng d liu vo l
ng do khng cn kim tra tnh ng n ca chng. Nh vy Doc s cho gi tr
false trong trng hp khng m c file, do ghi sai ng dn hoc file
khng c to lp t trc.
Ch th {$I-} yu cu h thng ch ghi nhn ch khng bt cc li vo/ra, tc l
khng dng s thc hin chng trnh. Bin h thng IORESULT s ghi nhn s hiu
li. Nu IORESULT=0 th thao tc vo ra khng sinh li, ngc li, nu IORESULT
0 tc l c li.
Ch th {$I+} yu cu h thng bt mi li vo/ra. Nh vy, dng lnh
{$I-} reset(f); {$I+}
s c hiu nh sau:
Thot tin ta yu cu h thng b ch bt li vo/ra {$I-}. Sau thc hin
lnh m tp c reset(f).Tip n t li ch bt li {$I+}.
(* Pascal *)
uses crt;
const MN = 100;
var a: array[1..MN,1..MN] of integer;
m,n: integer;
Function Doc(fn: string): Boolean;
var
f: text;
i, j: integer;
begin
Doc := false; assign(f,fn);
{$I-} reset(f); {$I+}
if IORESULT <> 0 then exit; {khng m c file}
read(f,n,m);{doc kich thuoc n va m cua mang }
for i := 1 to n do
for j:= 1 to m do
read(f,a[i, j]);
close(f);
Doc := true;
end;
procedure Xem(n,m: integer); Hin th mng 2 chiu,
t vit
BEGIN
if Doc('DATA.INP') then Xem(n,m)
else write('Khong mo duoc tep ');
readln;
Sng to trong Thut ton v Lp trnh Tp I

48



END.
// C#
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace sabgTao1
{
class DocMang2Chieu
{
static void Main(string[] args)
{
string fn = "Data.inp";
int n = 0, m = 0;
int [,] a = Doc(fn, ref n, ref m);
if (a != null)
{
PrintInput(fn);
Print(a, n, m);
}
else
Console.WriteLine("\n " +
" Khong mo duoc file " +fn);
Console.WriteLine("\n Fini ");
Console.ReadLine();
}

static public int[,] Doc(string fn,
ref int n, ref int m)
{
if (!File.Exists(fn)) return null;
// Cac dau ngan
char[] cc = new char[]
{ ' ', '\n', '\t', '\r' };
// Mo tep ten fn doc, tch, dong tep
string[] ss = (File.ReadAllText(fn)).
Split(cc,
StringSplitOptions.RemoveEmptyEntries);
// Chuyn sang mng 1 chiu int [] c
int [] c = Array.ConvertAll(ss,
new Converter<string,int>(int.Parse));
n = c[0]; m = c[1];
int[,] a = new int[n, m];
int k = 2;
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
a[i,j] = c[k++];
return a;
}
static void Print(int[,] a, int n, int m)
Hin th mng 2 chiu a, t vit
Sng to trong Thut ton v Lp trnh Tp I

49



static public void PrintInput(string fn)
c li file fn, t vit
} // DocMang2Chieu
} // sangTao1
Gii thch
Trong cc my tnh hin i, b nh trong RAM ln c th cha ton b d
liu trong hu ht cc file input v th vi mi trng C# .NET bn nn c mt ln
d liu t cc file ny. Hm Doc cho ra mng nguyn hai chiu. Nu file khng tn ti,
hm cho ra gi tr null. Bn cn chun b trc file input vi tn Data.inp v ghi vo th
mc BIN\DEBUG trong Project hin hnh. Nu ghi file vo th mc khc th trong
tham bin fn phi ghi chi tit ng dn, th d D:\\MyDIR\\Data.inp. Khi
vit ng dn, thay v vit du \ ta phi vit hai du , tc l \\ v bn thn
du \ trong ng vai tr bo hiu k t ng st sau n l k t iu khin, th d,
\n biu th du xung dng. Bn cng c th vit du i mc @ cnh ng dn
ch th rng bn mun dng mt du \ thay v hai du, th d,
@D:\MyDIR\Data.inp
Lnh File.ReadAllText(fn) m file vi ng dn fn c ton b d liu
mt ln vo mt bin string sau t ng ng file.
Lnh Split(cc,StringSplitOptions.RemoveEmptyEntries)
tch cc n v trong bin string ghi vo bin string[] ss ng thi b i cc
du trng m t trong bin cc, bao gm du cch , du xung dng \n, du tab
\t v du kt RETURN \r, cui cng loi b cc n v rng, tc l cc string
khng cha k t no (Length = 0).
Lnh int[] c = Array.ConvertAll(ss,
New Converter<string,int>(int.Parse));
chuyn cc string trong ss sang dng s nguyn v ghi vo mng nguyn (mt chiu)
c. n y ton b d liu trong file input fn c c v ghi vo mng nguyn c. Cc
mng trong C# c nh ch dn t 0 n Length-1. Theo iu kin ca u bi c[0]
cha gi tr n, c[1] cha gi tr m, t c[2] tr i cha ln lt cc gi tr trn cc dng
ca mng hai chiu.
Bi 2.12. c d liu t tp vo mng bit mt kch thc
c d liu kiu nguyn t mt tp vn bn vo mt mng hai chiu a[n,m] cho
bit mt kch thc m (s ct).
Tp c cu trc nh sau:
- S u tin ghi s lng ct m ca mng tc l s phn t trn mt dng.
- Tip n l cc d liu ghi lin tip nhau theo tng dng ca mng.
- Cc s cch nhau t nht mt du cch.
Th d:
3 -1 4 5 3 7 1
s c b tr vo mng n = 3 dng, m = 3 ct nh sau:
-1 4 5
3 7 1
Thut ton
Sng to trong Thut ton v Lp trnh Tp I

50



1. M tp.
2. c gi tr u tin vo bin m: s lng ct ca ma trn.
3. Mi ln c xong mt dng ta tng con m dng (n) thm 1.
Ch
Do c th gp dng trng nn ta cn s dng hm SeekEof. Hm SeekEof
duyt tip t v tr hin thi ca con tr tp, b qua cc du trng (gm du cch, du
kt thc dng, du u dng, du nhy TAB), nu gp du ht tp th cho gi tr true,
ngc li, nu sau khi b qua cc du trng m cha gp du ht tp th cho gi tr
false.
(* Pascal *)
uses crt;
const MN = 100;
var a: array[1..MN,1..MN] of integer;
m,n: integer;
Function Doc(fn: string): Boolean;
var f: text; j: integer;
begin
Doc := FALSE; assign(f,fn);
{$I-} reset(f); {$I+}
if IORESULT <> 0 then exit;
read(f,m); {m: so luong cot}
n := 0; {n: so luong dong}
while NOT SeekEof(f) do
begin
inc(n);
for j := 1 to m do read(f,a[n,j]);
end;
close(f);
Doc := TRUE;
end;
procedure Xem(n,m: integer); t vit
BEGIN
if Doc('DATA.INP') then Xem(n,m)
else write('Khong mo duoc tep ');
readln;
END.
Ch
Cn chun b trc d liu v ghi trong tp vn bn DATA.INP, th d:

DATA.INP
3 -1 4 5 3 7 1
// C#
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
Sng to trong Thut ton v Lp trnh Tp I

51



namespace SangTao1
{
class DocMang2
{
static void Main(string[] args)
{
string fn = "Data.inp";
int n = 0, m = 0;
int [,] a = Doc(fn, ref n, ref m);
if (a != null)
{
PrintInput(fn);
Print(a, n, m);
}
else Console.WriteLine("\n " +
" Khong mo duoc file " + fn);
Console.WriteLine("\n Fini ");
Console.ReadLine();
}

static public int[,] Doc(string fn,
ref int n, ref int m)
{
if (!File.Exists(fn)) return null;
int [] c = Array.ConvertAll(
File.ReadAllText(fn).
Split(new char[] {' ','\n','\t','\r'},
StringSplitOptions.RemoveEmptyEntries),
new Converter<string,int>(int.Parse));
int k = 0;
m = c[k++]; n = (c.Length-1)/m;
int[,] a = new int[n, m];
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
a[i,j] = c[k++];
return a;
}
static void Print(int [,] a, int n, int m)
Hin th mng 2 chiu a[n,m], t vit
static public void PrintInput(string fn)
Hin th file fn; t vit
} // DocMang2
} // SangTao1
Gii thch
Bit s ct ca mng l m ta c th tnh ra s dng n ca mng theo cng thc
n = (c.Length-1) / m, trong c.Length cha s lng cc gi tr
c t file input, bao gm gi tr m v n.m gi tr ca mng, tc l
c.Length = n.m+1.
Bi 2.13. c d liu t tp vo mng i xng
Sng to trong Thut ton v Lp trnh Tp I

52



c d liu kiu nguyn t mt tp vn bn c tn fn vo mt mng hai chiu
i xng.
Tp c cu trc nh sau:
- S u tin ghi s lng ct (v ng thi l s lng dng) ca mng.
- Tip n l cc d liu ghi lin tip nhau theo na tam gic trn tnh t
ng cho chnh.
- Cc s cng dng cch nhau t nht mt du cch.
Th d: 3 1 2 3 4 6 8 s c b tr vo mng 3 3 nh sau:
1 2 3
2 4 6
3 6 8
Thut ton
1. M tp.
2. c gi tr u tin vo bin n: s lng ct v dng ca ma trn vung i
xng.
3. Vi mi dng i ta c phn t trn ng cho chnh ca dng a[i, i], sau
ta c cc phn t nm bn phi a[i, i], tc l a[i, j] vi j = i + 1..n ri ly i xng
bng php gn a[j, i]:= a[i, j].
(* Pascal *)
uses crt;
const MN = 100;
var a: array[1..MN,1..MN] of integer;
n: integer; { kich thuoc mang }
Function Doc(fn: string): Boolean;
var f: text; i, j: integer;
begin
Doc := FALSE; assign(f,fn);
{$I-} reset(f); {$I+}
if IORESULT <> 0 then exit;
read(f,n);
for i := 1 to n do
begin
read(f,a[i,i]);
for j := i+1 to n do
begin
read(f,a[i,j]); a[j,i]:= a[i,j];
end;
end;
close(f); Doc:= TRUE;
end;
procedure Xem(n,m: integer); t vit
BEGIN
if Doc('DATA.INP') then Xem(n,n)
else write('Khong mo duoc tep ');
readln;
END.
// C#
Sng to trong Thut ton v Lp trnh Tp I

53



using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace SangTao1
{
class MangDoiXung
{
static void Main(string[] args)
{
string fn = "Data.inp";
int n = 0;
int [,] a = Doc(fn, ref n);
if (a != null)
{
PrintInput(fn);
Print(a, n);
}
else Console.WriteLine("\n " +
" Khong mo duoc file "+fn);
Console.WriteLine("\n Fini ");
Console.ReadLine();
}
static public int[,] Doc(string fn,
ref int n)
{
if (!File.Exists(fn)) return null;
int [] c = Array.ConvertAll(
File.ReadAllText(fn).
Split(new char[] {' ','\n','\t','\r'},
StringSplitOptions.RemoveEmptyEntries),
new Converter<string,int>(int.Parse));
int k = 0; n = c[k++];
int[,] a = new int[n, n];
for (int i = 0; i < n; ++i)
for (int j = i; j < n; ++j)
a[i,j] = a[j,i] = c[k++];
return a;
}
static void
Print(int [,] a, int n)
Hin th mng 2
chiu a[n,n], t vit
static public void PrintInput(string fn)
Hin th file fn, t vit
} // MangDoiXung
} // SangTao1

Bi 2.14. m tu
1 1 1 1 0 0 1 1 1
0 0 0 0 0 0 1 1 1
Sng to trong Thut ton v Lp trnh Tp I

54



Mt tp vn bn c tn fn c ghi s
mt vng bin hnh ch nht chiu ngang
250 k t, chiu dc (s dng) khng hn
ch. Trn bin c cc con tu hnh ch
nht cha cc k t 1, vng nc c biu th qua cc k t 0. Bit rng cc
con tu khng dnh nhau. Hy m s lng tu.
V d, hnh bn c 5 tu.
Thut ton
V cc tu khng dnh nhau nn ta phn bit cc tu qua mi tu, tc l gc A - gc
Ty-Bc ca tu. Ta c,
s lng tu = s lng mi tu
Mi tu l im nhn gi tr 1 v nu bc mt bc sang tri hoc ln trn s ln
b hoc ri xung bin.
Sau khi m tp ta c v x l tng dng vn bn y v so snh n vi dng x x
l trc . Nu y l dng u tin, tc l dng nm st b Bc, ta khi tr cho x vi 250
ks t 0 tc l ta loi tr trng hp bc ln b Bc. Khi x l y, ta ch tch ring
trng hp tu nm st b Ty, tc l xt ring y[1]. Sau mi ln x l dng y ta copy
dng y sang x v lun gi cho x c chiu di ti a 250 k t nh yu cu ca u bi.

(* Pascal *)
program Ships;
{$B-}
uses crt;
const MN = 250;
boong = '1'; nuoc = '0';
Function Dem(fn: string):
integer;
var
f: text; d,i: integer;
x,y: string;{x:dong tren, y:dong duoi }
begin
Dem := 0; assign(f,fn);
{$I-} reset(f); {$I+}
if IORESULT <> 0 then exit;
x := nuoc;
for i := 1 to 8 do x:= x+x; {x = 00...0}
d := 0;
while NOT EOF(f) do
begin
readln(f,y);
if (y[1]=boong)AND(x[1]=nuoc) then d:=d+1;
for i:=2 to length(y) do
if (y[i]= boong) AND (y[i-1]= nuoc)
AND (x[i]= nuoc) then d:=d+1;
1 1 0 0 0 0 0 0 0
1 1 0 0 1 1 0 0 1
5 tu

A
0 0 0 0 0
B
0 1 1 1 1 1
0 1 1 1 1 1
D
0 0 0 0 0
C

Con tu ABCD

Sng to trong Thut ton v Lp trnh Tp I

55



x := y;
end;
Dem := d;
end;
BEGIN
n:= Dem('TAU.INP');
if n=0 then
write('Khong mo duoc tep/khong co tau')
else write('Tong so tau: ',n);
readln;
END.
// C#
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace SangTao1
{
class Ships
{
static public string fn = "Tau.inp";
static public string gn = "Tau.out";
static public char boong = '1';
static public char nuoc = '0';
static void Main(string[] args)
{
Save(Count());
Test();
Console.WriteLine("\n Fini ");
Console.ReadLine();
}
static public int Count()// dem tau
{
StreamReader f = File.OpenText(fn);
string x = new string(nuoc,251);
string y;
string empty = "";
int d = 0;
while ((y=(f.ReadLine()).Trim())
!= empty)
{
d += Scan(x, y); x = y;
}
f.Close(); return d;
}
// Snh dng tren x vi dng di y
static public int Scan(string x, string y)
{
int d = 0;
if ((y[0]==boong)&&(x[0]==nuoc)) ++d;
for (int i = 1; i < y.Length; ++i)
Sng to trong Thut ton v Lp trnh Tp I

56



if ((y[i]==boong)&&(y[i-1]==nuoc)
&& (x[i]==nuoc)) ++d;
return d;
}
static public void Save(int d) // ghi file
{ File.WriteAllText(gn, d.ToString()); }
static public void Test()
{
Console.WriteLine("\n" +
File.ReadAllText(fn) + "\n");
Console.WriteLine("\n" +
File.ReadAllText(gn) + "\n");
}
} // Ships
} // SangTao1
Bi 2.15. Sp on
Trong mt tp vn bn cha nhng on ct ra t mt trc s. Mi on c dng
<d, c> trong "<" c th l mt trong hai k t ( hoc [, > c th l mt trong
hai k t ) hoc], d v c l cc biu thc dng x hoc x + y hoc x*y vi x v y l
nhng s t nhin. Ta lun c d s c. Chiu di ca on <d, c> l hiu c - d.
Hy sp xp cc on tng theo chiu di v ghi chng vo mt tp vn bn theo
ng dng thc c c ca mi on. C th thm, bt mt s du cch trong
v ngoi cc on. Trn mi dng ca tp lun lun cha trn mt s on.
Th d cho d liu vo trong file input Doan.inp l:
[2+1,7) (4,4*3) (5,6]
Sau khi sp ta c kt qu sau trong file output Doan.out:
(5,6] [2+1,7) (4,4*3)
Thut ton
Ta m t cu trc ca mi on nh sau:
mo so1[toan1 so2] , so3[toan2 so4]
trong :
mo l mt trong hai du m ngoc: ( hoc [.
so1, so2, so3 v so4 l cc s t nhin xut hin trong thnh phn ca
on.
toan1 v toan2 l du cc php ton (+, *), nu c trong thnh phn
ca on.
dong l mt trong hai du ng ngoc: ) hoc].
Trong m t trn, chng ta s dng k php [*] ch ra thnh phn * c th b
qua.
Nu thnh phn th i (i = 1..2) ca on khng c du php ton, th cng khng c
ton hng th hai, tc l thnh phn c dng l mt s t nhin th ta t toan[i] =
BL (du cch).
Nu s th i khng xut hin trong on, ta t so[i] = 0.
Th d:
on mo so1 Toan1 so2 so3 Toan2 so4 dong
Sng to trong Thut ton v Lp trnh Tp I

57



[2+10,7*6) [ 2 + 10 7 * 6 )
[2+10,7) [ 2 + 10 7 BL 0 )
(2,7+5] ( 2 BL 0 7 + 5 ]
Ngoi ra ta thm mt thnh phn len xc nh chiu di ca on. len ca mi
on c tnh theo cng thc sau
len = TriCuoi-TriDau
TriCuoi = so3 Toan2 so4, nu Toan2 l du '+' hoc '-' v
TriCuoi = so3, nu Toan2 = BL.
Tng t,
TriDau = so1 Toan1 so2, nu Toan1 l du '+' hoc '-' v
TriDau = so1, nu Toan1 = BL.
Ta s dng cu trc bn ghi biu din d liu cho mi on:
type
MangSo = array[1..4] of integer; {4 toan hang}
MangToan = array[1..2] of char; {2 toan tu +,*}
KieuDoan = record
mo: char;
dong: char;
so: MangSo;
Toan: MangToan;
len: integer;
end;
Cc on c c s c ghi dn vo mng a vi bin m s phn t n:
type MangDoan = array[0..1000] of KieuDoan;
var a: MangDoan; n: integer;
Khi th tc tnh chiu di len ca mi on s c ci t nh sau:
procedure LenSeg(i: integer);
var dau, cuoi: integer;
begin
with a[i] do
begin
dau := so[1];
if Toan[1]='+' then dau := dau+so[2]
else if Toan[1]='*' then dau:=dau*so[2];
cuoi:=so[3];
if Toan[2]='+' then cuoi:=cuoi+so[2]
else if Toan[2]='*' then cuoi:=cuoi*so[2];
end;
len := cuoi-dau;
end;
Cu trc with x do T cho php ta thc hin thao tc T trn cc thnh phn
ca bn ghi x m khng phi vit li phn tip u x.
c cc on t tp ta s dng mt my trng thi nh sau. Hy tng tng
mt bn b bt kn, do bn phi dng tay nhn bit tng k t trong tp vn bn.
Sng to trong Thut ton v Lp trnh Tp I

58



Mi ln bn s mt k t c no ri da vo k t bn xc nh cc th tc cn thc
hin nhn bit tng i tng. Mun vy ta s dng mt bin gi l bin trng thi q
vi mc ch ghi nhn cc tnh hung gp v trn c s xc nh cc thao tc cn
thit. Gi q l bin trng thi. Trong qu trnh c v x l tp input ta c th gp nm
trng thi nh sau:
q = 0: Trng thi d tm u on: Nu gp k t m u mt on, c th l nu gp
k t c = '(' hoc c = '[' th cn to mt on mi nh sau:
- Tng ch dn ghi nhn on mi: n := n + 1;
- Ghi nhn k t m u on: a[n].mo:= c;
- Khi tr mng s: a[n].so := (0, 0, 0, 0);
- Khi tr mng du cc php ton: a[n].Toan:= (BL, BL);
- Chuyn qua trng thi q := 1 l trng thi tm c so[1].
0: if c in['(','['] then
begin
n:=n+1; a[n].mo:=c;
a[n].so:=KhoiTriSo;
a[n].Toan:=KhoiTriToan;
q:= 1;
end;
Cc bin KhoiTriSo v KhoiTriToan c khai bo v gn tr khi u nh
sau:
const
KhoiTriSo: MangSo = (0,0,0,0);
KhoiTriToan: MangToan = (BL,BL);
q = 1: Trng thi tm c s th nht, so[1]: trng thi ny, nu gp ch s th ta
ghp thm ch s vo so[1], nu gp du php ton th ta hiu l thnh phn th
nht ca on l mt biu thc dng:
so[1] Toan[1] so[2]
Ta ghi nhn du php ton vo trng Toan[1] v chuyn qua trng thi q = 2
c s th hai. Nu gp du phy (,) l du ngn gia hai thnh phn ca on ta
chuyn qua trng thi q = 3 c s u tin ca thnh phn th hai, tc l c
so[3].
1: if c in ChuSo then DocSo(n,1)
else if c in PhepToan then
begin a[n].Toan[1]:=c; q:=2; end
else if c=',' then q:=3;
Th tc DocSo(i,j) nhn thm 1 ch s ghp vo bin a[i].so[j].
q = 2: c s th hai, so[2]: trng thi ny, nu gp ch s th ta ghp thm ch s
vo so[2], nu gp du phy l du ngn gia hai thnh phn ca on ta chuyn
qua trng thi q = 3 c s u tin ca thnh phn th hai, tc l c so[3].
2: if c in ChuSo then DocSo(n,2)
else if c =',' then q:=3;
q = 3: c s th ba, so[3]: trng thi ny, nu gp ch s th ta ghp thm ch s
vo so[3], nu gp du php ton th ta hiu l thnh phn th hai ca on l mt
biu thc dng:
Sng to trong Thut ton v Lp trnh Tp I

59



so[3] Toan[2] so[4]
Ta ghi nhn du php ton vo trng Toan[2] v chuyn qua trng thi q = 4 c
s th t, so[4], nu gp k t c = ')' hoc c = ']' th ta hiu l kt thc mt
on, ta gi th tc KetDoan thc hin cc thao tc sau:
- Ghi nhn k t ng on: a[n].dong:= c.
- Tnh chiu di ca on: LenSeg(n);
- Chuyn qua trng thi q = 0 tip tc vi on tip theo, nu cn.
procedure KetDoan;
begin
a[n].dong:=c; LenSeg(n); q:=0;
end;
on chng trnh th hin trng thi q = 3 khi s nh sau:
3: if c in ChuSo then DocSo(n,3)
else if c in PhepToan then
begin a[n].Toan[2]:=c; q:=4 end
else if c in[')',']'] then KetDoan;
q = 4: c s th t, so[4]: trng thi ny, nu gp ch s th ta ghp thm ch s
vo so[4], nu gp k t c = ')' hoc c = ']' th ta hiu l kt thc mt
on, ta gi th tc KetDoan.
4: if c in ChuSo then DocSo(n,4)
else if c in[')',']'] then KetDoan;
c tp xong ta dng th tc qsort sp cc on tng dn theo chiu di. Sau khi
sp ta ghi cc on vo tp gn theo cc trng.
(* Pascal *)
{$B-}
program Segments;
uses crt;
const
fn = 'DOAN.INP'; {Tep input}
gn = 'DOAN.OUT';{Tep output}
MN = 1000; {So luong toi da cac doan}
BL = #32;{Dau cach}
ChuSo = ['0'..'9'];
PhepToan = ['+','*'];
type
MangSo = array[1..4] of integer;
MangToan = array[1..2] of char;
KieuDoan = record
mo: char; {dau mo ngoac}
dong: char; {dau dong ngoac}
so: MangSo; {4 so trong doan}
Toan: MangToan; {2 phep toan}
len: integer; {chieu dai doan}
Sng to trong Thut ton v Lp trnh Tp I

60



end;
MangDoan = array[0..MN] of KieuDoan;
const
KhoiTriSo: MangSo = (0,0,0,0);
KhoiTriToan: MangToan = (BL,BL);
var
f,g:text;
a: MangDoan;
c: char;{ky tu dang xet}
n: integer;{chi so doan dang xet}
q: integer;{bien trang thai}
(*---------------------------------
Cac trang thai q = 0: do tim dau doan
1: doc so[1]
2: doc so[2]
3: doc so[3]
4: doc so[4]
-----------------------------------*)
procedure LenSeg(i: integer); t vit
procedure KetDoan; t vit
(*-----------------------------------------
Them 1 chu so vao so thu j cua doan i
------------------------------------------*)
procedure DocSo(i,j: integer);
begin
a[i].so[j]:=a[i].so[j]*10+(ord(c)-ord('0'))
end;
(*--------------------------------------
Doc cac doan
---------------------------------------*)
procedure doc;
begin
assign(f,fn); reset(f);
q:=0; n:=0;
while not eof(f) do
begin
read(f,c);
case q of
0: if c in['(','['] then
begin
n:=n+1; a[n].mo:=c;
a[n].so:=KhoiTriSo;
a[n].Toan:=KhoiTriToan;
q:=1;
end;
Sng to trong Thut ton v Lp trnh Tp I

61



1: if c in ChuSo then DocSo(n,1)
else if c in PhepToan then
begin a[n].Toan[1]:=c; q:=2 end
else if c=',' then q:=3;
2: if c in ChuSo then DocSo(n,2)
else if c =',' then q:=3;
3: if c in ChuSo then DocSo(n,3)
else if c in PhepToan then
begin
a[n].Toan[2]:=c; q:=4;
end
else if c in[')',']'] then KetDoan;
4: if c in ChuSo then DocSo(n,4)
else if c in [')',']'] then KetDoan;
end; { case }
end; { while }
close(f);
end;
procedure qsort(d,c:integer);
var i,j,m: integer;
x: KieuDoan;
begin
i:=d; j:=c; m:=a[(i+j) div 2].len;
while i<=j do
begin
while a[i].len < m do i:=i+1;
while a[j].len > m do j:=j-1;
if i<=j then
begin
x:=a[i]; a[i]:=a[j]; a[j]:= x;
i:=i+1; j:=j-1;
end;
end;
if d < j then qsort(d,j);
if i < c then qsort(i,c);
end;
procedure Ghi;
var i: integer;
begin
assign(g,gn); rewrite(g);
for i:=1 to n do
with a[i] do
begin
if Toan[1]<>BL then
write(g,mo, so[1],Toan[1],so[2])
Sng to trong Thut ton v Lp trnh Tp I

62



else write(g,mo, so[1]);
if Toan[2]<>BL then
write(g,',',so[3],Toan[2],so[4],dong,BL)
else write(g,',',so[3],dong,BL);
{ moi dong viet 10 doan }
if i mod 10 = 0 then writeln(g);
end;
close(g);
end;
BEGIN
Doc; qsort(1,n); Ghi;
END.
// C#
using System;
using System.IO;
using System.Collections;
namespace SangTao1
{
class SapDoan
{
static public string fn = "Doan.inp";
static public string gn = "Doan.out";
static public string s; // du lieu vao
static public Doan[] d = new Doan[5000]; // cac doan
static public int n = 0; // so luong doan
static public char Ket = '#';
static void Main(string[] args)
{
s = File.ReadAllText(fn) + Ket.ToString();
Console.WriteLine("\n Du lieu " +
"truoc khi xu li:\n " + s);
n = DocDoan();
Console.WriteLine("\n Tong cong " + n + " Doan");
Console.WriteLine(n); Printd();
QSort(d, 0, n-1);
Console.WriteLine("\n Da sap: "); Printd();
Ghi(); XemLai();
Console.WriteLine("\n Fini ");
Console.ReadLine();
}
static public void XemLai()
{
Console.WriteLine("\n Kiem tra lai:\n");
Console.WriteLine("\n Input:\n" +
File.ReadAllText(fn));
Console.WriteLine("\n Output:\n" +
File.ReadAllText(gn));
}
static public int DocDoan()
{
Sng to trong Thut ton v Lp trnh Tp I

63



int n = -1;
int q = 0; // trang thai
int i = 0; // bien tro trong s
int dau, cuoi;
for (; s[i] != Ket; ++i)
{
switch(q)
{
case 0: // Tim dau doan
if (GapMo(s[i]))
{
++n; d[n] = new Doan();
d[n].Mo = s[i]; q = 1;
}
break;
case 1: // Doc so1
if (GapSo(s[i]))
d[n].So1 = DocSo(ref i);
else if (GapToan(s[i]))
{d[n].Toan1 = s[i]; q = 2;}
else if (s[i]==',') q = 3;
break;
case 2: // Doc so2
if (GapSo(s[i]))
d[n].So2 = DocSo(ref i);
else if (s[i]==',') q = 3;
break;
case 3: // Doc so3
if (GapSo(s[i]))
d[n].So3 = DocSo(ref i);
else if (GapToan(s[i]))
{
d[n].Toan2 = s[i]; q = 4;
}
else if (GapDong(s[i]))
q = 5;
break;
case 4: // Doc so4
if (GapSo(s[i]))
d[n].So4 = DocSo(ref i);
else if (GapDong(s[i]))
q = 5;
break;
case 5: // Xong 1 doan
d[n].Dong = s[--i];
dau = d[n].So1;
if (d[n].Toan1 == '+')
dau += d[n].So2;
else if (d[n].Toan1 == '*')
dau *= d[n].So2;
cuoi = d[n].So3;
if (d[n].Toan2 == '+')
cuoi += d[n].So4;
Sng to trong Thut ton v Lp trnh Tp I

64



else if (d[n].Toan2 == '*')
cuoi *= d[n].So4;
d[n].Len = cuoi-dau;
Console.Write("\n Doan "+
n + ". ");
d[n].Print(); q = 0; break;
}
} // endfor
return (++n);
}
static public bool GapSo(char c)
{ return (c >= '0' && c <= '9'); }
static public bool GapMo(char c)
{ return (c == '(' || c== '['); }
static public bool GapDong(char c)
{ return (c == ')' || c== ']'); }
static public bool GapToan(char c)
{ return (c == '+' || c== '*'); }
static public int DocSo(ref int i)
{
int m = 0;
do
{ m = m * 10 + s[i++] - '0';
} while (GapSo(s[i]));
--i;
return m;
}
static public void Printd()
{ for (int i = 0;i < n; ++i) d[i].Print(); }
static public void Ghi()
{
StreamWriter g = File.CreateText(gn);
for (int i = 0; i < n; ++i) d[i].FWrite(g);
g.Close();
}
static public void QSort(Doan[] d,int s, int e)
{
int i = s, j = e, m = d[(i+j)/2].Len;
Doan t;
while (i <= j)
{
while (d[i].Len < m) ++i;
while (d[j].Len > m) --j;
if (i <= j)
{
t = d[i]; d[i] = d[j]; d[j] = t;
++i; --j;
}
}
if (s < j) QSort(d,s,i);
if (i < e) QSort(d,i,e);
}
} // SapDoan
Sng to trong Thut ton v Lp trnh Tp I

65




public class Doan
{
public char Mo;
public char Dong;
public int So1;
public int So2;
public int So3;
public int So4;
public char Toan1;
public char Toan2;
public int Len;
public Doan()
{
Mo = '<'; Dong = '>';
So1 = So2 = So3 = So4 = 0;
Toan1 = Toan2 = '#';
Len = 0;
}
public void FWrite(StreamWriter g)
{
g.Write(Mo.ToString());
if (Toan1 != '#')
g.Write(So1 + Toan1.ToString() + So2);
else g.Write(So1);
g.Write(",");
if (Toan2 != '#')
g.Write(So3 + Toan2.ToString() + So4);
else g.Write(So3);
g.WriteLine(Dong.ToString());
}
public void Print()
{
Console.Write(Mo.ToString());
if(Toan1!='#')
Console.Write(So1+Toan1.ToString()+So2);
else Console.Write(So1);
Console.Write(",");
if(Toan2!='#')
Console.Write(So3+Toan2.ToString()+So4);
else Console.Write(So3);
Console.WriteLine(Dong.ToString()+
" Len = "+Len);
} // Print
} // Doan
} // SangTao1



Sng to trong Thut ton v Lp trnh Tp I

66



CHNG 3
BN PHM V MN HNH





Bi 3.1. Bng m ASCII
Sinh tp c tn ASCII.DAT cha m ASCII tin dng.
Ch
ASCII (c l a-ski) l b m chun dng trong trao i thng tin ca M v u tin
c ci t trong cc my tnh s dng h iu hnh MS-DOS. Trong bng m ny, mi
k t c mt m s ring bit chim 1 byte. Trong TP Ta vit 65 l biu th m s 65,
vit #65 l biu th k t c m s 65, tc l ch 'A'. Cc k t mang m s t 0 n
31 l cc k t iu khin, th d, k t #13 iu khin con tr vn bn xung dng mi,
k t #10 iu khin con tr vn bn v u dng. Nh vy, xu k t #13#10 s iu
khin con tr v u dng mi v do lnh write(#13#10) s tng ng vi lnh
writeln. Lnh writeln(#13#10) s tng ng vi hai lnh writeln;
writeln.
Chng trnh di y ghi vo tp vn bn c tn ASCII.DAT cc k t v m ca
chng. Tt c c 256 k t chia lm hai phn. 128 k t u tin m s t 0 n 127 l
cc k t c s, 128 k t cn li, m s t 128 n 255 l cc k t m rng.
Sau khi thc hin chng trnh, bn c th m tp ASCII.DAT xem tng k t
v m ca chng. Lu rng c k t hin th c v c k t khng hin th c trn
mn hnh, chng hn nh cc k t iu khin.
(* Pascal *)
program ASCII;
uses crt;
procedure ASCII;
var f: text; i: byte;
begin
assign(f,'ASCII.DAT');
rewrite(f);
for i := 0 to 255 do
Sng to trong Thut ton v Lp trnh Tp I

67



begin
write(f,chr(i), ': ',i:3,' ');
if i mod 5 = 0 then writeln(f);
end;
close(f);
writeln('OK'); readln;
end;
BEGIN
ASCII;
END.
// C#
Chng trnh di y lu li m ca 128 k t u tin ng vi phn c s ca
bng m ASCII. Cc k t phn m rng ph thuc vo tng phin bn ci t ca cc
h iu hnh.
using System;
using System.IO;
namespace SangTao1
{
class ASCII
{
static void Main()
{
string fn = "ASCII.TXT";
StreamWriter g = File.CreateText(fn);
for (int i = 0; i < 128; ++i)
g.WriteLine("{0}: {1}", i, (char)i);
g.Close();
Console.WriteLine(File.
ReadAllText(fn)); // Doc lai
Console.ReadLine();
}
} // class
} // space
Bi 3.2. B T l kh
Lp chng trnh hin th trn mn hnh cc qun bi T l kh gm R, C,
Pch, Nhp theo quy nh qun A mang m s 1 v c 1 hnh n v, cc qun
m s i t 2 n 10 c i hnh n v, cc qun J, Q v K ln lt c 11, 12 v
13 hnh n v tng ng. Hnh n v gm bn loi k t c m ASCII tng
ng nh sau:
+ (R) : #4, v (C) : #3, + (Pch): #6, + (Nhp): #5.
8 A Q
+
+
+
v
+
+ + +
+ + + +
+ +
+

+ + +
+ + + +
+ + + +
Sng to trong Thut ton v Lp trnh Tp I

68



8 A Q

Ba qun bi T l kh
Gi
Trc ht ta cn thng nht mt s quy nh sau:
Qun bi c v bng mt mu M ty chn.
Nu l qun R hoc C ta t mu ch l (RED), vi cc qun Pch v
Nhp ta t mu ch l en (BLACK).
Mi qun bi c hai thuc tnh l loi (R, C, Pch hoc Nhp) v m s. M
s ca qun A l 1, J l 11, Q l 12 v K l 13. Cc qun cn li mang m s
t 2 n 10 ng vi s ghi trn qun bi .
Trn nn cc qun bi J, Q v K khng v hnh ngi m v s lng hnh n
v (R, C, Pch hoc Nhp) tng ng vi m s ca qun .
b tr s lng hnh n v trn mi qun bi cho cn i ta cn 5 dng. Th tc
Dong(q:char;s:string;x,y:byte) v 5 dng cha hnh n v loi q, bt u
tnh t to (x, y) ng vi v tr gc trn tri ca qun bi trn mn hnh, theo du hiu ghi
trong xu mu s. Th d, li gi vi xu mu s = '20302' s v 5 dng th hin cho qun
mang m s 7 thuc loi v (R, C, Pch hoc Nhp) nh sau:
1. Dng th nht c 2 k t v.
2. Dng th hai c 0 k t v tc l trng.
3. Dng th ba c 3 k t v.
4. Dng th t c 0 k t v tc l trng.
5. Dng th nm c 2 k t v.
V trong xu mu s tng cng c 2 + 3 + 2 = 7 k t v nn qun bi mang m s 7.
procedure Dong(v: char;s: string;x,y: byte);
var i: byte;
begin
x := x+3; y := y+TY;
for i := 1 to 5 do
begin
gotoxy(x,y);
case s[i] of
'1': write(BL,BL,v,BL,BL);
'2': write(v,BL,BL,BL,v);
'3': write(v,BL,v,BL,v);
end;
y := y+TY;
end;
end;
Cc mu dng s c tnh ton trc v khi tr nh sau:
MauDong: array[1..13] of string[5] =
('00100', '01010', '10101', '20002', '20102',
'20202', '20302', '21212', '30303', '22222',
'22322', '23232', '23332');
Ta d dng nhn ra c tt c 13 mu dng ng vi 13 m s 1(A), 2,..., 10, 11(J), 12(Q)
v 13(K). Tm li mu dng th i cho ta phng thc v i hnh n v trn qun bi mang
m s i. Mi mu dng c biu din qua mt xu 5 k t.
Sng to trong Thut ton v Lp trnh Tp I

69



Cc th tc iu khin mn hnh c ngha nh sau:
gotoxy(x,y): Chuyn con tr mn hnh n ct x dng y.
TextColor(c): t mu c cho nt ch. Th d, k t sau khi gp lnh
TextColor(BLACK) cc k t xut hin trn mn hnh s c nt mu en,
TextBackGround(m): t mu m cho nn ch. Th d, k t sau khi gp lnh
TextBackGround(WHITE) cc k t s c vit trn nn trng.
textattr: Bin h thng c gi tr 1 byte, tnh t phi qua tri, 4 bit u tin (gi l
cc bit thp) to thnh mt s nguyn th hin mu cho nt ch, 4 bit tip theo (gi l cc bit
cao) th hin mu cho nn ch. Th d php gn textattr:=7 s c nhn gi tr nh
phn l (0000)(0111) v do h thng s t mu nt ch l 7 (mu trng) v mu nn
ch l 0 (mu en). Nh vy php gn trn tng ng vi t hp ca hai lnh
TextColor v TextBackGround.
Lnh write(a:m) hin th n v d liu a vi rng m v tr. Nu chiu di d
liu ca a nh hn m th h thng t ng in thm du cch cho m v tr. Nu chiu di
d liu ca a ln hn m th h thng hin th v tr cho a. Th d, lnh
write(BL:20)s hin th 20 du cch trn mn hnh.
V mn hnh trong h iu hnh Windows c phn gii cao, khc vi mn hnh vn
bn trong DOS nn th tc VeBai c ci t vi tham s iu khin Kieu quy nh kiu
ca h iu hnh. Kieu = Wind s hin th b bi trong ch Windows, Kieu =
DOS s hin th b bi trong ch mn hnh DOS. Hai kiu ch khc nhau mt gi tr
cn khi tr cho vi tham s, c th l:
Kch thc qun bi. Nu coi mi qun bi nh mt hnh ch nht th DX l chiu rng,
DY l chiu di.
gin dng TX. Khi hin th trn mn hnh Windows th ta cch hai dng, TX =
2, ngc li, trn mn hnh DOS ta t TX = 1.
Bng di y m t cc tham s cn khi tr cho hai mi trng WINDOWS v DOS.
WINDOWS DOS
DX 9 9
DY 12 6
TX 2 1
Cc tham s kch thc qun bi DX DY v gin cch
dng TX
trong mi trng WINDOWS v DOS.
(* Pascal *)
uses crt;
const
CO = #3; RO = #4; NHEP = #5; PIC = #6;
WIND = 1; DOS = 2; BL = #32;
DX: byte = 9;
DY: byte = 12; {kich thuoc quan bai}
TY: byte = 2;
MauDong: array[1..13] of string[5] = ('00100',
'01010',
'10101',
'20002',
'20102',
Sng to trong Thut ton v Lp trnh Tp I

70



'20202',
'20302',
'21212',
'30303',
'22222',
'22322',
'23232',
'23332');
Nhan: array[1..13] of string[2]
= ('A','2','3','4','5',
'6','7','8',9', 10',
'J','Q','K');
procedure Dong(q: char;s: string;x,y: byte); t vit
{---------------------------------
Ve nen mau M cho quan bai
tai vi tri goc tren trai (x,y)
--------------------------------}
procedure Nen(M,x,y: byte);
var i: byte;
begin
TextBackGround(M);
for i:= 0 to DY do
begin
gotoxy(x+1,y+i);
write(BL:DX);
end;
end;
{----------------------------------------------
Ve 1 quan bai kieu q (ro, co, bich, nhep);
so n (2 ... 10; 1 = A; 11 = J; 12 = Q; 13 = K)
goc Tay-Bac tai cot x, dong y cua man hinh,
---------------------------------------------}
procedure VeQuanBai(q: char; n, x, y: byte);
var i, j: byte;
begin {VeQuanBai}
if (q = RO) OR (q = CO) then TextColor(RED)
else TextColor(BLACK);
Nen(WHITE,x,y);
Dong(q,MauDong[n],x,y);
{viet so}
gotoxy(x+1,y+1); write(Nhan[n]:2);
gotoxy(x+DX-1,y+DY-1); write(Nhan[n]);
end;
Procedure VeBai(Kieu: byte);
var i: integer;
begin
if Kieu = DOS then
begin
DY:= 6;
TY:= 1;
end else
if Kieu = WIND then
begin
Sng to trong Thut ton v Lp trnh Tp I

71



DY:= 12;
TY:= 2;
end else
begin
writeln('Dat kieu khong dung');
write('Cach goi thu tuc: ');
writeln('VeBai(WIND) hoac VeBai(DOS)');
readln; halt;
end;
textbackground(BLUE); clrscr;
for i := 1 to 13 do {Ve bo Tu lo kho}
begin
VeQuanBai(RO,i,5,10);
VeQuanBai(CO,i,20,10);
VeQuanBai(PIC,i,35,10);
VeQuanBai(NHEP,i,50,10);
if ReadKey=#27 then halt;
end;
textattr:= 7; clrscr;
end;
BEGIN
VeBai(WIND);
END.
// C#
using System;
using System.IO;
namespace SangTao1
{
/*-------------------------------
* Bo bai Tulokho
* -----------------------------*/
class TuLoKho
{
static void Main()
{
BoBai b = new BoBai();
b.Draw(6, 4);
Console.ReadLine();
}
} // Class

/*-----------------------------------
* Mo ta bo bai Tulokho
* ---------------------------------*/
class BoBai
{
private char CO = (char)3;
private char RO = (char)4;
private char NHEP = (char)5;
private char PIC = (char)6;
Sng to trong Thut ton v Lp trnh Tp I

72



const int DX = 9;
const int DY = 6;// kich thuoc quan bai
// 1 khoang cach giua 2 dong
const int TY = 1;
const int SOQUAN = 13;
private string[] MauDong = {"00100",
"01010",
"10101",
"20002",
"20102",
"20202",
"20302",
"21212",
"30303",
"22222",
"22322",
"23232",
"23332" };
private string[] Nhan = {"A","2","3","4","5","6","7",
"8","9","10","J","Q","K"};
// Dat mau nen va text cho man hinh
private void SetColors(ConsoleColor bg, ConsoleColor fg)
{
Console.BackgroundColor = bg;
Console.ForegroundColor = fg;
}
// Viet s tai cot x, dong y
private void WriteAt(string s, int x, int y)
{
Console.SetCursorPosition(x, y);
Console.Write(s);
} // WriteAt
// Ve bo bai tai vi tri x, y
public void Draw(int x, int y)
{
int DD = DX + 10;
Console.BackgroundColor =
ConsoleColor.Blue;
Console.Clear();
for (int i = 0; i < SOQUAN; ++i)
{
VeQuanBai(RO, i, x, y);
VeQuanBai(CO, i, x + DD, y);
VeQuanBai(PIC, i, x + 2 * DD, y);
VeQuanBai(NHEP, i, x + 3 * DD, y);
Console.ReadLine();
}
Console.ResetColor(); // tra lai nen cu
} // Draw
/*--------------------------------------
Ve 5 dong trong quan bai
--------------------------------------*/
private void Lines(char q, string s,
Sng to trong Thut ton v Lp trnh Tp I

73



int x, int y)
{
const string BL = " ";
string qs = q.ToString();
x += 3;
for (int i = 0; i < 5; ++i)
{
y += TY;
Console.SetCursorPosition(x, y);
switch (s[i])
{
case '1':
Console.WriteLine(BL + BL + qs + BL + BL);
break;
case '2':
Console.WriteLine(qs + BL + BL + BL + qs);
break;
case '3':
Console.WriteLine(qs + BL + qs + BL + qs);
break;
} // switch
} // for
}
// Dat mau nen cho quan bai
private void Nen(ConsoleColor m,
int x, int y)
{
string s = new string(' ', DX);
Console.BackgroundColor = m;
for (int i = 0; i <= DY; ++i)
WriteAt(s, x + 1, y + i);
}
/*--------------------------------------------
Ve 1 quan bai kieu q (ro, co, bich, nhep);
so n (1 ... 10; 0 = A; 10 = J; 11 = Q; 12 = K)
goc Tay-Bac tai cot x, dong y cua man hinh,
--------------------------------------------*/
private void VeQuanBai(char q, int n, int x, int
y)
{
// Chon mau chu RO, CO: mau do
// PIC, NHEP: mau den
Console.ForegroundColor =
(q == RO || q == CO)
? ConsoleColor.Red
: ConsoleColor.Black;
// Dat nen quan bai mau trang
Nen(ConsoleColor.White, x, y);
// Ve 5 dong
Lines(q, MauDong[n], x, y);
// Viet so o goc tren-trai
Sng to trong Thut ton v Lp trnh Tp I

74



WriteAt(Nhan[n], x + 2, y);// + 1);
// Viet so o goc duoi-phai
if (n == 9)
WriteAt(Nhan[n], x + DX - 2, y + DY );
else WriteAt(Nhan[n], x + DX - 1, y + DY );
} // VeQuanBai
} // TuLoKho
} // SangTao1
Ch thch
Cc tham s x, y v DX, DY ph thuc vo phn gii mn hnh. Bn cn iu
chnh cc tham s ny cho ph hp vi ch phn gii mn hnh chn.
Bi 3.3. Hm GetKey
Mi khi ta nhn mt phm, trong vng m 2 byte s c np 1 hoc 2 byte tu
theo kiu phm nhn. Nu l phm thng nh a, b, c, %, $,... trong vng m s
c np 1 byte cha m ASCII ca k t tng ng. Nu ta nhn phm m rng
nh F1,..., F10, cc phm dch chuyn con tr, |, , , +, Ins (chn), Del (xo),
PageUp/PgUp (ln mt trang), PageDown/PgDn (xung mt trang),... trong vng
m s c np hai byte, byte th nht c gi tr 0, byte th hai cha m ring
ca phm nhn. M ring ny c th trng vi m ca cc k t thng. Th d,
khi ta nhn phm m rng F10 trong vng m s c np 2 byte (0, 68). M
ring 68 trng vi m ca k t D. Hm ReadKey cho ta k t ca phm nhn v
khng hin th k t (trn mn hnh), ta gi l hm nhn thm mt k t.
ReadKey trc ht kim tra vng m bn phm xem cn byte no cha c c
khng. Nu cn, ReadKey s c byte . Ngc li, nu vng m trng, ReadKey
s ch ta nhn mt phm ri sau c 1 byte t vng m.
Hy vit hm GetKey cho ra m ASCII ca phm thng nhn v cho ra m
ring ca phm m rng cng thm 128 nhm phn bit c phm thng vi
phm m rng.
Ch : Hm GetKey bi 3.3 cho m ca mt s phm m rng dng iu
khin con tr mn hnh nh sau:
LEN: 200 Mi tn tr ln |
XUONG: 208 Mi tn tr xung +
PHAI: 205 Mi tn tr qua phi
TRAI: 203 Mi tn tr qua tri
ESC (27) v ENTER/RETURN (13) l nhng phm thng.
Gi
Trc ht gi hm c:= ReadKey ri kim tra gi tr ca k t c. Nu c c m 0
tc l nhn phm m rng, ta cn c tip byte th hai v gn cho hm gi tr ca
byte cng thm du hiu nhn bit phm m rng l 128. Nu c c m khc 0, ta gn
cho hm gi tr .
(* Pascal *)
(* -----------------------
Ham GetKey
-------------------------*)
program Conio;
Sng to trong Thut ton v Lp trnh Tp I

75



uses crt;
const Esc = 27;
Function GetKey: integer;
var c: char;
begin
c:= ReadKey;
if c <> #0 then GetKey := Ord(c)
else GetKey := Ord(ReadKey) + 128;
end;
Procedure Test;
var k: integer;
begin
repeat
write(' Nhan Phim (Bam ESC de thoat): ');
k:= GetKey;
if k > 128 then
writeln(' Phim mo rong (0, ',k-128,') ==> ',k)
else
writeln(' Phim thuong ',chr(k), '(',k,')');
until k = Esc;
readln;
end;
BEGIN
Test;
END.
Bi 3.4. Tr chi 15
C 15 qun c c nh m s t 1 n 15 c t trong mt bn c hnh vung 4
4 theo hnh trng ban u nh rong hnh . Mi bc i, ta c php di chuyn
mt qun nm cnh trng vo trong trng.
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15
Tr chi 15
Vit chng trnh thc hin hai chc nng sau y:
a) o ngu nhin cc qun c chuyn t hnh trng ban u v mt hnh trng
H no .
b) Nhn phm iu khin ca ngi chi ri di chuyn qun c theo phm . Khi
no ngi chi t c hnh trng ban u th kt thc mt vn.
Tr chi ny c tn l Tr chi 15, tng ni ting th k XIX nh tr chi Rubic
thi i chng ta vy.
Gi
Sng to trong Thut ton v Lp trnh Tp I

76



Tr chi ny kh d lp trnh. Bn cn lu s khc bit gia v tr ca phn t a[i, j]
trong ma trn a vi v tr hin th ca n trn mn hnh, v th tc gotoxy(i, j) a con tr
mn hnh n ct i, dng j trong khi a[i, j] li truy cp ti dng (i) v ct (j). S khc bit
ny c tnh n trong th tc Den (n - chuyn con tr n v tr thch hp hin th
phn t a[i, j]).
Mng b cha hnh trng ban u ca bn c v dng kim tra xem mng a c
trng vi hnh trng ny khng (xem hm lgic Dung).
Hai th tc DaoNgauNhien v Game15 u cng gi n th tc Chuyen(k) -
dch chuyn mt trong bn qun st vi trng vo trng. Ta quy c chn cc gi tr
ca k l:
0: Ln - chuyn qun nm st di trng vo trng.
1: Xung - chuyn qun nm st trn trng vo trng.
2: Phi - chuyn qun nm st tri trng vo trng.
3: Tri - chuyn qun nm st phi trng vo trng.
ng nhin, nu trng nm st ng bin th c th c trng hp khng
chuyn c.
Ta phn bit phn t (i, j) ca mng a vi v tr hin th gi tr a[i, j] ca phn t
trn mn hnh nh sau. Gi (x, y) l v tr gc trn tri ca vng hin th, dx v dy l
chiu di hai cnh ca s hin th gi tr a[i, j], khi th tc Den(i,j) di y
chuyn con tr mn hnh n v tr hin th c m t nh sau:
procedure Den(i,j: byte);
begin
Gotoxy(y+(j-1)*dy,x+(i-1)*dx);
end;
Khi th tc Viet(i,j: byte)vit gi tr a[i, j] vo tng ng trn mn
hnh s thc hin cc thao tc sau. Trc ht cn chuyn con tr mn hnh n v tr cn
vit bng th tc Den(i,j). Sau xt a[i, j]. Nu l trng (a[i, j] = 0) th xo
, ngc li ta ghi gi tr ca a[i, j] vo cn hin th.
procedure Viet(i,j: byte);
begin
Den(i,j);
if a [i,j] = 0 then
begin
TextBackGround(YELLOW);
write(BL:2);
TextBackGround(BLUE);
end
else write(a [i,j]:2);
end;
Khi khi ng chng trnh s hin th tr chi v tin hnh o ngu nhin cc qun c
cho n khi ngi chi nhn mt phm ty . T thi im , ngi chi s tm cch di
chuyn cc qun c t ti hnh trng ban u.
(* Pascal *)
(*----------------------
Game 15
-----------------------*)
uses crt;
const
Sng to trong Thut ton v Lp trnh Tp I

77



BL = #32;
DD = 4;
x = 2; y = 3; {Goc Tay-Bac cua ban co}
dx = 2; dy = 3; {Khoang cach giua cac o}
{cac ma dich chuyen con tro}
LEN = 200;
XUONG = 208;
PHAI = 205;
TRAI = 203;
var
a, b: array [1..DD,1..DD] of byte; {ban co}
xx, yy: byte; {Toa do cua con tro}

{------------------------
Nhan tham 1 ki tu
-------------------------}
Function GetKey: integer;
var c: char;
begin
c:= ReadKey;
if c <> #0 then GetKey:= Ord(c)
else begin
c:= ReadKey;
GetKey:= Ord(c) + 128;
end;
end;
{-------------------------
Chuyen con tro man hinh
den vi tri hien thi
quan co (i,j)
--------------------------}
procedure Den(i,j: byte);
begin
Gotoxy(y+(j-1)*dy,x+(i-1)*dx);
end;
{-----------------------------
Viet gia tri cua quan co
a[i,j] vao o tuong ung
------------------------------}
procedure Viet(i,j: byte);
begin
Den(i,j);
if a[i,j] = 0 then
begin
TextBackGround(YELLOW);
write(BL:2);
TextBackGround(BLUE);
end
else write(a[i,j]:2);
end;
{-------------------------------
Khoi tri:
1. Dat mau chu, mau nen
Sng to trong Thut ton v Lp trnh Tp I

78



2. Ve ban co
-------------------------------}
procedure Init;
var i, j, k: byte;
begin k := 0;
{nen ngoai mau vang}
TextBackGround(YELLOW);
Gotoxy(1,1);
{ Ve cac o trong }
for i:= 1 to dx*DD+1 do
begin
for j := 1 to dy*DD+3 do write(BL);
writeln;
end;
TextBackGround(BLUE); {nen ban co mau xanh}
TextColor(WHITE); {chu trang}
{Khoi tri va hien thi cac quan co}
for i:= 1 to DD do
for j:= 1 to DD do
begin
inc(k); a[i,j]:= k;
b[i,j]:= k; Viet(i,j);
end;
a[DD,DD]:= 0; b[DD,DD]:= 0;
Viet(DD,DD); Den(DD,DD);
xx:= DD; yy:= DD;
end;
{------------------------------
Di chuyen quan co a[xx,yy]
vao o trong ke no
-------------------------------}
procedure Chuyen(k: integer);
begin
case k of
0: {LEN}
if xx < DD then
begin
a[xx,yy]:= a[xx+1,yy];
Viet(xx,yy);
inc(xx); a[xx,yy]:= 0;
Viet(xx,yy);
end;
1: {XUONG}
if xx > 1 then
begin
a[xx,yy]:= a[xx-1,yy];
Viet(xx,yy);
dec(xx); a[xx,yy]:= 0;
Viet(xx,yy);
end;
2: {PHAI}
if yy > 1 then
begin
Sng to trong Thut ton v Lp trnh Tp I

79



a[xx,yy]:= a[xx,yy-1];
Viet(xx,yy);
dec(yy); a[xx,yy]:= 0;
Viet(xx,yy);
end;
3: {TRAI}
if yy < DD then
begin
a[xx,yy]:= a[xx,yy+1];
Viet(xx,yy);
inc(yy); a[xx,yy]:= 0;
Viet(xx,yy);
end;
end;
end;
{-----------------------------
Dao ngau nhien cac quan co
------------------------------}
procedure DaoNgauNhien;
var c: integer;
begin
repeat
Chuyen(random(4));
Delay(50); {Dat do tre de kip quan sat}
until KeyPressed;
c:= GetKey;
end;
{--------------------------
Kiem tra ban co a co
trung voi cau hinh chuan ?
----------------------------}
function Dung: Boolean;
var i, j: byte;
begin
Dung:= FALSE;
for i:= 1 to DD do
for j:= 1 to DD do
if (a[i,j] <> b[i,j]) then exit;
Dung:= TRUE;
end;
procedure Game15;
var k: integer;
d, v: longint;
sx, sy, ex, ey: byte;
begin
Randomize;
ClrScr; d:= 0; v:= 1;
TextBackGround(BLUE);
TextBackGround(BLUE);
TextColor(WHITE);
Init;
gotoxy(5,25); clreol;
write(' Van: ');
Sng to trong Thut ton v Lp trnh Tp I

80



sx:= Wherex; sy:= Wherey;
write(v); write(' Tong so buoc: ');
ex:= Wherex; ey:= Wherey;
DaoNgauNhien;
repeat
gotoxy(sx,sy); write(BL:10);
gotoxy(sx,sy); write(v);
gotoxy(ex,ey); clreol; {xoa cho den het dong}
gotoxy(ex,ey); write(d);
Den(xx,yy);
k:= GetKey;
case k of
LEN: k:= 0;
XUONG: k:= 1;
PHAI: k:= 2;
TRAI: k:= 3;
end;
Chuyen(k); inc(d);
if Dung then
begin
DaoNgauNhien;
inc(v); d:= 0;
gotoxy(sx,sy); write(BL:10);
gotoxy(sx,sy); write(v);
end;
until UpCase(chr(k)) in [#27, 'Q'];
Textattr := 7; clrscr;
end;
BEGIN
Game15;
END.
Bi 3.5. Bng nhy
Bng nhy bc b, bc k l mt tm bng c c tnh k l sau y: nu bn vit
ln lt ln bng n s nguyn th sau khi vit s th i, s th (i b) vit trc
s c tng thm k n v m ta gi l nhy s.
Vi mi cp s nguyn dng b v k cho trc hy lp trnh bin mn hnh
my tnh ca bn thnh mt bng nhy sau th vit ln tm bng
nhn c dy N s t nhin u tin 1 2 ... N vi mi N cho trc.
Th d, thu c dy s 1 2 ... 10 trn bng nhy bc b = 3 bc k = 6 bn
cn vit dy s sau:
-5 -4 -3 -2 -1 0 1 8 9 10
Gi
Vi mi bc b ta cn lu li b gi tr np trc trong on a[0..b-1] ca mng a
ng thi vi v tr hin th trn mn hnh ca cc gi tr trong cc mng tng ng x v
y. Ta s dng s hc ng d cho vic lu tr ny, c th l khi cn np phn t th i trc
ht ta np vo mt bin m z. Sau ta tng phn t a[i mod b] thm k n v v tm n
ct x[i mod b], dng y[i mod b] cp nht li gi tr ny. Cui cng ta chuyn gi tr z vo
a[i mod b]. Ni cch khc ta x l vng m a[0..(b - 1)] theo nguyn tc vng trn. Cc chi
tit x l mn hnh trong trng hp chuyn dng v cun mn hnh khi thao tc dng cui
mn hnh l n gin v c ch r trong chng trnh
Sng to trong Thut ton v Lp trnh Tp I

81



(* Pascal *)
uses crt;
const
MN = 50;
d = 6; {chieu dai cua moi so}
ML = 12; {so luong tren mot dong}
LIM = d*ML; BL = #32;
W = 500; {kich thuoc toi da cua bang nhay}
var
a: array [0..MN] of integer; {vung dem}
{toa do con tro man hinh}
x, y: array [0..MN] of byte;
{-------------------------------
Viet n so tren bang nhay bac k buoc b
---------------------------------}
procedure BangNhay(b,k,n: integer);
var i, j, z, t: integer;
xx, yy: byte; {vi tri con tro}
begin
textattr := 7; clrscr;
writeln('Bang nhay bac ',k,' buoc ',b);
writeln(' gom ',n,' so');
writeln('Bat dau nap day ',n,' so.');
writeln('Sau moi so bam ENTER');
xx:= wherex; yy:= wherey;
for i := 0 to n-1 do
begin
gotoxy(xx,yy); readln(z); {nap 1 so}
if i < b then t := i
else
begin
t:= i MOD b;
for j:= 1 to 5 do
begin {sua lai so truoc do b buoc}
gotoxy(x[t],y[t]); write(BL:d);
gotoxy(x[t],y[t]); write(a[t]);
delay(W);
gotoxy(x[t],y[t]); write(BL:d);
gotoxy(x[t],y[t]); write(a[t]+k);
delay(W);
end;
end;
x[t] := xx; y[t]:= yy;
a[t] := z; xx:= xx + d;
if xx > LIM then
Sng to trong Thut ton v Lp trnh Tp I

82



begin
xx:= 1;
if yy < 24 then inc(yy)
else
begin
gotoxy(1,25); writeln;
for j := 0 to b do dec(y[j]);
end;
end;
end;
gotoxy(xx,yy); write(' KET ');
readln;
end;
BEGIN
BangNhay(3,6,10);
(* Loi giai: -5 -4 -3 -2 -1 0 1 8 9 10 *)
END.
// C#
Cc bi 3.3, 3.4 v 3.5 l n gin. Trong C# c hm ReadKey() cho ra gi tr kiu
ConsoleKeyInfor. Da theo gi tr ny ta c th xc nh phm no c bm. on
trnh di y minh ha kh chi tit vic nhn bit cc phm.
// Minh hoa ham Console.ReadKey()
using System;
using System.Text;
class Sample
{
public static void Main()
{
Test();
}
public static void Test()
{
ConsoleKeyInfo k;
do {
Console.Write("\n Bam phim ESC de thoat: ");
k = Console.ReadKey(true);
char c = k.KeyChar;
Console.Write(c);
if (char.IsLetter(c))
Console.Write(" Chu cai");
else if (char.IsNumber(c))
Console.Write(" Chu so");
else if (char.IsControl(c))
{
Console.Write(" Phim dieu khien ");
switch (k.Key) {
case ConsoleKey.F1: Console.Write(" F1");
break;
Sng to trong Thut ton v Lp trnh Tp I

83



case ConsoleKey.F2: Console.Write(" F2");
break;
case ConsoleKey.F3: Console.Write(" F3");
break;
case ConsoleKey.F4: Console.Write(" F4");
break;
case ConsoleKey.F5: Console.Write(" F5");
break;
case ConsoleKey.F6: Console.Write(" F6");
break;
case ConsoleKey.F7: Console.Write(" F7");
break;
case ConsoleKey.F8: Console.Write(" F8");
break;
case ConsoleKey.F9: Console.Write(" F9");
break;
case ConsoleKey.F10: Console.Write(" F10");
break;
case ConsoleKey.F11: Console.Write(" F11");
break;
case ConsoleKey.F12: Console.Write(" F12");
break;
case ConsoleKey.Enter: Console.Write(" ENTER");
break;
case ConsoleKey.Backspace:
Console.Write(" Lui (Backspace)");
break;
case ConsoleKey.Home:
Console.Write(" Home");
break;
case ConsoleKey.Insert:
Console.Write(" Ins");
break;
case ConsoleKey.Delete:
Console.Write(" Del");
break;
case ConsoleKey.PageDown:
Console.Write(" PgDn");
break;
case ConsoleKey.PageUp:
Console.Write(" PgUp");
break;
case ConsoleKey.Pause:
Console.Write(" Pause - Break");
break;
case ConsoleKey.RightArrow:
Console.Write(" Mui ten phai");
break;
case ConsoleKey.LeftArrow:
Console.Write(" Mui ten trai");
break;
case ConsoleKey.DownArrow:
Sng to trong Thut ton v Lp trnh Tp I

84



Console.Write(" Mui ten xuong");
break;
case ConsoleKey.UpArrow:
Console.Write(" Mui ten len");
break;
case ConsoleKey.End: Console.Write(" End");
break;
case ConsoleKey.Escape: Console.Write(" ESC");
Console.ReadKey(true);
break;
}
}
} while (k.Key != ConsoleKey.Escape);
}
}// Sample
Chng trnh C# di y th hin tr chi Gam15 nhm minh ha mt s tnh
nng qun l bn phm v mn hnh trong mi trng DOT.NET.
Hm GetKey() nhn mt phm v cuyn cc gi tr iu khin sang ni m, tc l m
do chng ta t t, th d, ta c th gn m cho phm mi tn tri l 4.
khi to cu hnh ban u ta s lp ngu nhin maxk ln vi gi tr maxk do
ngi chi t chn.
Cc trong bn c c th hin di dng [xx], trong xx l tr s ca qun c.
trng c th hin l [ ] vi mu xanh. Th d, cu hnh ban u (a) v cu hnh (b)
nhn c sau khi o ngu nhin mt s ln c th nh sau:

[ 1] [ 2] [ 3] [ 4] [ 1] [ 6] [ 2] [ 4]
[ 5] [ 6] [ 7] [ 8] [ 5] [10] [ 3] [ 8]
[ 9] [10] [11] [12] [ ] [14] [ 7] [11]
[13] [14] [15] [ ] [ 9] [13] [15] [12]

(a) Cu hnh ban u


(b) Cu hnh sau khi o
// C#
using System;
using System.IO;
namespace SangTao1
{
/*-------------------------------------------
* Game15
* ------------------------------------------*/

class Game15
{
const int scot = 20; // Toa do cot goc
const int sdong = 8; // Toa do dong goc
const int dcot = 5; // Kh cach giua 2 o tren dong
const int ddong = 2; // Khoang cach dong
Sng to trong Thut ton v Lp trnh Tp I

85



const int dd = 4; // ban co kich thuoc 4 X 4
const int dd1 = dd - 1;
const int LEN = 1;
const int XUONG = 2;
const int PHAI = 3;
const int TRAI = 4;
const int END = 5;
const int ESC = 6;
const string BL = " ";// dau cach
static public int [,] a = new int [dd, dd];
static public int [,] b = new int[dd, dd];
static public int cot = dd1; // toa do o trong
static public int dong = dd1;
static void Main()
{
Init(); Play();
}
static public void Play()
{
int k = 0;
int d = 0;
if (Console.CursorVisible)
Console.CursorVisible =
!Console.CursorVisible;
Console.SetCursorPosition(1, 1);
Console.Write("So buoc: ");
int coty = Console.CursorTop;
int dongx = Console.CursorLeft;
Console.SetCursorPosition(dongx, coty);
Console.Write(d);
do
{
VeO(dong, cot);
if (Sanhab())
{
Console.SetCursorPosition(dongx+2,
coty);
Console.Write(" Chuc mung +
"Thanh Cong !!!");
Console.ReadLine();
return;
}
k = GetKey(); ++d;
Console.SetCursorPosition(dongx, coty);
Console.Write(" ");
Console.SetCursorPosition(dongx, coty);
Console.Write(d);
switch (k)
{
case LEN: // Day quan duoi o trong LEN
if (dong < dd1)
{
a[dong,cot]=a[dong+1,cot];
Sng to trong Thut ton v Lp trnh Tp I

86



VeO(dong, cot);
++dong; a[dong, cot] = 0;
VeO(dong, cot);
}
break;
case XUONG://Day quan tren o trong XUONG
if (dong > 0)
{
a[dong,cot]=a[dong-1,cot];
VeO(dong, cot);
--dong; a[dong, cot] = 0;
VeO(dong, cot);
}
break;
case PHAI: // Day quan TRAI o trong sang
if (cot > 0)
{
a[dong, cot]=a[dong,cot-1];
VeO(dong, cot);
--cot; a[dong, cot] = 0;
VeO(dong, cot);
}
break;
case TRAI: // Day quan PHAI o trong sang
if (cot < dd1)
{
a[dong,cot]=a[dong,cot+1];
VeO(dong, cot);
++cot; a[dong, cot] = 0;
VeO(dong, cot);
}
break;
}
} while (k != ESC);
}
static public void Gotoij(int i,int j)
{
Console.SetCursorPosition(scot+dcot*j,
sdong+ddong*i);
}
static public void VeO(int i, int j)
{
int dong = sdong + ddong*i;
int cot = scot + dcot * j;
Console.SetCursorPosition(cot,dong);
Console.Write(" ");
Console.SetCursorPosition(cot, dong);
if (a[i,j] == 0)
{
Console.BackgroundColor =
ConsoleColor.Blue;
Console.Write("["+BL+BL+"]");
Console.BackgroundColor =
Sng to trong Thut ton v Lp trnh Tp I

87



ConsoleColor.Black;
}
else if (a[i,j] < 10)
Console.Write("[" + BL + a[i,j] + "]");
else Console.Write("[" + a[i,j] + "]");
}
// so sanh hai cau hinh a va b
static public bool Sanhab()
{
for (int i = 0; i < dd; ++i)
for (int j = 0; j < dd; ++j)
if (a[i,j] != b[i,j]) return false;
return true;
}
// Dao ngau nhien maxk lan
static public void DaoNgauNhien(int maxk)
{
Random r = new Random();
for (; Sanhab(); ) // Dao den khi a != b
{
for (int k = 0; k < maxk; ++k)
{
switch (r.Next(4) + 1)
{
case LEN:
// Day quan duoi o trong LEN
if (dong < dd1)
{
a[dong,cot]=a[dong+1,cot];
++dong; a[dong, cot] = 0;
}
break;
case XUONG:
// Day quan tren o trong XUONG
if (dong > 0)
{
a[dong,cot]=a[dong-1,cot];
--dong; a[dong, cot] = 0;
}
break;
case PHAI:
// Day quan TRAI o trong sang
if (cot > 0)
{
a[dong,cot]=a[dong,cot-1];
--cot; a[dong, cot] = 0;
}
break;
case TRAI: // Day quan PHAI o trong sang
if (cot < dd1)
{
a[dong, cot] = a[dong, cot + 1];
++cot; a[dong, cot] = 0;
Sng to trong Thut ton v Lp trnh Tp I

88



}
break;
} // switch
} // for k
} // for sanh
}
static public void VeBanCo()
{
for (int i = 0; i < dd; ++i)
for (int j = 0; j < dd; ++j)
VeO(i,j);
}
static public void Init()
{
// Khoi tri ban co a.
// Ban co b dung de doi sanh.
int k = 1;
for (int i = 0; i < dd; ++i)
for (int j = 0; j < dd; ++j)
b[i,j] = a[i, j] = k++;
b[dd1,dd1] = a[dd1, dd1] = 0;
dong = dd1; cot = dd1;
DaoNgauNhien(200);
VeBanCo();
}
static public int GetKey()
{
ConsoleKeyInfo k;
k = Console.ReadKey(true);
char c = k.KeyChar;
if (char.IsControl(c))
{
switch (k.Key)
{

case ConsoleKey.RightArrow: return PHAI;
case ConsoleKey.LeftArrow: return TRAI;
case ConsoleKey.DownArrow: return XUONG;
case ConsoleKey.UpArrow: return LEN;
case ConsoleKey.End: return END;
case ConsoleKey.Escape: return ESC;
}
}
return 0;
}
} // Game15
} // space




Sng to trong Thut ton v Lp trnh Tp I

89



CHNG 4
T CHC D LIU











Bi 4.1. Cm
Mt cm trong mt biu thc ton hc l on nm gia hai du ng v m
ngoc n (). Vi mi biu thc cho trc hy tch cc cm ca biu thc .
D liu vo: Tp vn bn CUM.INP cha mt dng kiu xu k t (string) l
biu thc cn x l.
D liu ra: Tp vn bn CUM.OUT dng u tin ghi d l s lng cm. Tip
n l d dng, mi dng ghi mt cm c tch t biu thc. Trng hp gp
li c php ghi s 1.
Th d:
CUM.INP CUM.OUT

x*(a+1)*((b-2)/(c+3))

4
(a+1)
(b-2)
(c+3)
((b-2)/(c+3))
Gi
Gi s xu s cha biu thc cn x l. Ta duyt ln lt t u n cui xu s, vi
mi k t s[i] ta xt hai trng hp:
Trng hp th nht: s[i] l du m ngoc '(': ta ghi nhn i l v tr
xut hin u cm vo mt ngn xp (stack) st:
inc(p); st[p] := i;
trong p l con tr ngn xp. p lun lun tr n ngn, tc l phn t cui
cng ca ngn xp. Th tc ny gi l np vo ngn xp: NapST.
Sng to trong Thut ton v Lp trnh Tp I

90



Trng hp th hai: s[i] l du ng ngoc ')': ta ly phn t ngn ra
khi ngn xp kt hp vi v tr i ghi nhn cc v tr u v cui cm
trong s. Hm ny gi l ly phn t ra khi ngn xp: LayST. Khi ly mt
phn t ra khi ngn xp ta gim con tr ngn xp 1 n v.
j := st[p]; dec(p);
C hai trng hp gy ra li c php n gin nh sau:
1. Gp ')' m trc cha gp '(': Li "cha m ng". Li ny c
pht hin khi xy ra tnh hung s[i] = ')' v stack rng (p = 0).
2. gp '(' m sau khng gp ')': Li "m ri m khng ng". Li
ny c pht hin khi xy ra tnh hung duyt ht biu thc s nhng trong
stack vn cn phn t (p > 0). Lu rng stack l ni ghi nhn cc du m
ngoc '('.
Ta dng bin SoCum m v ghi nhn cc cm xut hin trong qu trnh duyt
biu thc. Trng hp gp li ta t SoCum := -1. Hai mng dau v cuoi ghi
nhn v tr xut hin ca k t u cm v k t cui cm. Khi tng hp kt qu, ta s
dng n thng tin ca hai mng ny.
(*--------------------------
X l biu thc trong s
---------------------------*)
procedure BieuThuc;
var i: byte;
begin
KhoiTriSt; {Khi tr cho stack}
SoCum := 0; {Khi tr con m cm}
for i := 1 to length(s) do
case s[i] of
'(': NapSt(i);
')': if StackRong then
begin SoCum:= -1; exit; end
else
begin
inc(SoCum);
dau[SoCum] := LaySt;
cuoi[SoCum] := i;
end;
end {case};
if p > 0 then
begin SoCum := -1; exit; end;
end;
Sau khi duyt xong xu s ta ghi kt qu vo tp output g. Hm copy(s,i,d)
cho xu gm d k t c ct t xu s k t k t th i trong s. Th d
copy('12345678',4,3) = '456'.
(* Pascal *)
program Cum;
{$B-}
uses crt;
const
fn = 'CUM.INP'; gn = 'CUM.OUT';
type mb1 = array[1..255] of byte;
Sng to trong Thut ton v Lp trnh Tp I

91



var s: string; {chua bieu thuc can xu li}
st: mb1; {stack}
{stack luu vi tri xuat hien dau ( trong xau s}
p: integer; {con tro stack}
dau,cuoi: mb1; {vi tri dau, cuoi cua 1 cum}
SoCum: integer;
f,g: text;
(*--------------------------
Khoi tri stack st
---------------------------*)
procedure KhoiTriSt;
begin p := 0; end;
(*--------------------------
Nap tri i vao stack st
---------------------------*)
procedure NapSt(i: byte);
begin inc(p); st[p] := i; end;
(*-----------------------------
Lay ra 1 tri tu ngon stack st
---------------------------------*)
function LaySt: byte;
begin LaySt := st[p]; dec(p); end;
(*--------------------------
Kiem tra Stack St rong ?
---------------------------*)
function StackRong: Boolean;
begin StackRong := (p=0); end;
(*--------------------------
Xu ly bieu thuc trong s
---------------------------*)
procedure BieuThuc; t vit
(*---------------------------------
Doc du lieu tu tep input vao xau s
----------------------------------*)
procedure Doc;
begin
s := ''; {gan tri rong cho s}
assign(f,fn); reset(f);
if not seekeof(f) then readln(f,s);
close(f);
end;
(*--------------------------
Ghi ket qua vao tep output
---------------------------*)
procedure Ghi;
var i: byte;
begin
assign(g,gn); rewrite(g); writeln(g,SoCum);
for i := 1 to SoCum do
writeln(g,copy(s,dau[i],cuoi[i]-dau[i]+1));
close(g);
end;
BEGIN
Sng to trong Thut ton v Lp trnh Tp I

92



Doc; BieuThuc; Ghi;
END.
// C#
using System;
using System.IO;
namespace SangTao1
{
/*----------------------------------------
* Tach cum trong bieu thuc
* -------------------------------------*/
class Cum
{
const string fn = "cum.inp";
const string gn = "cum.out";
static void Main()
{
if (XuLi()) KiemTra();
Console.ReadLine();
}

static public bool XuLi()
{
// Doc du lieu vao string s,
// bo cac dau cach dau va cuoi s
string s = (File.ReadAllText(fn)).Trim();
int[] st = new int[s.Length];//stack
int p = 0; // con tro stack
int sc = 0; // Dem so cum
String ss = ""; // ket qua
for (int i = 0; i < s.Length; ++i)
{
switch (s[i])
{
case '(': st[++p] = i; break;
case ')':
if (p == 0)
{
Console.WriteLine("\nLOI:" +
" Thieu (");
return false;
}
++sc;
for (int j = st[p]; j<=i; ++j)
ss += s[j];
ss += "\n"; // ket dong
--p;
break;
} // switch
} // for
if (p > 0)
{
Sng to trong Thut ton v Lp trnh Tp I

93



Console.WriteLine("\n LOI: Thua (");
return false;
}
// Ghi file ket qua
File.WriteAllText(gn,(sc.ToString() + "\n"
+ ss));
return true;
}
// Doc lai 2 file inp va out de kiem tra
static public void KiemTra()
{
Console.WriteLine("\n Input file " + fn);
Console.WriteLine(File.ReadAllText(fn));
Console.WriteLine("\n Output file " + gn);
Console.WriteLine(File.ReadAllText(gn));
}
} // Cum
} // SangTao1
Bi 4.2. Bi gp
B bi bao gm n qun, c gn m s t 1 n n. Lc u b bi c chia cho n
ngi, mi ngi nhn 1 qun. Mi lt chi, trng ti chn ngu nhin hai s x v y
trong khong 1..n. Nu c hai ngi khc nhau, mt ngi c trong tay qun bi x v
ngi kia c qun bi y th mt trong hai ngi phi trao ton b s bi ca mnh
cho ngi kia theo nguyn tc sau: mi ngi trong s hai ngi trnh ra mt
qun bi tu chn ca mnh, Ai c qun bi mang m s nh hn s c nhn bi
ca ngi kia. Tr chi kt thc khi c mt ngi cm trong tay c b bi. Bit s
qun bi n v cc qun bi trng ti chn ngu nhin sau m lt chi, hy cho bit
s lng ngi cn c bi trn tay.
D liu vo: Tp vn bn BAIGOP.INP.
- Dng u tin: hai s n v m, trong n l s lng qun bi trong b bi, m
l s ln trng ti chn ngu nhin hai s x v y. Cc qun bi c gn m s
t 1 n n. M s ny c ghi trn qun bi.
- Tip n l m dng, mi dng ghi hai s t nhin x v y do trng ti
cung cp. Cc s trn cng mt dng cch nhau qua du cch.
D liu ra: Hin th trn mn hnh s lng ngi cn c bi trn tay.
Th d:
D liu vo:
BAIGOP.INP
Kt qu hin th trn
mn hnh
ngha: b bi c 10 qun m s ln lt 1,
2,, 10 v c 10 ngi chi. Su ln trng ti
chn ngu nhin cc cp s (x, y) l (2, 5),
(3, 3), (4, 7), (1, 5), (2, 8) v (9, 3). Cui vn
chi cn li 5 ngi c bi trn tay: {1, 2, 5, 8},
{3, 9}, {4, 7}, {6}, {10}.

10 6
2 5
3 3
4 7
1 5
2 8
9 3
5

Thut ton
y l bi ton c nhiu ng dng hu hiu nn bn c cn tm hiu k v c gng
ci t cho nhun nhuyn. Nh sau ny s thy, nhiu thut ton x l th nh tm
Sng to trong Thut ton v Lp trnh Tp I

94



cy khung, xc nh thnh phn lin thng, xc nh chu trnh s phi vn dng cch
t chc d liu tng t nh thut ton s trnh by di y.
Bi ny i hi t chc cc tp qun bi sao cho thc hin nhanh nht cc thao tc
sau y:
Find(x): cho bit tn ca tp cha phn t x.
Union(x, y): hp tp cha x vi tp cha y.
Mi tp l nhm cc qun bi c trong tay mt ngi chi. Nh vy mi tp l mt
tp con ca b bi {1, 2,, n}. Ta gi b bi l tp ch hay tp nn. Do tnh cht ca
tr chi, ta c hai nhn xt quan trng sau y:
1. Hp ca tt c cc tp con (mi tp con ny do mt ngi ang chi qun
l) ng bng tp ch.
2. Hai tp con khc nhau khng giao nhau: ti mi thi im ca cuc chi,
mi qun bi nm trong tay ng mt ngi.
H cc tp con tha hai tnh cht ni trn c gi l mt phn hoch ca tp ch.
Cc thao tc ni trn phc v trc tip cho vic t chc tr chi theo s sau:
Khi tr:
for i:= 1 to n do
begin
Trng ti sinh ngu nhin hai s x v y
trong khong 1..n:
Hp tp cha x vi tp cha y: Union(x,y);
end;
thc hin th tc Union(x,y) trc ht ta cn bit qun bi x v qun bi y
ang trong tay ai? Sau ta cn bit ngi gi qun bi x (hoc y) c qun bi nh
nht l g? Qun bi nh nht c xc nh trong ton b cc qun bi m ngi c
trong tay. y chnh l im d nhm ln. Th d, ngi chi A ang gi trong tay cc
qun bi 3, 4 v 7, A = {3, 4, 7}; ngi chi B ang gi cc qun bi 2, 5, 9 v 11, B =
{2, 5, 9, 11}. Cc s gch chn l s hiu ca qun bi nh nht trong tay mi ngi.
Nu x = 9 v y = 7 th A (ang gi qun y = 7) v B (ang gi qun x = 9) s phi u
vi nhau. V trong tay A c qun nh nht l 3 v trong tay B c qun nh nht l 2 nn
A s phi np bi cho B v ra khi cuc chi. Ta c, B = {2, 3, 4, 5, 7, 9, 11}. Ta kt
hp vic xc nh qun bi x trong tay ai v ngi c qun bi nh nht l bao nhiu
lm mt xy dng hm Find(x). C th l hm Find(x) s cho ta qun bi nh
nht c trong tay ngi gi qun bi x. Trong th d trn ta c:
Find(x) = Find(9) = 2 v Find(y) = Find(7) = 3
Lu rng hm Find(x) khng ch r ai l ngi ang gi qun bi x m cho
bit qun bi c s hiu nh nht c trong tay ngi ang gi qun bi x, ngha l
Find(9)=2 ch khng phi Find(9) = B. gii quyt s khc bit ny ta hy
chn phn t c s hiu nh nht trong tp cc qun bi c trong tay mt ngi lm
phn t i din ca tp . Ta cng ng nht phn t i din vi m s ca ngi
gi tp qun bi. Theo quy nh ny th biu thc Find(9)=2 c th c hiu theo
mt trong hai ngha tng ng nh sau:
Ngi s 2 ang gi qun bi 9.
Tp s 2 cha phn t 9.
T chc hm Find nh trn c li l sau khi gi i:=Find(x) v j:=Find(y) ta
xc nh ngay c ai phi np bi cho ai. Nu i < j th j phi np bi cho i, ngc
Sng to trong Thut ton v Lp trnh Tp I

95



li, nu i > j th i phi np bi cho j. Trng hp i = j cho bit hai qun bi x
v y ang c trong tay mt ngi, ta khng phi lm g.
Tm li ta t ra cc nguyn tc sau:
a) Ly phn t nh nht trong mi tp lm tn ring cho tp .
b) Phn t c gi tr nh qun l cc phn t c gi tr ln hn n theo phng
thc: mi phn t trong mt tp u tr trc tip n mt phn t nh hn n v c trong
tp . Phn t nh nht trong tp tr ti chnh n.
Trong th d trn ta c A = {3, 4, 7}, B = {2, 5, 9, 11}, x = 9 v y = 7.
Nh vy, tp A c phn t i din l 3 v tp B c phn t i din l 2.
D liu ca tp A khi s c t chc nh sau:
A = {3 3, 4 3, 7 3}. Nh vy 3 l phn t i din ca tp ny, do ta
khng cn dng bin A biu th n na m c th vit:
{3 3, 4 3, 7 3} hoc gn hn {3, 4, 7} 3.
Tng t, d liu ca tp B s c dng:
{2 2, 5 2, 9 2, 11 2} hoc gn hn {2, 5, 9, 11} 2.
Khi Find(9) = 2 v Find(7) = 3, v do , tp 3 phi c gp vo
tp 2. Php Union(9,7) s to ra tp sau y:
{3 2, 4 3, 7 3, 2 2, 5 2, 9 2, 11 2},
tc l ta thc hin ng mt thao tc sa 3 3 thnh 3 2: hp hai tp ta ch vic
i snh hai phn t i din i v j ca chng:
Nu i > j th cho tp i ph thuc vo tp j.
Nu j > i th cho tp j ph thuc vo tp i.
Nu i = j th khng lm g.
K thut ni trn c gi l hp cc tp con ri nhau.
Ta dng mt mng nguyn a th hin tt c cc tp. Khi hai tp A v B ni trn
c th hin trong a nh sau:
a[3] = 3; a[4] = 3; a[7] = 3;
{tp A: phn t i din l 3, cc phn t 3, 4 v 7 u tr n 3}
a[2] = 2; a[5] = 2; a[9] = 2; a[11] = 2;
{tp B: phn t i din l 2, cc phn t 2, 5, 9 v 11 u tr n 2}
(1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) (15)

2
(B)
3
(A)
3
(A)
2
(B)

3
(A)

2
(B)

2
(B)

Sau khi hp nht A vi B ta c:
a[3] = 2; {ch sa duy nht}
a[4] = 3; a[7] = 3; a[2] = 2; a[5] = 2; a[9] = 2; a[11] = 2;
(1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) (15)
2 2 3 2 3 2 2
Theo cc nguyn tc trn ta suy ra phn t x l phn t i din ca tp khi v ch
khi a[x] = x. Da vo y ta t chc hm Find(x): xc nh phn t i din ca tp
cha x.
function Find(x: integer): integer;
begin
Sng to trong Thut ton v Lp trnh Tp I

96



while (x <> a[x]) do x := a[x];
Find := x;
end;
Khi th tc Union c trin khai n gin nh sau:
procedure Union(x, y: integer);
begin
x := Find(x);
y := Find(y);
if x = y then exit else
if x < y then a[y] := x
else {x > y} a[x] := y;
end;
Lc bt u chi, mi ngi gi mt qun bi, ta khi tr a[i]:=i cho mi i
= 1..n vi ngha: tp c ng mt phn t th n l i din ca chnh n.
m s tp cn li sau mi bc chi ta c th thc hin theo hai cch.
Ta thy, nu Find(x)=Find(y) th khng xy ra vic gp bi v x v y cng
nm trong mt tp. Ngc li, nu Find(x)<>Find(y) th do gp bi nn s ngi
chi s gim i 1 tc l s lng tp gim theo. Ta dng mt bin c m s lng tp.
Lc u khi tr c:=n (c n ngi chi). Mi khi xy ra iu kin Find(x) <>
Find(y) ta gim c 1 n v: dec(c).
Theo cch th hai ta vit hm Dem m s lng tp sau khi kt thc mt lt
chi. Ta c c t sau y:
s lng tp = s lng i din ca tp.
Phn t i l i din ca mt tp khi v ch khi a[i] = i.
c t trn cho ta:
function Dem: integer;
var d,i: integer;
begin
d := 0;
for i := 1 to n do
if a[i] = i then inc(d);
Dem := d;
end;
D nhin trong bi ny phng php th nht s hiu qu hn, tuy nhin ta thc
hin c hai phng php v hm Dem l mt tin ch trong loi hnh t chc d liu theo
tip cn Find-Union.
Ta cng s ci t Union(x,y) di dng hm vi gi tr ra l 1 nu trc thi
im hp nht x v y thuc v hai tp phn bit v l 0 nu trc x v y thc
s c trong cng mt tp. Ni cch khc Union(x,y) cho bit php hp nht c thc
s xy ra (1) hay khng (0).
Trong chng trnh di y tp BAIGOP.INP cha d liu vo c cu trc
nh sau:
- Dng u tin cha hai s nguyn dng n v m, trong n l s lng qun
bi, m l s ln trng ti pht sinh ra hai s ngu nhin.
Sng to trong Thut ton v Lp trnh Tp I

97



- Tip n l m dng, mi dng cha hai s do trng ti pht sinh. Cc s c
vit cch nhau bi du cch.
K thut trn c tn gi l Find-Union ng vai tr quan trng trong cc th tc x
l hp cc tp ri nhau. Trc khi xem chng trnh chng ta hy th lm mt bi tp
nh sau y:
Vi mng a c t chc theo k thut Find-Union di y hy cho bit c my
tp con v hy lit k tng tp mt.
(1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) (15)
1 2 2 3 2 6 3 1 2 6 2 10 3 8 12
p s: ba tp.
Tp vi i din 1: {1, 8, 14}.
Tp vi i din 2: {2, 3, 4, 5, 7, 9, 11, 13}.
Tp vi i din 6: {6, 10, 12, 15}.
(* Pascal *)
(*-----------------------------------
BAI GOP
------------------------------------*)
program BaiGop;
uses crt;
const
MN = 5000;
fn = 'BAIGOP.INP';
var
a: array[1..MN] of integer;
c,n,m: integer;
{c: dem so tap
n: so quan bai = so nguoi choi
m: so lan trong tai sinh 2 so}
f: text;
{----------------------------------
Xac dinh tap chua phan tu x
-----------------------------------}
function Find(x: integer): integer;
begin
while (x <> a[x]) do x:= a[x];
Find := x;
end;
{-------------------------------------
Hop cua tap chua x voi tap chua y.
Union = 1: co hop nhat
Union = 0: khong hop nhat vi x va y
thuoc cung 1 tap
--------------------------------------}
function Union(x,y: integer): integer;
begin
Union := 0;
x := Find(x);
y := Find(y);
Sng to trong Thut ton v Lp trnh Tp I

98



if x = y then exit
else if x < y then a[y] := x
else a[x] := y;
Union := 1;
end;
{-----------------------------------------------
Dem so luong tap con roi nhau (so nguoi choi)
-----------------------------------------------}
function Dem: integer;
var d,i: integer;
begin
d := 0;
for i := 1 to n do
if a[i] = i then inc(d);
Dem:= d;
end;
procedure BaiGop;
var i,j,k,x,y: integer;
begin
assign(f,fn); reset(f);
readln(f,n,m);
{n so quan bai; m so lan chon x,y}
c := n; {c: so nguoi choi}
if (n < 1) or (n > MN) then exit;
for i := 1 to n do a[i] := i;
for i := 1 to m do
begin
readln(f,x,y);
c := c-Union(x,y);
end;
writeln(c);
close(f);
end;
BEGIN
BaiGop;
END.
// C#
using System;
using System.IO;
namespace SangTao1
/*--------------------------------------
* Bai gop
* -------------------------------------*/
class BaiGop
{
const string fn = "baigop.inp";
static int[] a; // quan li cac tap roi nhau
static int n = 0; // so quan bai
static int m = 0;// so lan trong tai
// chon 2 quan bai
static void Main()
{
Sng to trong Thut ton v Lp trnh Tp I

99



Run();
Console.ReadLine();
} // Main
// Xac dinh tap chua phan tu x
static int Find(int x) t vit
static int Union(int x, int y) t vit
static void Run()
{
int [] b = ReadInput();
n = b[0];
m = b[1];
a = new int[n + 1];
for (int i = 1; i <= n; ++i)
a[i] = i;
int j = 2, d = n;
for (int i = 1; i <= m; ++i)
{
d -= Union(b[j], b[j+1]);
j += 2;
}
Console.WriteLine("\n " + d + "\n");
}
static int[] ReadInput()
{
char[] cc = new char[]
{ ' ', '\n', '\t', '\r'};
string[] ss = (File.ReadAllText(fn)).
Split(cc,StringSplitOptions.
RemoveEmptyEntries);
return Array.ConvertAll(ss,
new Converter<string, int>(int.Parse));
}
} // BaiGop
} // SangTao1
Bi 4.3. Chui ht
Trong mt tp vn bn tn CHUOI.DAT c biu din mt chui ht, mi ht
c th nhn mt trong s cc mu m s t 1 n 30.
Lp trnh thc hin cc vic sau:
a) c chui ht t tp vo mng nguyn dng a.
b) Hin th s mu c trong chui.
c) Tm mt im ct chui ri cng thng ra sao cho tng s cc ht cng
mu hai u l ln nht.
Chui c th hin trong tp di dng hnh thoi, dng u tin v dng cui
cng mi dng c mt ht.
Mi dng cn li c hai ht (xem hnh).
Cc ht ca chui c nh s bt u t ht trn cng v theo chiu kim
ng h.
CHUOI.DAT Trong th d ny, cc thng bo trn mn hnh s l:
Sng to trong Thut ton v Lp trnh Tp I

100



4
4 7
1 4
5 8
5 8
5 8
8
S mu trong chui: 5
Ct gia ht th 7 v th 8, tng s ln nht l 7.
Chui ht
Thut ton
Khung chng trnh c phc tho nh sau:
procedure run;
var i: integer;
begin
c d liu;
Tnh v thng bo s mu
X l tm im ct;
Thng bo im ct
end;
c chui t tp vo mng a ta dng thm mt mng ph b c cng cu trc
nh mng a. Mng b s cha cc ht na tri chui, trong khi mng a cha cc ht
na phi. Lc u, do ch c 1 ht ti dng u tin nn ta c ht vo a[1]. Ti cc
dng tip theo, mi dng n = 2, ta c s hiu mu ca 2 ht, ht tri vo b[n] v ht
phi vo a[n]. Du hiu kt thc chui l 1 ht. Ht ny c c vo b[n]. Ta
rng, theo cu trc ca chui ht th s ht trong chui lun lun l mt s chn.
Th d di y minh ho giai on u ca th tc c d liu. Khi kt thc giai
on ny ta thu c n = 7 v na phi ca chui ht (s c gch di) c ghi trong
a[1..(n 1)], na tri c ghi trong b[2..n]. Tng s ht trong chui khi s l
2*(n 1).
CHUOI.DAT

4
4 7
1 4
5 8
5 8
5 8
8
4 a[1]
b[2] 4 7 a[2]
b[3] 1 4 a[3]
b[4] 5 8 a[4]
b[5] 5 8 a[5]
b[6] 5 8 a[6]
b[7] 8
c d liu ca chui ht vo
hai mng a v b
a[1..6]=(4,7,4,8,8,8)
b[2..7]=(4,1,5,5,5,8)
Sau khi c xong ta duyt ngc mng b ni na tri ca chui ht vo sau na
phi a.
Sng to trong Thut ton v Lp trnh Tp I

101



(*-----------------------------------
Doc du lieu tu file CHUOI.DAT
ghi vao mang a
------------------------------------*)
procedure Doc;
var
f: text;
i: integer;
begin
assign(f,fn); reset(f);
n := 1; read(f,a[n]);
while NOT SeekEof(f) do
begin
inc(n); read(f,b[n]);
if NOT SeekEof(f) then read(f,a[n]);
end;
{noi nua trai b (duyet nguoc) vao nua phai a}
for i:= 0 to n-2 do a[n+i]:= b[n-i];
n := 2*(n-1); close(f);
end;
Theo th d trn, sau khi ni b[2..n] vo sau a[1..(n 1)] ta thu c
a[1..12] = (4,7,4,8,8,8,8,5,5,5,1,4)
m s mu trong chui ta dng phng php nh du. Ta s dng mng b
vi ngha nh sau:
- b[i] = 0: mu i cha xut hin trong chui ht;
- b[i] = 1: mu i xut hin trong chui ht.
Ln lt duyt cc phn t a[i], i = 1..n trong chui. Nu mu a[i] cha
xut hin ta tng tr ca con m mu d thm 1, inc(d) v nh du mu a[i]
trong b bng php gn b[a[i]] := 1.
(*-----------------------------------
Dem so mau trong chuoi
------------------------------------*)
function Dem: integer;
var i,d: integer;
begin
d := 0;
fillchar(b,sizeof(b),0);
for i := 1 to n do
if b[a[i]] = 0 then
begin
inc(d);
b[a[i]] := 1;
end;
Dem := d;
end;
tm im ct vi tng chiu di hai u ln nht ta thc hin nh sau. Trc ht
ta nh ngha im i mu trn chui ht l ht (ch s) m mu ca n khc vi mu
ca ht ng st n (st phi hay st tri, ty theo chiu duyt xui t tri qua phi hay
duyt ngc t phi qua tri). Ta cng nh ngha mt on trong chui ht l mt dy
lin tip cc ht cng mu vi chiu di ti a. Mi on u c im u v im cui.
Sng to trong Thut ton v Lp trnh Tp I

102



V im cui ca mi on ch lch 1 n v so vi im u ca on tip theo, cho
nn vi mi on ta ch cn qun l mt trong hai im: im u hoc im cui ca
on . Ta chn im u. K thut ny c gi l qun l theo on.
Th d, chui ht a vi n = 12 ht mu nh trong th d cho:
a[1..12] = (4,7,4,8,8,8,8,5,5,5,1,4)
mi xem tng nh c to t by on l:
a[1..1] = (4)
a[2..2] = (7)
a[3..3] = (4)
a[4..7] = (8,8,8,8)
a[8..10] = (5,5,5)
a[11..11] = (1)
a[12..12] = (4)
Tuy nhin, do chui l mt dy ht khp kn v cc ht c b tr theo chiu quay
ca kim ng h nn thc cht a ch gm su on:
a[2..2] = (7)
a[3..3] = (4)
a[4..7] = (8,8,8,8)
a[8..10] = (5,5,5)
a[11..11] = (1)
a[12..1] = (4,4)
trong a[x..y] cho bit ch s u on l x, cui on l y. Nu x s y th cc
ht trong on c duyt theo chiu kim ng h t ch s nh n ch s ln, ngc
li, nu x > y th cc ht trong on cng c duyt theo chiu kim ng h t ch
s ln n ch s nh. Cc phn t u mi on c gch chn. C th c nhng
on cha c ht cui cng a[n] v ht u tin a[1] nn ta cn xt ring trng
hp ny.
on trnh di y xc nh cc im u ca mi on v ghi vo mng
b[1..sdc]. Gi tr sdc cho bit s lng cc on.
sdc := 0;
if a[1]<>a[n] then
begin
sdc := 1;
b[sdc] := 1;
end;
for i := 1 to n-1 do
if a[i] <> a[i+1] then
begin
inc(sdc);
b[sdc] := i+1;
end;
Gi im u ca ba on lin tip l d1, d2 v d3. Ta thy, nu chn im ct st
tri ht d2 th hiu d3 - d1 chnh l tng s ht ng mu ti hai u ca chui ht c
cng ra. T ta phc tho c s cho th tc xuly tm im ct DiemCat
vi chiu di ln nht Lmax nh sau:
Khi tr;
Duyt t b ba im u ca
ba on lin tip d1, d2, d3
Sng to trong Thut ton v Lp trnh Tp I

103



Nu d3-d1 > Lmax th
t li Lmax := d3-d1
t li DiemCat := d2
xong nu
Gi s chui ht c m on. Theo phng thc duyt chui ht vng trn theo chiu
kim ng h, ta cn xt ring hai on u v cui, c th l:
Vi on 1 ta phi xt hai on ng trc v sau on l on m v
on 2.
Vi on m ta phi xt hai on ng trc v sau on l on
m 1 v on 1.
Ta x l ring hai on ny bc khi tr nh sau:
{xu li diem cat dau}
Lmax := (b[1]+(n-b[sdc]))+(b[2]-b[1]);
DiemCat := b[1];
{xu li diem cat cuoi}
if (b[1]+(n-b[sdc]))+(b[sdc]-b[sdc-1]) > Lmax then
begin
Lmax := (b[1]+(n-b[sdc]))+(b[sdc]-b[sdc-1]);
DiemCat := b[sdc];
end;
Phng n cui cng ca th tc xuly s nh sau:
procedure xuly;
var i,sdc: integer; {sdc: so diem cat}
begin
sdc:=0;
if a[1]<>a[n] then
begin
sdc := 1;
b[sdc]:= 1;
end;
for i:=1 to n-1 do
if a[i] <> a[i+1] then
begin
inc(sdc);
b[sdc] := i+1;
end;
if sdc=0 then
begin
DiemCat:=0;
Lmax:=n;
exit;
end;
{xu li diem cat dau}
Lmax := (b[1]+(n-b[sdc]))+(b[2]-b[1]);
DiemCat := b[1];
{xu li diem cat cuoi}
if (b[1]+(n-b[sdc]))+(b[sdc]-b[sdc-1]) > Lmax then
begin
Lmax := (b[1]+(n-b[sdc]))+(b[sdc]-b[sdc-1]);
DiemCat := b[sdc];
end;
Sng to trong Thut ton v Lp trnh Tp I

104



{xu li cac diem cat giua}
for i:= 2 to sdc-1 do
if b[i+1]-b[i-1] > Lmax then
begin
Lmax := b[i+1]-b[i-1];
DiemCat := b[i];
end;
end;
(* Pascal *)
(*--------------------
CHUOI HAT
---------------------*)
program Chuoi;
{$B-}
uses crt;
const
MN = 500; {So luong hat toi da trong chuoi}
MC = 30; {So luong mau}
fn = 'CHUOI.DAT';
BL = #32;
var
a,b,len: array[0..MN] of byte;
n: integer; {So luong phan tu thuc co trong chuoi hat}
DiemCat: integer; {diem cat}
Lmax: integer; {Chieu dai toi da}
(*-----------------------------------
Doc du lieu tu tep CHUOI.DAT ghi
vao mang a
------------------------------------*)
procedure Doc;
var
f: text;
i: integer;
begin
assign(f,fn);
reset(f);
n:= 1;
read(f,a[1]);
while not SeekEof(f) do
begin
inc(n);
read(f,b[n]);
if not SeekEof(f) then read(f,a[n]);
end;
for i:=0 to n-2 do a[n+i]:= b[n-i];
n:= 2*(n-1);
close(f);
end;
(*-------------------------------------
Hien thi chuoi tren man hinh
de kiem tra ket qua doc
Sng to trong Thut ton v Lp trnh Tp I

105



--------------------------------------*)
procedure Xem;
var i: integer;
begin
writeln;
writeln('Tong so hat: ',n);
for i:= 1 to n do
write(a[i],bl);
end;
(*-----------------------------------
Dem so mau trong chuoi
------------------------------------*)
function Dem: integer;
var i,d: integer;
begin
d:=0;
fillchar(b,sizeof(b),0);
for i:= 1 to n do
if b[a[i]] = 0 then
begin
inc(d);
b[a[i]]:=1;
end;
Dem:= d;
end;
procedure xuly;
var i,sdc: integer; {sdc: so diem cat}
begin
sdc:=0;
if a[1]<>a[n] then
begin
sdc:=1;
b[sdc]:=1;
end;
for i:=1 to n-1 do
if a[i] <> a[i+1] then
begin
inc(sdc);
b[sdc]:=i+1;
end;
if sdc=0 then
begin
DiemCat:=0;
Lmax:=n;
exit;
end;
{xu li diem cat dau}
Lmax:= (b[1]+(n-b[sdc]))+(b[2]-b[1]);
DiemCat:=b[1];
{xu li diem cat cuoi}
if (b[1]+(n-b[sdc]))+(b[sdc]-b[sdc-1]) > Lmax
then
begin
Sng to trong Thut ton v Lp trnh Tp I

106



Lmax:= (b[1]+(n-b[sdc]))+(b[sdc]-b[sdc-1]);
DiemCat:=b[sdc];
end;
{xu li cac diem cat giua}
for i:=2 to sdc-1 do
if b[i+1]-b[i-1] > Lmax then
begin
Lmax:= b[i+1]-b[i-1];
DiemCat:=b[i];
end;
end;
procedure run;
var i: integer;
begin
Doc; Xem; writeln;
writeln('So mau trong chuoi: ',Dem);
xuly;
writeln;
if DiemCat=0 then
writeln(' Chuoi dong mau, cat tai diem tuy y')
else
begin
if DiemCat = 1 then i :=n
else i:=DiemCat-1;
writeln('Cat giua hat ',i,
' va hat ',DiemCat);
end;
writeln(' Chieu dai max: ',Lmax);
readln;
end;
BEGIN
run;
END.

D liu kim th
CHUOI.DAT
Kt qu d kin
4
4 7
1 4
5 8
5 8
5 8
8

Ct gia ht: 7 v 8
Chiu di max: 7


// C#
using System;
using System.IO;
namespace SangTao1
{
class ChuoiHat
{
Sng to trong Thut ton v Lp trnh Tp I

107



const string fn = "chuoi.dat";
static int[] a; // chuoi hat
static int n; // so phan tu trong input file
static void Main()
{
Run();
Console.ReadLine();
} // Main
static void Run()
{
int[] b = ReadInput();
n = b.Length;
a = new int[n];
int t = 0; // nua trai
int p = n - 1; // nua phai
int n2 = n / 2;
for (int i = 0; i < n2; ++i)
{
a[t++] = b[2 * i];
a[p--] = b[2 * i + 1];
}
Console.WriteLine();
for (int i = 0; i < n; ++i)
Console.Write(a[i] + " ");
Console.WriteLine("\n\n Chuoi hat co "
+ Dem() + " mau \n");
DiemCat();
}
static int[] ReadInput()
{
char[] cc = new char[] { ' ', '\n', '\t', '\r'};
return Array.ConvertAll(
(File.ReadAllText(fn)).Split(cc,

StringSplitOptions.RemoveEmptyEntries),
new Converter<string, int>(int.Parse));
}
/*--------------------------
* Dem so mau trong chuoi
* -------------------------*/
static int Dem()
{
int[] b = new int[31];
for (int i = 1; i <= 30; ++i) b[i] = 0;
for (int i = 0; i < n; ++i) b[a[i]] = 1;
int d = 0;
for (int i = 1; i <= 30; ++i) d += b[i];
return d;
}
static void DiemCat()
{
int sdc = 0; // dem so diem cat
int[] b = new int[n];
Sng to trong Thut ton v Lp trnh Tp I

108



for (int i = 1; i < n ; ++i)
if (a[i] != a[i-1]) b[sdc++] = i-1;
// xet diem dau a[0] va diem cuoi a[n-1]
if (a[n-1] != a[0]) b[sdc++] = n-1;
int DiemCat = 0;
int Lmax = 0;
if (sdc == 0) // chuoi hat dong mau
{
Lmax = n;
Console.WriteLine("Chuoi hat dong mau. ");
Console.WriteLine("Chon diem cat tuy y. ");
Console.WriteLine("Chieu dai max = " + Lmax);
return;
}
if (sdc == 2) // 2 mau
{
Lmax = n;
Console.WriteLine("\n Cat giua hat " + b[0]);
Console.WriteLine("va hat " + (b[0] + 1) % n);
Console.WriteLine("Chieu dai max = " + Lmax);
return;
}
for (int i = 0; i < sdc; ++i)
if ((b[(i + 2) % sdc] + n - b[i]) % n > Lmax)
{
Lmax = (b[(i + 2) % sdc] + n - b[i]) % n;
DiemCat = b[(i + 1) % sdc];
}
Console.WriteLine("\n Cat giua hat thu " +
(DiemCat + 1));
Console.WriteLine(" va hat thu " +
((DiemCat + 1) % n + 1));
Console.WriteLine(" Chieu dai max = " + Lmax);
}
} // class
} // SangTao1
Bi 4.4. Sp mng ri ghi tp
Sinh ngu nhin n phn t cho mng nguyn a. Sp a theo trt t tng dn ri
ghi vo mt tp vn bn c tn tu t.
Gi
Chng trnh gii thiu hai th tc sp mng l MinSort v QuickSort. Theo
phng php MinSort vi mi i ta tm phn t nh nht a[j] trong on a[i..n] sau ta
i ch phn t ny vi phn t a[i]. Nh vy mng c chia thnh hai on: on
tri, a[1..i] c sp tng, cn on phi a[i + 1..n] cha x l. Mi bc ta thu hp
on phi cho n khi cn mt phn t l xong.
Theo phng php QuickSort ta ly mt phn t x nm gia on mng cn sp
lm mu ri chia mng thnh hai on. on tri a[1..i] bao gm cc gi tr khng ln
hn x v on phi a[j..n] bao gm cc gi tr khng nh thua x. Tip n ta lp li th
tc ny vi hai on thu c nu chng cha nhiu hn mt phn t.
(* Pascal *)
Sng to trong Thut ton v Lp trnh Tp I

109



(*---------------------------------------
SAPTANG: Sap mang, ghi tep
----------------------------------------*)
program SapTang;
{$B-}
uses crt;
const
MN = 5000;
fn = 'saptang.out';
var
f: text;
a: array[1..MN] of integer;
n: integer;
(*------------------------------
sinh ngau nhien m phan tu
cho mang nguyen a
--------------------------------*)
procedure Init(m: integer);
var i: integer;
begin
if (m < 0) or (m > MN) then exit;
n:= m;
randomize;
for i:= 1 to n do a[i]:= random(MN);
end;
(*-------------------------------------
Sap nhanh doan a[d..c]
---------------------------------------*)
procedure QuickSort(d, c: integer);
var i, j, x, y: integer;
begin
i:= d; j:= c;
x:= a[(i+j) div 2];{lay tri mau x}
while i <= j do
begin
while a[i] < x do inc(i); {to chuc doan trai}
while a[j] > x do dec(j); {to chuc doan phai}
if (i <= j) then {doi cho neu can}
begin
y:= a[i];
a[i]:= a[j];
a[j]:= y;
inc(i); dec(j);
end;
end;
if (d < j) then QuickSort(d,j); {sap tiep doan trai}
if (i < c) then QuickSort(i,c); {sap tiep doan phai}
end;
(*------------------------------------
Tim chi dan m trong khoang d..c
thoa a[m] = min(a[d..c])
--------------------------------------*)
function Min(d, c: integer): integer;
Sng to trong Thut ton v Lp trnh Tp I

110



var i: integer;
begin
for i:= d+1 to c do
if a[i] < a[d] then d:= i;
Min:= d;
end;
procedure MinSort;
var i, j, y: integer;
begin
for i:= 1 to n-1 do
begin
j:= Min(i,n);
{doi cho a[i] va a[j]}
y:= a[i];
a[i]:= a[j];
a[j]:= y;
end;
end;
(*----------------------------------
Ghi tep, moi dong khong qua 20 so
-----------------------------------*)
procedure Ghi;
var i: integer;
begin
assign(f,fn); rewrite(f);
writeln(f,n);
for i:= 1 to n do
begin
write(f,a[i]:5);
if i mod 20 = 0 then writeln(f);
end;
close(f);
end;
procedure TestQuickSort;
begin
Init(MN);
QuickSort(1,n);
Ghi;
write('Fini Quick Sort'); readln;
end;
procedure TestMinSort;
begin
Init(MN);
MinSort;
Ghi;
write('Fini Min Sort'); readln;
end;
BEGIN
TestQuickSort;
{TestMinSort;}
END.
// C#
Sng to trong Thut ton v Lp trnh Tp I

111



using System;
using System.IO;
namespace SangTao1
{
/*---------------------------------------
* Sinh du lieu
* Sap tang
* Ghi file
* -------------------------------------*/
class SapTang
{
const int mn = 50000;
const string fn = "SapTang.dat";
static int[] a = new int[mn];
static int n = 0; // so phan tu trong input file

static void Main()
{
Run(150);
Console.ReadLine();
} // Main

static void Run(int nn) // sinh nn phan tu
{
n = nn;
Console.Write("\n Sinh ngau nhien " + n);
Console.WriteLine("\n phan tu cho mang
a[0.." + (n - 1) +
"]");
Gen();
Console.WriteLine("\n Quik Sort...");
QSort(0, n - 1);
Console.WriteLine("\n Ghi file " + fn + "...");
Ghi();
Console.WriteLine("\n Kiem tra lai file " +
fn + "\n\n");
ShowFile();
}
/*------------------------------
* Sinh ngau nhien n so nguyen
* cho mang a[0..n-1]
* -----------------------------*/
static void Gen()
{
Random r = new Random();
for (int i = 0; i < n; ++i) a[i] = r.Next(100);
}
/*------------------------------
* Giai thuat sap (tang) nhanh
* Quick Sort (Hoare T.)
* -----------------------------*/
static void QSort(int d, int c)
{
Sng to trong Thut ton v Lp trnh Tp I

112



int i = d;
int j = c;
int m = a[(i + j) / 2];
int t;
while (i <= j)
{
while (a[i] < m) ++i;
while (m < a[j]) --j;
if (i <= j)
{
t = a[i]; a[i] = a[j]; a[j] = t;
++i; --j;
}
}
if (d < j) QSort(d, j);
if (i < c) QSort(i, c);
}
static void MinSort()
{
int i = 0;
int j = 0;
int t = 0;
for (i = 0; i < n; ++i)
for (j = i + 1; j < n; ++j)
if (a[j] < a[i])
{ t = a[i]; a[i] = a[j]; a[j] = t;}
}
/*----------------------------------
* Ghi du lieu vao file SapTang.Dat
* ---------------------------------*/
static void Ghi()
{
StreamWriter f = File.CreateText(fn);
f.WriteLine(n);
for (int i = 0; i < n; ++i)
f.Write(a[i] + ((i % 10 == 9) ? "\n" : " "));
f.Close();
}
/*-------------------------------
* Doc lai du lieu tu file
* SapTang.dat de kiem tra
* ------------------------------*/
static void ShowFile()
{
Console.WriteLine(File.ReadAllText(fn));
}
} // class
} // SangTao1
Bi 4.5. abc - sp theo ch dn
Cho xu S gm N k t to t cc ch ci 'a'..'z'. ta gi S l xu mu. T xu
mu S ny ngi ta to ra N xu th cp bng cch dch xu S qua tri i v tr
theo dng vng trn, tc l i k t u xu ln lt c chuyn v cui xu, i
Sng to trong Thut ton v Lp trnh Tp I

113



= 0, 1,, N - 1. Nh vy xu th cp vi i = 0 s trng vi xu mu S. Gi s
ta sp tng N xu thu c theo trt t t in. Hy tm xu th k trong dy.
Tn chng trnh: abc.pas.
D liu vo: tp vn bn abc.inp c cu trc nh sau:
- Dng th nht cha hai s t nhin N v k cch nhau qua du cch,
6 s N s 500, 1 s k s N. N cho bit chiu di xu S, k cho bit v tr ca xu
th cp trong dy c sp tng theo th t t in.
- Dng th hai: xu mu S.
D liu ra: tp vn bn abc.out gm mt dng cha xu th k trong dy
c sp.
Th d:
abc.inp abc.out
6 3
dabdec
cdabde

Bi gii
Ta gi xu s ban u l xu mu, cc xu c sinh ra bi php quay l xu th
cp. rng cc xu mu cng l mt xu th cp ng vi php quay 0 v tr. Ta c
th nhn c xu th cp th i bng cch duyt xu mu theo vng trn k t v tr th
i v cui, n v tr th n. Sau duyt tip tc t v tr th 1 n v tr th i - 1. Ta k
hiu xu th cp th i l [i]. Th d, nu xu mu s = 'dabdec' th xu th cp th
2 s l [2] = 'abdecd'. tm xu th k trong dy c sp, trc ht ta cn sp
tng cc xu theo trt t t in sau ly xu th k trong dy c sp lm kt qu.
sp tng c cc xu ny m khng phi sinh ra cc xu mi ta dng mt mng
ph id gi l mng ch dn. Trc khi sp ta gn id[i]:= i. Sau khi sp th id[i] s cho
bit ti v tr th i trong dy c sp l xu th cp no. Trong th d trn, id[3] = 6 l
xu th cp [6]. Gi tr 3 cho bit cn tm xu th k = 3 trong dy sp tng cc xu th
cp. Gi tr 6 cho bit xu cn tm l xu th 6 trong dy cc xu th cp c sinh ra
lc u, tc l lc cha sp.
Xu th cp Sp tng id[i] = ?
[1] = S dabdec [2] 2
C [2] abdecd [3] 3
C [3] bdecda [6] 6
[4] decdab [1] 1
C [5] ecdabd [4] 4
C [6] cdabde [5] 5
Sp ch dn cc xu th cp
Thut ton QuickSort sp nhanh cc xu th cp do Hoare xut c phc tp
N.log
2
N c trnh by nh sau:
Init: for i:=1 to n do id[i]:=i;
procedure idquicksort(d,c: integer);
var i, j, m, y: integer;
begin
i:=d;
j:=c;
Sng to trong Thut ton v Lp trnh Tp I

114



m:=id[(i+j) div 2]; {phan tu giua}
while i <= j do
begin
while Sanh(id[i],m)<0 do inc(i); {doan trai}
while Sanh(m,id[j])<0 do dec(j); {doan phai}
{doi cho neu can}
if (i <= j) then
begin
y:= id[i];
id[i]:= id[j];
id[j]:= y;
inc(i); dec(j);
end;
end;
if d < j then idquicksort(d,j);
if i < c then idquicksort(i,c);
end;
Hm Sanh(i,j) so snh hai xu th cp [i] v [j] theo th t t in v cho gi
tr -1 nu xu th cp [i] nh hn xu th cp [j], cho gi tr 1 nu xu th cp [i] ln
hn xu th cp [j] v 0 nu hai xu ny ging nhau. so snh hai xu theo trt t t
in ta ln lt duyt tng cp k t ca mi xu. Nu hai xu ging nhau ti mi v tr
th ta gn tr 0 cho hm Sanh. Ngc li, nu tm c v tr khc nhau u tin th ta
so snh hai k t s[i] v s[j] ti v tr v gn cho hm Sanh gi tr -1 nu s[i] < s[j],
ngc li, tc l khi s[i] > s[j] th gn gi tr 1 cho hm Sanh.
Ta ch cn lu l vic duyt xu phi thc hin trn vng trn theo chiu quay
ca kim ng h.
function Sanh(i,j: integer): integer;
var k: integer;
begin
for k:=1 to n do
begin
if s[i] <> s[j] then
begin
if s[i] < s[j] then Sanh:=-1
else Sanh:=1;
exit;
end;
if i=n then i:=1 else inc(i);
if j=n then j:=1 else inc(j);
end;
Sanh:=0;
end;
Hoare cng cung cp thm thut ton tm phn t th k trong dy c sp vi
phc tp 2N. Ta vn dng thut ton ny cho bi ton abc. Bn cht thut ton ny l
nh sau. Ta cng sp tng cc xu th cp theo thut ton QuickSort nhng khng sp
ht m ch quan tm n on d liu trong mng c cha phn t th k. Lu rng sau
mt ln chia d liu ca on id[d..c] ta thu c ba on: on id[d..j], id[j+1..i-1] v
id[i..c], trong on gia l id[j+1..i-1] c sp. Nu k ri vo on th nht l
id[d..j] hoc on th ba l id[i..c] th ta ch cn sp tip on . Hm Find(k) cho ra
v tr gc ca xu th cp s ng th k trong dy sp. Trong th d trn
Find(3)=6.
Sng to trong Thut ton v Lp trnh Tp I

115



(*-------------------------------------
Tim phan tu thu k
---------------------------------------*)
function Find(k: integer):integer;
var d, c, i, j, m, y: integer;
begin
d:=1 ;
c:=n;
while d <= c do
begin
i:=d;
j:=c;
m:=id[(i+j) div 2]; {phan tu giua}
while i <= j do
begin
while Sanh(id[i],m)<0 do inc(i); {doan trai}
while Sanh(m,id[j])<0 do dec(j); {doan phai}
{doi cho neu can}
if (i <= j) then
begin
y:= id[i];
id[i]:= id[j];
id[j]:= y;
inc(i); dec(j);
end;
end;
if j < k then d:=i;
if k < i then c:=j;
end;
find:=id[k];
end;
(* Pascal *)
(*----------------------------------
ABC: Tim phan tu thu k
------------------------------------*)
program ABC;
{$B-}
uses crt;
const
MN = 501;
nl = #13#10; {xuong dong}
bl = #32; {dau cach}
fn = 'abc.inp';
gn = 'abc.out';
type
MI = array[0..MN] of integer;
MC = array[0..MN] of char;
var
f,g: text;
s: MC;
id: MI;
Sng to trong Thut ton v Lp trnh Tp I

116



n,k: integer;
(*---------------------------------------------
Doc du lieu:
n: chieu dai xau s,
k: vi tri xau thu cap trong day da sap
----------------------------------------------*)
procedure Doc;
var i: integer;
begin
assign(f,fn); reset(f);
readln(f,n,k);
for i:=1 to n do read(f,s[i]);
close(f);
end;
(*----------------------------------------
So sanh 2 xau thu cap [i] va [j].
Sanh(i,j)
= 0: neu [i] = [j]
= -1: neu [i] < [j]
= 1 neu [i] > [j]
----------------------------------------*)
function Sanh(i,j: integer): integer;
var k: integer;
begin
for k:=1 to n do
begin
if s[i] <> s[j] then
begin
if s[i] < s[j] then Sanh:=-1
else Sanh:=1;
exit;
end;
if i=n then i:=1 else inc(i);
if j=n then j:=1 else inc(j);
end;
Sanh:=0;
end;
(*-------------------------------------
Tim phan tu thu k
---------------------------------------*)
function Find(k: integer):integer;
var d, c, i, j, m, y: integer;
begin
d:=1 ;
c:=n;
while d <= c do
begin
i:=d;
j:=c;
m:=id[(i+j) div 2]; {phan tu giua}
while i <= j do
begin
while Sanh(id[i],m)<0 do inc(i); {doan trai}
Sng to trong Thut ton v Lp trnh Tp I

117



while Sanh(m,id[j])<0 do dec(j); {doan phai}
{doi cho neu can}
if (i <= j) then
begin
y:= id[i];
id[i]:= id[j];
id[j]:= y;
inc(i); dec(j);
end;
end;
if j < k then d:=i;
if k < i then c:=j;
end;
find:=id[k];
end;
{-----------------------------
Ghi ket qua vao tep
-------------------------------}
procedure Ghi(k: integer);
var i: integer;
begin
assign(g,gn); rewrite(g);
for i:=1 to n do
begin
write(g,s[k]);
if k=n then k:=1 else inc(k);
end;
close(g);
end;
procedure run;
var i:integer;
begin
Doc;
for i:=1 to n do id[i]:=i;
Ghi(find(k));
end;
BEGIN
run;
END.
// C#
using System;
using System.IO;
namespace SangTao1
{
/*----------------------------------------
* Tim xau mau thu k voi do phuc tap 2N
* -------------------------------------*/
class abc
{
const int mn = 500;
const string fn = "abc.inp";
Sng to trong Thut ton v Lp trnh Tp I

118



const string gn = "abc.out";
static string s;
static int n = 0; // chieu dai xau mau
static int k = 0; // xau thu k
static int[] id;

static void Main()
{
Run();
Console.ReadLine();
} // Main

static void Run()
{
Doc();
Console.WriteLine(n + " " + k + " " + s);
id = new int[n];
for (int i = 0; i < n; ++i) id[i] = i;
PhanTuGiua();
Ghi();
Test();
Console.WriteLine("\n Fini");
}
/*----------------------------
* Ghi dong thu k trong
* day da sap vao file gn
* ---------------------------*/
static void Ghi()
{
StreamWriter g = File.CreateText(gn);
int j = id[k-1];
for (int i = 0; i < n; ++i)
g.Write(s[(j + i) % n]);
g.Close();
}
/*------------------------------
* Hien thi dong thu s[j...]
* -----------------------------*/
static void PrintLine(int j)
{
for (int i = 0; i < n; ++i)
Console.Write(s[(j + i) % n]);
Console.WriteLine();
}
static void Doc()
{
char[] cc = new char[] { ' ', '\n', '\t', '\r'};
string [] ss = (File.ReadAllText(fn)).Split(cc,
StringSplitOptions.RemoveEmptyEntries);
n = int.Parse(ss[0].Trim()); // do dai xau mau
k = int.Parse(ss[1].Trim()); // xau thu k
s = ss[2]; // xau mau
}
Sng to trong Thut ton v Lp trnh Tp I

119



static void PhanTuGiua() // Tim phan tu thu k
{
int m;
int d = 0;
int c = n - 1;
int i = 0;
int j = 0;
int t = 0;
int k0 = k - 1; // xau thu k tinh tu 1
while (d <= c)
{
i = d;
j = c;
m = id[(i + j) / 2];
while (Sanh(id[i], m) < 0) ++i;
while (Sanh(m, id[j]) < 0) --j;
if (i <= j)
{
t = id[i]; id[i] = id[j]; id[j] = t;
++i; --j;
}
if (j < k0) d = i;
if (k < i) c = j;
}
}
// so sanh 2 xau thu cap s[x...] va s[y..]
static int Sanh(int x, int y)
{
int ix = 0;
int iy = 0;
for (int i = 0; i < n; ++i)
{
ix = (x + i) % n;
iy = (y + i) % n;
if (s[ix] != s[iy])
return (s[ix] < s[iy]) ? -1 : 1;
}
return 0;
}
static void IdQSort(int d, int c)// sap theo chi dan
{
int i = d;
int j = c;
int m = id[(i + j) / 2];
int t = 0;
while (i <= j)
{
while (Sanh(id[i], m) < 0) ++i;
while (Sanh(m, id[j]) < 0) --j;
if (i <= j)
{
t = id[i]; id[i] = id[j]; id[j] = t;
++i; --j;
Sng to trong Thut ton v Lp trnh Tp I

120



}
}
if (d < j) IdQSort(d, i);
if (i < c) IdQSort(i, c);
}
/*-------------------------------
* Kiem tra lai bang cach dung
* thuat toan QSort theo chi dan
* ------------------------------*/
static void Test()
{
Console.WriteLine("\n Xau mau: " + s);
for (int i = 0; i < n; ++i) id[i] = i;
IdQSort(0, n - 1);
Console.WriteLine("\n Day sap tang: \n");
for (int i = 0; i < n; ++i)
{
Console.Write((i + 1) + ". ");
PrintLine(id[i]);
}
Console.WriteLine();
Console.WriteLine("\n Xau thu " + k);
PrintLine(id[k-1]);
Console.WriteLine("\n Xau ghi trong file " + gn);
Console.WriteLine(File.ReadAllText(gn));
}
} // class
} // SangTao1
Bi 4.6. Xu mu
Mt tp vn bn f c tn STRINGS.INP cha cc xu k t, mi dng ghi mt
xu c chiu di ti a 250 k t. Xu u tin c gi l xu mu s. Lp
trnh:
c xu mu s t tp f, ghi vo tp vn bn g c tn STRINGS.OUT. Sau
c tng xu x cn li ca f, vi mi xu x cn ghi vo g cc thng tin sau:
- ni dung xu x;
- hai s v v d cch nhau qua du cch, trong v l v tr xut hin v d
l chiu di ln nht ca khc u ca x trong xu mu s. Nu v nghim
th ghi -1 0.
Th d:
STRINGS.INP STRINGS.OUT
cabxabcdab
abcd
cdaeh
cabxabcdab
abcd
5 4
cdaeh
7 3
Thut ton
Vi mi xu k t w ta k hiu w[i..j], i s j, v gi l on, l xu gm dy k t lin
tip t w[i] n w[j] trong xu w. Th d, nu w = 'cabxabcdab' th w[5..8] = 'abcd'. Gi
Sng to trong Thut ton v Lp trnh Tp I

121



s l xu mu, x l xu cn kho st. Nhim v ca ta l tm v tr v v chiu di ln nht
d x[1..d] = s[v..(v + d 1)]. Ta vn dng k thut t chc hu t nh sau.
Hu t ca mt xu l on cui ca xu . Nh vy mt xu c chiu di n s c
n hu t. Th d, vi xu mu s[1..10] = 'cabxabcdab' ta c 10 hu t sau
y:
s[1..10] = 'cabxabcdab'
s[2..10] = 'abxabcdab'
s[3..10] = 'bxabcdab'
s[4..10] = 'xabcdab'
s[5..10] = 'abcdab'
s[6..10] = 'bcdab'
s[7..10] = 'cdab'
s[8..10] = 'dab'
s[9..10] = 'ab'
s[10..10] = 'b'
Nh vy, hu t sau s nhn c t hu t st trc n bng cch b i k t
u tin.
Trc ht ta sp tng cc hu t ca xu mu s theo trt t t in. S dng mt
mng ch dn id, trong id[i] tr n v tr u tin ca hu t trong xu mu. C th
l, nu id[i] = k th hu t tng ng s l s[k..n]. Sau khi sp tng cc hu t ca xu
mu s[1..10] = 'cabxabcdab' ta thu c:

i id[i] Hu t Xu
1 9
S[9..10] ab
2 5
S[5..10] abcdab
3 2
S[2..10] abxabcdab
4 10
S[10..10] b
5 6
S[6..10] bcdab
6 3
S[3..10] bxabcdab
7 1
S[1..10] cabxabcdab
8 7
S[7..10] cdab
9 8
S[8..10] dab
10 4
S[4..10] xabcdab
Sp tng theo ch dn cc hu t ca xu
s[1..10] = 'cabxabcdab'
Vic cn li l so snh xu x vi cc hu t s[i..j] tm khc u chung di nht
gia chng. Th d, vi x[1..4]='abcd' th khc u chung di nht tm c vi
hu t s[5..10] do id[2] tr ti. V tr v tm c s l 5 v chiu di ln nht d s l 4.
Phn chnh ca chng trnh s nh sau:
procedure Run;
begin
...
n:= length(s);
Sng to trong Thut ton v Lp trnh Tp I

122



for i:=1 to n do id[i]:=i;
IdQuikSort(1,n);
while not seekeof(f) do
begin
readln(f,x);
writeln(g,x);
Tim; {xac dinh v v d}
writeln(g,v,BL,d);
end;
end;
rng vi mi xu x, nu phn t u tin ca x l x[1] khng trng vi phn t
u tin ca hu t h th chiu di ca khc u chung ca chng s bng 0. Nh nhn
xt ny v do dy cc hu t c sp tng nn vi mi xu x, trc ht ta gi hm
Binsearch thc hin tm kim nh phn phn t x[1] trong dy gm cc phn t
u tin ca cc hu t, sau ta thc hin vic duyt tm.
procedure Tim;
var
i,Len: integer;
begin
v:=BinSearch; d := 0;
if v=0 then exit;
Maxlen:=0;
for i:=v to n do
begin
if s[id[i]]<>x[1] then exit;
Len:=Eqsx(id[i]);
if Len > d then
begin
d:=Len;
v:=id[i];
end;
end;
end;
Hm BinSearch s cho ra ch dn ti hu t h u tin tho iu kin h[1] =
x[1].
(*---------------------------------
Tim xuat hien cua x[1]trong day
da sap cac hau to
---------------------------------*)
function BinSearch:integer;
var
d,c,m: integer;
begin
d:=1;
c:=n;
repeat
m:=(d+c) div 2;
if x[1]>s[id[m]] then d:=m+1
else c:=m;
until d=c;
Sng to trong Thut ton v Lp trnh Tp I

123



if x[1]<>s[id[d]] then Binsearch := -1
else BinSearch := d;
end;
Hm Eqsx(i) cho ta chiu di ln nht ca khc u chung gia hu t s[i..n] v
xu x.
(*---------------------------------
Khuc dau dai nhat giua
hau to s[i..n] va x
---------------------------------*)
function Eqsx(i:integer): integer;
var
k,m:integer;
begin
m:=min(length(x),n-i+1);
for k:=1 to m do
if s[i+k-1]<>x[k] then
begin
Eqsx:=k-1;
exit;
end;
Eqsx:=m;
end;
(* Pascal *)
(*----------------------
STRINGS: Xau mau
------------------------*)
program Strings;
{$B-}
uses crt;
const
MN = 255;
cd = #0; {ki tu trong}
cc = #255; {ki tu cuoi cua bang ma ASCII}
BL=#32; {dau cach}
fn = 'strings.inp'; {tep vao}
gn = 'strings.out'; {tep ra}
type
mb1 = array[0..MN] of integer;
var
f,g: text;
s,x: string; {s: xau mau}
id: mb1; {chi dan}
n: integer; {chieu dai xau mau s}
v,d: integer;
{v: vi tri xuat hien khuc dau cua x trong xau mau s}
{d: maxlen}
(*-------------------------------
min cua 2 phan tu
--------------------------------*)
Sng to trong Thut ton v Lp trnh Tp I

124



function min(a,b:integer):integer;
begin
if a<=b then min:=a
else min:=b;
end;
(*-------------------------------
Tim xuat hien cua x[1] trong day da sap cac hau to
-------------------------------*)
function BinSearch:integer;
var
d,c,m: integer;
begin
d:=1;
c:=n;
repeat
m:=(d+c) div 2;
if x[1]>s[id[m]] then d:=m+1
else c:=m;
until d=c;
if x[1]<>s[id[d]] then Binsearch:=0
else BinSearch:=d;
end;
(*--------------------------------------
so sanh 2 hau to trong s:
s[i..n] va s[j..n]
---------------------------------------*)
function sanh(i,j:integer):integer;
var k:integer;
begin
for k:=0 to min(n-i,n-j) do
if s[i+k]<>s[j+k] then
begin
if s[i+k]<s[j+k] then sanh:=-1
else sanh:=1;
exit;
end;
if i=j then sanh:=0
else if i<j then sanh:=1
else sanh:=-1;
end;
(*-------------------------------------
Quick sort cac hau to theo chi dan
-------------------------------------*)
procedure IdQuickSort(d,c: integer);
var i,j,m,t: integer;
begin
i:=d; {dau}
j:=c; {cuoi}
m:=id[(i+j) div 2]; {phan tu giua}
while i<=j do
begin
Sng to trong Thut ton v Lp trnh Tp I

125



while sanh(id[i],m)<0 do inc(i);
while sanh(id[j],m)>0 do dec(j);
if (i<=j) then
begin
t:=id[i];
id[i]:=id[j];
id[j]:=t;
inc(i); dec(j);
end;
end;
if d<j then IdQuickSort(d,j);
if i<c then IdQuickSort(i,c);
end;
(*------------------------------------------
Khuc dau dai nhat giua hau to s[i..n] va x
-------------------------------------------*)
function Eqsx(i:integer): integer;
var k,m:integer;
begin
m:=min(length(x),n-i+1);
for k:=1 to m do
if s[i+k-1]<>x[k] then
begin
Eqsx:=k-1;
exit;
end;
Eqsx:=m;
end;
(*--------------------------------------------
Tim vi tri va chieu dai lon nhat
MaxLen giua cac hau to cua xau mau s va xau x
---------------------------------------------*)
procedure Tim;
var i,Len: integer;
begin
v:=BinSearch;
d:=0;
if v=0 then exit;
for i:=v to n do
begin
if s[id[i]]<>x[1] then exit;
Len:=Eqsx(id[i]);
if Len > d then
begin
d:=Len;
v:=id[i];
end;
end;
end;
procedure Run;
Sng to trong Thut ton v Lp trnh Tp I

126



var i:integer;
begin
assign(f,fn);
reset(f);
assign(g,gn);
rewrite(g);
readln(f, s);
writeln(g,s);
n:= length(s);
for i:=1 to n do id[i]:=i;
IdQuickSort(1,n);
while not seekeof(f) do
begin
readln(f,x);
writeln(g,x);
Tim;
writeln(g,v,BL,d);
end;
close(f);
close(g);
end;
BEGIN
Run;
END.
D liu kim th
STRINGS.INP
Kt qu d kin
STRINGS.OUT
cabxabcdab
abcd
cdaeh
cabxabcdab
abcd
5 4
cdaeh
7 3
// C#
using System;
using System.IO;
namespace SangTao1
{
/*------------------------
* Xau mau
* ----------------------*/
class Strings
{
const string fn = "strings.inp";
const string gn = "strings.out";
static string s; // xau mau
static string x; // xau can xu ly
Sng to trong Thut ton v Lp trnh Tp I

127



static int[] id;
static int v = 0;// vi tri xuat hien khuc dau x trg s
static int d = 0;// chieu dai x trong s
static int n = 0; // chieu dai xau mau
static void Main()
{
Run();
Test();
Console.ReadLine();
} // Main

// Doc lai file gn de kiem tra ket qua
static void Test()
{
Console.WriteLine("\n Kiem tra lai ket qua \n\n");
Console.WriteLine("\n Input: " +
File.ReadAllText(fn));
Console.WriteLine("\n Output: " +
File.ReadAllText(gn));
}
static void Run()
{
StreamReader f = File.OpenText(fn);
StreamWriter g = File.CreateText(gn);
// Bo qua cac dong trong dau tien
while ((s = (f.ReadLine()).Trim()) == "") ;
n = s.Length; // Len xau mau
id = new int[n];
// Khoi tri cho index
for (int i = 0; i < n; ++i) id[i] = i;
IdQSort(0, n - 1);
Console.WriteLine(" Xau mau: " + s + "\n\n");
SPrint();
g.WriteLine(s);
while ((x = f.ReadLine()) != null)
{
x = x.Trim();
if (x != "")
{
Console.WriteLine(x);
g.WriteLine(x);
Find();
g.WriteLine(v + " " + d);
}
}
Sng to trong Thut ton v Lp trnh Tp I

128



f.Close(); g.Close();
}
static void Find()
{
v = BinSearch(x[0]);// hau to co ki tu dau la x[0]
d = 0;
if (v < 0) return;
for (int i = v; i < n; ++i)
{
int j = id[i];
if (s[j] != x[0]) return;
int k = ComLen(x, j);
if (d < k) { v = j + 1; d = k;}
}
}
// MaxLen khuc dau cua x va hau to s[j...
static int ComLen(string x, int j)
{
int minlen = Min(x.Length, n - j);
for (int i = 0; i < minlen; ++i)
if (x[i] != s[j + i]) return i;
return minlen;
}
static int Min(int a, int b)
{ return (a < b) ? a : b;}
static int BinSearch(char c)
{
int i = 0;
int j = n - 1;
int m = 0;
while (i < j)
{
m = (i + j) / 2;
if (s[id[m]] < c) i = m + 1;
else j = m;
}
return (s[id[i]] == c) ? i : -1;
}
// Hien thi day duoc sap cac hau to
// cua s de kiem tra
static void SPrint()
{
Console.WriteLine("\n Cac hau to sap tang: \n");
for (int i = 0; i < n; ++i)
Console.WriteLine(s.Substring(id[i], n - id[i]));
Sng to trong Thut ton v Lp trnh Tp I

129



}
static void IdQSort(int d, int c)
{
int i = d;
int j = c;
int m = id[(i + j) / 2];
int t = 0;
while (i <= j)
{
while (Sanh(id[i], m) < 0) ++i;
while (Sanh(m, id[j]) < 0) --j;
if (i <= j)
{
t = id[i]; id[i] = id[j]; id[j] = t;
++i; --j;
}
}
if (d < j) IdQSort(d, j);
if (i < c) IdQSort(i, c);
}
static int Sanh(int x, int y)
{
int ix = 0;
int iy = 0;
for (int i = 0; i < n; ++i)
{
ix = (x + i) % n;
iy = (y + i) % n;
if (s[ix] != s[iy])
return (s[ix] < s[iy]) ? -1 : 1;
}
return 0;
}
} // Strings
} // SangTao1

CHNG 5
PHNG PHP THAM LAM
Sng to trong Thut ton v Lp trnh Tp I

130





Phng php tham lam gi chng ta tm mt trt t hp l duyt d liu nhm
t c mc tiu mt cch chc chn v nhanh chng. Thng thng, d liu c
duyt theo mt trong hai trt t l tng hoc gim dn theo mt ch tiu no . Mt s
bi ton i hi nhng dng thc ci bin ca hai dng ni trn.
Bi 5.1. Bng nhc
Ngi ta cn ghi N bi ht, c m s t 1 n N, vo mt bng nhc c thi
lng tnh theo pht cha ton b cc bi cho. Vi mi bi ht ta bit
thi lng pht ca bi . Bng s c lp vo mt my pht nhc t trong
mt siu th. Khch hng mun nghe bi ht no ch vic nhn phm ng vi
bi . tm v pht bi th i trn bng, my xut pht t u cun bng,
quay bng b qua i 1 bi ghi trc bi . Thi gian quay bng b qua
mi bi v thi gian pht bi c tnh l nh nhau. Tnh trung bnh, cc
bi ht trong mt ngy c khch hng la chn vi s ln (tn sut) nh
nhau. Hy tm cch ghi cc bi trn bng sao cho tng thi gian quay bng
trong mi ngy l t nht.
D liu vo c ghi trong tp vn bn tn BANGNHAC.INP.
- Dng u tin l s t nhin N cho bit s lng bi ht.
- Tip n l N s nguyn dng th hin dung lng tnh theo pht ca
mi bi. Mi n v d liu cch nhau qua du cch.

Th d di y cho bit c N = 3 bi ht:
- Bi 1 pht trong thi gian 7 pht.
- Bi 2 pht trong thi gian 2 pht.
- Bi 3 pht trong thi gian 3 pht.
D liu ra c ghi trong tp vn bn
BANGNHAC.OUT theo dng thc sau:
- N dng u tin th hin trt t ghi bi ht trn bng: m i dng gm hai s nguyn
dng j v d cch nhau bi du cch, trong j l m s ca bi ht cn ghi, d l thi
gian tm v pht bi theo trt t ghi ny.
- Dng th n + 1 ghi tng s thi gian quay bng nu mi bi ht c pht mt ln
trong ngy.
Vi th d trn, kt qu thu c s nh sau:
- Cn ghi ln lt trn bng cc bi theo trt t : bi 2, bi 3, bi 1;
- tm v pht bi 2 cn 2 pht;
- tm v pht bi 3 cn 5 pht;
- tm v pht bi 1 cn 12 pht;
- Tng thi gian tm v pht mi bi mt ln l: 19 pht.
Thut ton
Gi s ta c ba bi ht vi s pht ln lt nh sau:
M s bi ht
C C
Thi gian pht 7 2 3
Ta xt vi tnh hung ghi bng rt ra kt lun cn thit.
BANGNHAC.INP
3
7 2 3
BANGNHAC.OUT
2 2
3 5
1 12
19
Sng to trong Thut ton v Lp trnh Tp I

131



Trt t ghi trn bng
(x, y, z)
Thi gian pht
t(x) + t(y) + t(z); t(i): thi gian tm v pht bi i
( , C , C) (7) + (7 + 2) + (7 + 2 + 3) = 28 pht
( , C , C) (7) + (7 + 3) + (7 + 3 + 2) = 29 pht
(C , , C) (2) + (2 + 7) + (2 + 7 + 3) = 23 pht
(C , C , ) (2) + (2 + 3) + (2 + 3 + 7) = 19 pht (phng n ti u)
(C , , C) (3) + (3 + 7) + (3 + 7 + 2) = 25 pht
(C , C , ) (3) + (3 + 2) + (3 + 2 + 7) = 20 pht
Vy phng n ti u s l (C , C , ): ghi bi 2 ri n bi 3, cui cng ghi bi
1. Tng thi gian theo phng n ny l 19 pht.
c phng n ti u ta ch cn ghi bng theo trt t tng dn ca thi lng. Bi
ton c cho vi gi thit bng ln ghi c ton b cc bi. D dng sa
chng trnh vn dng cho trng hp dung lng tng hn ch trong M pht.
Chng trnh sp xp d liu theo ch dn.
(* Pascal *)
(*----------------------
BangNhac.pas
-----------------------*)
program BangNhac;
uses crt;
const
MN = 200; BL = #32; {dau cach}
fn = 'Bangnhac.inp'; gn = 'Bangnhac.out';
var
a,id: array[1..MN] of integer;
f, g: text;
n: integer;
{------------------------------------
Doc du lieu tu input file vao mang a
-------------------------------------}
procedure Doc;
var i,k: integer;
begin
assign(f,fn); reset(f); read(f,n);
for i := 1 to n do read(f,a[i]);
close(f);
end;
{---------------------------------
Khoi tri mang chi dan id
quan li sap tang theo chi dan
----------------------------------}
procedure InitID;
var i: integer;
begin
for i := 1 to n do id[i] := i;
end;
{---------------------------------
Sap tang theo chi dan
----------------------------------}
Sng to trong Thut ton v Lp trnh Tp I

132



procedure IDQuickSort(d,c: integer);
var i, j, m, x: integer;
begin
i := d;
j := c;
m := a[id[(i+j) div 2]]; {phan tu giua}
while i <= j do
begin
while a[id[i]] < m do inc(i);
while a[id[j]] > m do dec(j);
if i <= j then
begin
x := id[i];
id[i] := id[j];
id[j] := x;
inc(i); dec(j);
end;
end;
if d < j then IDQuickSort(d,j);
if i < c then IDQuickSort(i,c);
end;
{-------------------------------
Ghi ket qua vao output file
--------------------------------}
procedure Ghi;
var i, t, tt: longint;
begin
assign(g,gn); rewrite(g);
t := 0; {thoi gian tim va phat 1 bai}
tt := 0; {tong thoi gian cho n bai}
for i := 1 to n do
begin
t := t + a[id[i]];
tt := tt + t;
writeln(g,id[i],BL,t);
end;
writeln(g,tt); close(g);
end;
BEGIN
Doc; InitID; IDQuickSort(1,n); Ghi;
END.
// C#
using System;
using System.IO;
namespace SangTao1
{
/*-------------------------------------
* Bang nhac
* -----------------------------------*/
class BangNhac
{
const string fn = "BangNhac.inp";
Sng to trong Thut ton v Lp trnh Tp I

133



const string gn = "BangNhac.out";
static public Bang[] b;
static public int n = 0; // so bai hat
static void Main()
{
Doc(); QSort(0, n-1);
Ghi(); Test();
Console.WriteLine("\n Fini ");
Console.ReadLine();
}
static void Ghi()
{
StreamWriter g = File.CreateText(gn);
int t = 0; // tg tim va phat 1 bai
int tt = 0; // tong tg tim va phat n bai
for (int i = 0; i < n; ++i)
{
t += b[i].len;
tt += t;
g.WriteLine(b[i].id + " " + t);
}
g.WriteLine(tt); g.Close();
}
static void QSort(int d, int c)
{
int i = d, j = c, m = b[(i+j)/2].len;
Bang t = new Bang(0,0);
while (i <= j)
{
while (b[i].len < m) ++i;
while (m < b[j].len) --j;
if (i <= j)
{
t = b[i]; b[i] = b[j];
b[j] = t; ++i; --j;
}
}
if (d < j) QSort(d, j);
if (i < c) QSort(i, c);
}
// Doc lai file gn de kiem tra ket qua
static void Test() t vit
static void Doc()
{
int [] a = Array.ConvertAll(
(File.ReadAllText(fn)).Split(
new char[] { '\n', ' ', '\t', '\0', '\r'},
StringSplitOptions.RemoveEmptyEntries),
new Converter<string, int>(int.Parse));
n = a[0];
Sng to trong Thut ton v Lp trnh Tp I

134



b = new Bang[n];
for (int i = 1; i <= n; ++i)
b[i-1] = new Bang(a[i],i);
}
public struct Bang
{
public int len;// thoi luong
public int id; // so hieu 1,2,...
public Bang(int t, int nn)
{ len = t; id = nn;}
}
} // BangNhac
} // SangTao1
Bi 5.2. Xp vic
C N cng vic cn thc hin trn mt my tnh, mi vic i hi ng 1 gi
my. Vi mi vic ta bit thi hn phi np kt qu thc hin sau khi hon thnh
vic v tin thng thu c nu np kt qu trc hoc ng thi im quy
nh. Ch c mt my tnh trong tay, hy lp lch thc hin N cng vic trn
my tnh sao cho tng s tin thng thu c l ln nht v thi gian hot ng
ca my l nh nht. Gi thit rng my c khi ng vo u ca, thi im
t = 0 v ch tt my sau khi hon thnh N cng vic.
D liu vo: tp vn bn viec.inp:
- Dng u tin l s N.
- N dng tip theo: mi vic c m t bng hai s t nhin, s th nht l thi
hn giao np, s th hai l tin thng. Cc s cch nhau bi du cch.
Th d:
viec.inp
4
1 15
3 10
5 100
1 27
ngha: Cho bit c 4 vic vi cc thng tin sau:
- Vic th nht phi np khng mun hn thi im 1 (gi) vi
tin thng 15 (ngn ng);
- Vic th hai phi np khng mun hn thi im 3 (gi) vi tin
thng 10 (ngn ng);
- Vic th ba phi np khng mun hn thi im 5 (gi) vi tin
thng 100 (ngn ng);
- Vic th t phi np khng mun hn thi im 1 (gi) vi tin
thng 27 (ngn ng).
D liu ra: tp vn bn viec.out:
- N dng u tin, dng th t ghi mt s t nhin i cho bit vic th i c
lm trong gi t.
- Dng cui cng ghi tng s tin thu c.
Vi th d trn, tp viec.out s nh sau:
viec.out
4
2
3
1
137
ngha:
- Gi th 1 thc hin vic 4 v np ng hn nn c
thng 27;
- Gi th 2 thc hin vic 2 v np trc hn nn c
thng 10;
- Gi th 3 thc hin vic 3 v np trc hn nn c
Sng to trong Thut ton v Lp trnh Tp I

135



thng 100;
- Gi th 4 thc hin vic 1;
- Tng tin thng thu c do hon thnh ng hn
ba vic 4, 2 v 3 l 27 + 10 + 100 = 137.

Thut ton
Ta u tin cho nhng vic c tin thng cao, do ta sp cc vic gim dn theo
tin thng. Vi mi vic k ta bit thi hn giao np vic l h = t[k]. Ta xt trc
thi gian b. Nu gi h trn trc bn do vic khc th ta tm t thi im h tr v
trc mt thi im c th thc hin c vic k . Nu tm c mt thi im m nh
vy, ta nh du bng m s ca vic trn trc thi gian b, b[m]:= k. Sau khi xp
vic xong, c th trn trc thi gian cn nhng thi im ri, ta dn cc vic xp v
pha trc nhm thu c mt lch lm vic tr mt, tc l khng c gi trng. Cui
cng ta xp tip nhng vic trc xt nhng khng xp c. y l nhng vic
phi lm nhng khng th np ng hn nn s khng c tin thng. Vi th d
cho, N = 4, thi hn giao np t = (1, 3, 5, 1) v tin thng a = (15, 10, 100, 27) ta
tnh ton nh sau:
- Khi tr: trc thi gian vi 5 thi im ng vi Tmax = 5 l th im mun
nht phi np kt qu, Tmax = max { thi hn giao np }, b = (0, 0, 0, 0,0).
- Chn vic 3 c tin thng ln nht l 100. Xp vic 3 vi thi hn t[3] = 5 vo
h: h[5] = 3. Ta thu c h = (0, 0, 0, 0, 3).
- Chn tip vic 4 c tin thng 27. Xp vic 4 vi thi hn t[4] = 1 vo h: h[1]
= 4. Ta thu c h = (4, 0, 0, 0, 3).
- Chn tip vic 1 c tin thng 15. Xp vic 1 vi thi hn t[1] = 1 vo h:
Khng xp c v t thi im 1 tr v trc trc thi gian h[1..1] kn. Ta
thu c h = (4, 0, 0, 0, 3).
- Chn nt vic 2 c tin thng 10. Xp vic 2 vi thi hn t[2] = 3 vo h:
h[3] = 2.
- Ta thu c h = (4, 0, 2, 0, 3).
- Dn vic trn trc thi gian h, ta thu c h = (4, 2, 3, 0, 0).
- Xp nt vic phi lm m khng c thng, ta thu c h = (4, 2, 3, 1).
- Ca lm vic ko di ng N = 4 gi.
- Nu khng mun sp gim mng tin thng a theo ch dn ta c th sp song
song a v id nh m t trong chng trnh.
Trong chng trnh di y ta s dng mng id vi hai mc ch: id[i] = v > 0
cho bit vic v ng th i trong dy c sp gim theo gi tr tin thng v vic v
cha c xp. id[i] = v < 0 cho bit vic v xp xong trong ln duyt u tin.
(* Pascal *)
(*----------------------
VIEC.PAS Chon viec
-----------------------*)
program viec;
uses crt;
const
MN = 200; bl = #32; {dau cach}
nl = #13#10; {xuong dong}
fn = 'viec.inp'; {input file}
Sng to trong Thut ton v Lp trnh Tp I

136



gn = 'viec.out'; {output file}
var
a,id,t: array[1..MN] of integer;
{a: tien thuong, t: thoi han giao nop}
{id: chi dan}
h: array[0..MN] of integer; {truc thoi gian}
N: integer; {so luong viec}
f,g: text;
M: integer; {so viec da xep}
tt: longint; {tong so tien thuong}
(*----------------------------
Doc du lieu tu input file
------------------------------*)
procedure Doc;
var i,k: integer;
begin
assign(f,fn); reset(f);
readln(f,N);
for i := 1 to N do
readln(f,t[i],a[i]);
close(f);
end;
(*----------------------------
Khoi tri cho mang chi dan id
------------------------------*)
procedure InitID;
var i: integer;
begin
for i := 1 to N do id[i] := i;
end;
(*-----------------------------------
Sap giam a[1..N] theo chi dan
--------------------------------------*)
procedure IDQuickSort(d,c: integer);
var i, j, m, k: integer;
begin
i := d; j := c;
m := a[id[(i+j) div 2]]; {phan tu giua}
while i <= j do
begin
while a[id[i]] > m do inc(i);
while a[id[j]] < m do dec(j);
if i <= j then
begin
k := id[i];
id[i] := id[j];
id[j] := k;
inc(i); dec(j);
end;
end;
if d < j then IDQuickSort(d,j);
if i < c then IDQuickSort(i,c);
end;
Sng to trong Thut ton v Lp trnh Tp I

137



(*-------------------------------------
Xep viec theo giai thuat tham lam
---------------------------------------*)
procedure XepViec;
var i,k,v: integer;
begin
fillchar(h,sizeof(h),0);
for i := 1 to N do
begin
v := id[i]; {viec nao}
for k := t[v] downto 1 do
if h[k]= 0 then
begin
{xep duoc viec v tai thoi diem k}
h[k] := v;
id[i] := -v;
break;
end;
end;
end;
(*------------------------------------
Don cac viec da xep trong h len phia truoc
va tinh tong tien thuong
-------------------------------------*)
procedure DonViec;
var i: integer;
begin
tt := 0;
{tim gio trong dau tien trong h}
for i := 1 to MN do
if h[i]=0 then
begin
M := i;
break;
end
else tt := tt+a[h[i]];
if M > N then exit;
for i := M+1 to MN do
if h[i] > 0 then
begin
h[M] := h[i];
tt := tt+a[h[i]];
inc(M);
if M > N then exit;
end;
end;
(*---------------------------------------
Xep not cac viec con lai
----------------------------------------*)
procedure XepTiep;
var i: integer;
begin
for i := 1 to N do
Sng to trong Thut ton v Lp trnh Tp I

138



if id[i] > 0 then
begin
h[M] := id[i];
inc(M);
end;
end;
(*-----------------------------
Ghi ket qua
------------------------------*)
procedure GhiTep;
var i: integer;
begin
assign(g,gn); rewrite(g);
for i := 1 to N do
writeln(g,h[i]);
writeln(g,tt); close(g);
end;
BEGIN
Doc; InitID; IDQuickSort(1,n);
XepViec; DonViec; XepTiep; GhiTep;

END.

// C#
using System;
using System.IO;
namespace SangTao1
{
/*------------------------
* Xep viec
* ----------------------*/
class XepViec
{
const int mn = 280;
const string fn = "Viec.inp";
const string gn = "Viec.out";
static public Viec [] v; // cac viec
static public int n = 0; // so luong viec
static public int tong = 0;
static public int[] h;
static public int k = 0;
static void Main()
{
Doc(); QSort(0, n-1);
Xep(); Ghi(); Test();
Console.ReadLine();
} // Main

static void Xep()
{
// Tim Tmax
Sng to trong Thut ton v Lp trnh Tp I

139



int tmax = 0;
for (int i = 0; i < n; ++i)
if (v[i].t > tmax) tmax = v[i].t;
int tt = tmax + n + 1;
h = new int[tt];
// Khoi tri cho h
for (int i = 0; i < tt; ++i) h[i] = 0;
tong = 0;
for (int i = 0; i < n; ++i)
{
int td = v[i].t;
while (h[td] > 0) --td;
if (td == 0)
h[++tmax] = v[i].id; //viec ko thg
else
{
h[td] = v[i].id;
tong += v[i].thuong;
}
}
// Dich cac viec len phia truoc
k = 0;
for (k = 1; k <= tmax; ++k)
if (h[k] == 0) break;
for (int i = k + 1; i <= tmax; ++i)
if (h[i] > 0)
h[k++] = h[i];
}
static void Ghi() // Ghi file
{
StreamWriter g = File.CreateText(gn);
for (int i = 1; i < k; ++i)
g.WriteLine(h[i]);
g.WriteLine(tong); g.Close();
}
// Sap cac viec giam theo tien thuong
static void QSort(int d, int c)
{
int i = d;
int j = c;
int m = v[(d + c) / 2].thuong;
Viec t = new Viec(0, 0, 0);
while (i <= j)
{
while (v[i].thuong > m) ++i;
while (m > v[j].thuong) --j;
Sng to trong Thut ton v Lp trnh Tp I

140



if (i <= j)
{
t = v[i]; v[i] = v[j]; v[j] = t;
++i; --j;
}
}
if (d < j) QSort(d, j);
if (i < c) QSort(i, c);
}
// Doc lai file gn de kiem tra ket qua
static void Test() t vit
static void Doc()
{
int [] a = Array.ConvertAll(
(File.ReadAllText(fn)).Split(
new char[] { '\n', ' ', '\t', '\0', '\r' },
StringSplitOptions.RemoveEmptyEntries),
new Converter<string, int>(int.Parse));
n = a[0];
v = new Viec[n];
Console.WriteLine(" n = " + n);
int k = 1;
for (int i = 0; i < n; ++i)
v[i] = new Viec(a[k++],a[k++],i+1);
}
public struct Viec
{
public int t; // Thoi han giao nop
public int thuong; // Tien thuong
public int id; // Ma so
public Viec(int th, int thg, int nn)
{ t = th; thuong = thg; id = nn; }
}
} // XepViec
} // SangTao1
Bi 5.3. Xp ba l
C N vt (mt hng), vi mi vt ta bit trng lng v gi tr ca n. Hy xc
nh trng lng cn ly mt s vt xp vo mt ba l c sc cha ti a
l M sao cho gi tr cha trong ba l l ln nht. Gi thit l c th ly mt t
l tu mi vt.
D liu vo: Tp vn bn balo.inp:
- Dng u tin: hai gi tr nguyn dng N v M.
- N dng tip theo, mi dng cha hai gi tr nguyn dng d v cho mi vt,
trong d l trng lng, v l gi tr tnh theo mt n v trng lng ca
vt (n gi). Cc s cch nhau qua du cch.
BALO.INP
5 30
8 5
5 4
4 2
C N = 5 vt v sc cha ti a ca ba l l
M = 30 (kg).
- Vt th nht c trng lng 8, n gi 5
tr/kg,
- Vt th hai c trng lng 5, n gi 4,
BALO.OUT
8
3
0
3
Sng to trong Thut ton v Lp trnh Tp I

141



3 8
16 6

- Vt th ba c trng lng 4, n gi 2,
- Vt th t c trng lng 3, n gi 8,
- Vt th nm c trng lng 16, n gi 6.
(tr. - triu ng)
16
172
D liu ra: Tp vn bn tn balo.out:
- N dng, dng th i cho bit trng lng cn ly vt th i.
- Dng cui cng ghi tng gi tr thu c.
Hng dn
C nhiu bi ton thuc h xp ba l, thut ton cho bi ny thuc lp tham lam.
D thy tiu chun chn l gi n v cao. Ta duyt cc vt theo gi n v t cao
tr xung. Vt c chn s c ly ti a. Nh vy, nu tng trng lng cc vt
bng hoc ln hn sc mang ca ba l th bao gi ba l cng c xp .
(* Pascal *)
(*--------------------------------
BALO.PAS
---------------------------------*)
program balo;
uses crt;
const
MN = 200;
fn = 'BaLo.inp'; gn = 'BaLo.out';
var
a,id: array[1..MN] of integer;{a[i] tr lg vat i}
gdv: array[1..MN] of integer; {gdv[i] don gia vat i}
f, g: text;
n,m: integer; {n: so vat; m: trong luong balo}
t,tt: integer;
{t: tong trong luong con duoc xep vao balo}
{tt: tong gia tri da lay}
(*----------------------------------
Doc du lieu
-----------------------------------*)
procedure Doc;
var i,k: integer;
begin
assign(f,fn); reset(f); readln(f,n,m);
for i := 1 to n do read(f,a[i],gdv[i]);
close(f);
end;
(*------------------------------------
Khoi tri cho chi dan
--------------------------------------*)
procedure InitID;
var i: integer;
begin
for i := 1 to n do id[i] := i;
end;
(*--------------------------------------
Sap giam theo gia don vi
Sng to trong Thut ton v Lp trnh Tp I

142



----------------------------------------*)
procedure IDQuickSort(d,c: integer);
var i, j, k, x: integer;
begin
i := d; j := c;
x := gdv[id[(i+j) div 2]]; {phantu giua}
while i <= j do
begin
while gdv[id[i]] > x do inc(i);
while gdv[id[j]] < x do dec(j);
if i <= j then
begin
k := id[i];
id[i] := id[j];
id[j] := k;
inc(i); dec(j);
end;
end;
if d < j then IDQuickSort(d,j);
if i < c then IDQuickSort(i,c);
end;
procedure XepBaLo;
var i: integer;
begin
tt := 0; {tong gia tri }
t := m; {trong luong con lai cua balo }
for i :=1 to n do
if t >= a[id[i]] then
begin { lay tron vat id[i] }
t := t-a[id[i]];
tt := tt + (a[id[i]]*gdv[id[i]]);
end
else { lay cho day balo }
begin
tt := tt+(t*gdv[id[i]]); {lay vua du }
a[id[i]] := t; {chinh lai vat cuoi }
t := 0;
end;
end;
procedure Ghi;
var i: integer;
begin
assign(g,gn); rewrite(g);
for i := 1 to n do writeln(g,a[i]);
writeln(g,tt); close(g);
end;
BEGIN
Doc; InitID; IDQuickSort(1,n);
XepBaLo; Ghi;
END.
// C#
using System;
Sng to trong Thut ton v Lp trnh Tp I

143



using System.IO;
namespace SangTao1
{
/*------------------------
* Xep BaLo
* ----------------------*/
class BaLo
{
const string fn = "BaLo.inp";
const string gn = "BaLo.out";
static public Item[] Items;
static public int[] t;
static public int n = 0; // so luong vat
static public int m = 0; // suc chua cua Ba lo
static public int vh = 0; // Gia tri cua balo
static void Main()
{
Doc(); QSort(0, n-1);
Xep(); Ghi();
Test();
Console.WriteLine("\n Fini");
Console.ReadLine();
} // Main
static public void Xep()
{
int th = m; // tr lg con lai cua balo
vh = 0;
t = new int[n];
for (int i = 0; i < n; ++i) t[i] = 0;
for (int i = 0; i < n; ++i)
{
int j = Items[i].Id;
t[j] = Min(th,Items[i].Weight);
th -= t[j];
vh += t[j]*Items[i].Price;
if (th == 0) break;
}
}
static public int Min(int a, int b)
{ return (a < b) ? a : b; }
static public void Ghi()
{
StreamWriter g = File.CreateText(gn);
for (int i = 0; i < n; ++i)
g.WriteLine(t[i]);
g.WriteLine(vh); g.Close();
}
// Sap cac BaLo giam theo tien thuong
static public void QSort(int d, int c)
{
int i = d, j = c;
int m = Items[(d + c) / 2].Price;
Item t = new Item(0,0,0);
Sng to trong Thut ton v Lp trnh Tp I

144



while (i <= j)
{
while (Items[i].Price > m) ++i;
while (m > Items[j].Price) --j;
if (i <= j)
{
t = Items[i];
Items[i] = Items[j];
Items[j] = t;
++i; --j;
}
}
if (d < j) QSort(d, j);
if (i < c) QSort(i, c);
}
// Doc lai file gn de kiem tra ket qua
static public void Test() t vit
/*----------------------------
* Doc du lieu vao mang a
* ---------------------------*/
static public void Doc()
{
char[] cc = new char[]
{'\n',' ','\t','\0','\r'};
int[] b = Array.ConvertAll ((
File.ReadAllText(fn)).
Split(cc, StringSplitOptions.
RemoveEmptyEntries),
new Converter<string, int>(int.Parse));
n = b[0]; // so luong vat
m = b[1]; // gioi han trong luong balo
// Tach du lieu
Items = new Item[n];
for (int k = 2, i = 0; i < n; ++i, k+=2)
Items[i] = new Item(b[k], b[k+1], i);
}
public struct Item // mo ta mot mat hang
{
public int Weight; // trong luong
public int Price; // don gia
public int Id; // ma so
public Item(int w, int p, int i)
{ Weight = w; Price = p; Id = i; }
}
} // BaLo
} // SangTao1
Bi 5.4. Cy bao trm ngn nht
Cho mt th lin thng G v hng bao gm n nh, m s t 1 n n, v m
cnh ni hai nh vi nhau. Mi cnh c chiu di cho trc. Tnh lin thng ca
th cho bit vi hai nh cho trc tu ta lun tm c cc cnh gi u
nhau i t nh ny n nh kia. Hy ch ra mt phn P ca th tho cc
tnh cht sau:
Sng to trong Thut ton v Lp trnh Tp I

145



(i) P cha tt c cc nh ca G;
(ii) P cha mt s t nht cc cnh ca G;
(iii) P l th lin thng;
(iv) Tng chiu di cc cnh ca P l ngn nht.
th P tho ba tnh cht (i), (ii) v (iii) c gi l cy bao trm ca th G.
Nu P tho thm tnh cht (iv) th P c gi l cy bao trm ngn nht ca G. Mt s
ti liu dng thut ng cy khung thay cho cy bao trm v cy khung cc tiu thay cho
cy bao trm ngn nht.
Bi ton trn c nhiu ng dng thc tin. Mt trong s ng dng c m t
thng qua th d sau:
C n my tnh c ni vi nhau thnh mng bng cp quang l mt loi dy
truyn tin t tin. Trong mng ny, hai my tnh bt k u c th lin lc c vi
nhau trc tip hoc thng qua mt vi my trung gian. Ta gi tnh cht ny l tnh lin
thng ca mng my tnh. Hy b bt mt s dy ni n my tnh trn vn lin thng
c vi nhau. Mng ti thiu thu c chnh l mt cy bao trm ngn nht ca mng
ban u.
D liu vo: tp vn bn tn DOTHI.INP.
- Dng u tin ghi hai s t nhin n v m cch nhau qua du cch, biu th
s nh (n) v s cnh (m) ca th.
- Mi dng th i = 1, 2,..., m trong s m dng tip theo ghi ba gi tr x y v d
cch nhau qua du cch vi ngha cnh (x, y) ca th c chiu di d.
D liu ra: tp vn bn tn DOTHI.OUT bao gm:
- Danh sch cc cnh c chn.
- Dng cui cng ghi tng chiu di tm c.
Thut ton
Ta dng thut gii Kruskal vi k thut nh sau. Duyt cc cnh t chiu di nh
n ln. Cnh c chn s l cnh khng to thnh chu trnh khi ghp n vo th
kt qu.
DOTHI.INP
8 17
1 2 8
1 3 4
1 4 6
1 5 1
1 6 2
2 3 2
2 4 7
3 4 9
3 7 4
3 8 3
4 5 5
4 6 5
4 8 1
5 6 6
6 7 8
6 8 7
7 8 1

ngha: th c 8
nh v 17 cnh.
Cnh (1, 2) di 8,
cnh (1, 3) di 4,
cnh (1, 4) di 6, ...,
cnh (7, 8) di 1 n
v.

DOTHI.OU
T
1 5
4 8
7 8
2 3
1 6
3 8
1 3
14

ngha: Cy bao trm
ngn nht ca th
cho gm 8 nh v 7 cnh
l (chiu di mi cnh
c ghi sau du
hai chm):
cnh 1. (1, 5): 1
cnh 2. (4, 8): 1
cnh 3. (7, 8): 1
cnh 4. (2, 3): 2
cnh 5. (1, 6): 2
cnh 6. (3, 8): 3
cnh 7. (1, 3): 4
Tng chiu di 7 cnh
chn l: 14.

Sng to trong Thut ton v Lp trnh Tp I

146



Lu rng th kt qu thu c cc bc trung gian c th khng lin thng
m bao gm nhiu mnh lin thng (cy con). Loi th ny c gi l rng. Kt qu
cui cng s l cy v n lin thng v c to thnh t n - 1 cnh. Ta vn dng t
chc find-union cho cc tp nh ri nhau qun l cc tp nh c chn nhm pht
hin chu trnh. Cnh (x, y) khi c ghp vo th trung gian s to thnh chu trnh
khi v ch khi cc nh x v y cng nm trong mt cy ca th (rng) trung gian .
Nh vy mi cy con ca th trung gian c qun l nh mt tp con ca tp cc
nh 1..n ca th ban u. Tp con ny c phn t i din chnh l gc ca cy
tng ng. Phn t ny c chn theo m s nh nht. Cc nh cn li ca cy con
u tr n gc .
D thy cy bao trm lun lun c n nh v n - 1 cnh.
(* Pascal *)
(*---------------------------------
DOTHI.PAS Cay bao trum ngan nhat
(thuat giai Kruskal)
---------------------------------*)
program DoThi;
uses crt;
const
MN = 100; bl = #32; {dau cach}
fn = 'DoThi.inp'; gn = 'DoThi.out';
nl = #13#10; {xuong dong}
type { Mo ta mot canh cua do thi }
CANH = record
x,y: integer; {canh (x,y) }
len: integer; { do dai canh }
end;
var
a: array[0..MN] of CANH; { Mang cac canh }
d: array[1..MN] of integer;{dung cho find-union }
n: integer; {n: so dinh }
m: integer; {so canh }
f,g: text;
procedure Doc; (* Doc du lieu *)
var i: integer;
begin
assign(f,fn); reset(f);
read(f,n,m);
for i := 1 to m do
read(f,a[i].x,a[i].y,a[i].len);
close(f);
end;
(* Sap canh tang theo len *)
procedure qsort(d,c: integer);
var
i,j,m: integer;
t: CANH;
begin
i := d;
j := c;
m := a[(i+j) div 2].len; {diem giua}
while (i<=j) do
Sng to trong Thut ton v Lp trnh Tp I

147



begin
while a[i].len < m do i := i+1;
while a[j].len > m do j := j-1;
if i<=j then
begin
t := a[i];
a[i] := a[j];
a[j] := t;
i := i+1; j := j-1;
end;
end;
if d < j then qsort(d,j);
if i < c then qsort(i,c);
end;
{Tim dai dien cua tap chua x }
function Find(x: integer): integer;
begin
while x <> d[x] do x := d[x];
Find := x;
end;
{--------------------------------
Hop nhat 2 tap dinh: tap chua dinh x va tap chua
dinh y.
Union = false: Neu canh (x,y) tao thanh chu trinh.
Union = true: Neu (x,y) khong tao thanh chu trinh.
----------------------------------}
function Union(x,y: integer): Boolean;
begin
Union := false;
x := Find(x);
y := Find(y);
if x = y then exit;
if x < y then d[y] := x
else d[x] := y;
Union := true;
end;
procedure CBTNN;(* Cay bao trum ngan nhat *)
var
i, t: integer;
k: integer;
begin
assign(g,gn); rewrite(g);
for i := 1 to n do d[i] := i; {Khoi tri }
k := 0;
t := 0; {tong chieu dai cac canh}
for i := 1 to m do
{duyet cac canh theo chieu dai tang dan }
if Union(a[i].x,a[i].y) then
begin
writeln(g,a[i].x,bl,a[i].y);
t := t + a[i].len;
inc(k);
if k=n-1 then break;{chon duoc n-1 canh la du }
Sng to trong Thut ton v Lp trnh Tp I

148



end;
writeln(g,t);
close(g);
end;
BEGIN
Doc; qsort(1,m);
CBTNN; readln;
END.
// C#
using System;
using System.IO;
namespace SangTao1
{
/*------------------------------------
* Cay khung (cay bao trum)
* ngan nhat
* -----------------------------------*/
class CayKhung
{
const string fn = "DoThi.inp";
const string gn = "DoThi.out";
// do thi co n dinh
// m canh (u,v)
// u la dinh dau, v - dinh cuoi
// Len - chieu dai canh
static int[] d ; // to chuc Find-Union
static int n = 0; // so dinh cua do thi
static int m = 0; // so canh cua do thi
static Canh[] cc; // Tap cac canh
static int [] t; // canh duoc chon
static int k; // so canh duoc chon
static int sum = 0;
static void Main()
{
Doc(); QSort(0, m-1);
Ghi(); Test();
Console.WriteLine("Fini");
Console.ReadLine();
} // Main
static void Xep()
{
d = new int[n+1];
t = new int [n];
k = 0; sum = 0;
// Khoi tri cho Find-Union
for (int i = 1; i <= n; ++i) d[i] = i;
for (int i = 0; i < m; ++i)
if (Union(cc[i].U,cc[i].V))
{ t[k++] = i; sum += cc[i].Len; }
}
static void Ghi()
{
Sng to trong Thut ton v Lp trnh Tp I

149



StreamWriter g = File.CreateText(gn);
for (int i = 0; i < k; ++i)
cc[t[i]].FWrite(g);
g.WriteLine(sum); g.Close();
}
static int Find(int x)
{
while (d[x] != x) x = d[x];
return x;
}
// Hop nhat 2 tap dinh
// tap chua dinh u va tap chua dinh v
static bool Union(int u, int v)
{
u = Find(u); v = Find(v);
if (u == v) return false;
if (u < v) d[v] = u; else d[u] = v;
return true;
}
// Sap cac canh tang dan theo Len
static void QSort(int d, int c)
{
int i = d, j = c;
int m = cc[(d + c) / 2].Len;
Canh t = new Canh(0,0,0);
while (i <= j)
{
while (cc[i].Len < m) ++i;
while (m < cc[j].Len) --j;
if (i <= j)
{
t = cc[i]; cc[i] = cc[j];
cc[j] = t;
++i; --j;
}
}
if (d < j) QSort(d, j);
if (i < c) QSort(i, c);
}
// Doc lai file gn de kiem tra ket qua
static void Test() t vit
static void Doc()
{
int[] b =

Array.ConvertAll((File.ReadAllText(fn)).Split(
new char[] {'\n',' ','\t','\0','\r'},
StringSplitOptions.RemoveEmptyEntries),
new Converter<string, int>(int.Parse));
n = b[0];// so dinh
m = b[1]; // so canh
// Tach du lieu
cc = new Canh[m];
Sng to trong Thut ton v Lp trnh Tp I

150



for (int k = 2, i = 0; i < m; ++i, k += 3)
cc[i] = new Canh(b[k], b[k + 1], b[k + 2]);
} // Doc
public struct Canh // Mo ta canh
{
public int U; // dinh dau
public int V; // dinh cuoi u < v
public int Len;
public Canh(int d1, int d2, int d)
{
if (d1 < d2) { U = d1; V = d2; }
else { U = d2; V = d1; }
Len = d;
}
public void Print()
{
Console.WriteLine(U + " " + V
+ " " + Len);
}
public void Print2()
{ Console.WriteLine(U + " " + V); }
public void FWrite(StreamWriter f)
{ f.WriteLine(U + " " + V); }
}
} // CayKhung
} // SangTao1
Bi 5.5. Trn hai tp
Cho hai tp vn bn data1.inp v data2.inp cha cc s nguyn c sp tng. Vit
chng trnh trn hai dy d liu trong hai tp ny thnh mt dy d liu sp tng
duy nht v ghi trong tp vn bn data.out.
Ch :
- Vi d liu cho trong tp th nht l 5 s, tp th hai l 6 s th tp kt
qu s cha 11 s.
- S lng cc s trong mi tp ti a l 50 nghn v khng bit trc.
- Cc s c gi tr kiu nguyn, c tch nhau bi du cch v c th nm
trn nhiu dng.
- Khi trn hai tp ni trn ta phi thc hin ti thiu 22 ln c-ghi bao gm
11 ln c v 11 ln ghi.
Th d:
data1.inp
2
3
5
5
10
data2.inp
3
3
4
7
12
20
data.out
2
3
3
3
4
5
5
7
10
12
20

Sng to trong Thut ton v Lp trnh Tp I

151



Thut ton
Ta dng phng php cn. Gi hai tp cha d liu cn trn l f v g, tp cha kt
qu trn l h. Hy tng tng, ta dng tay tri ly ln lt, mi ln mt phn t ca
tp f (ghi vo bin t) v dng tay phi ly ln lt mi ln mt phn t ca tp g (ghi
vo bin p). So snh vt nng trn hai tay t v p. Tay no cm phn t nh hn th t
phn t vo tp kt qu h v do tay ri nn ly tip phn t t tp tng ng. Qu
trnh ny kt thc khi no mt trong hai tp f hoc g c duyt xong. Cui cng ta
chuyn nt cc phn t cn li ca tp cha duyt ht (tp f hoc g) vo tp kt qu h.
Ta cn lu my im sau y:
Khi c xong phn t cui cng ca mt tp th tp chuyn sang trng thi kt
thc (EOF), do nu ta t chc vng lp WHILE trong th tc trn hai tp theo iu
kin (NOT EOF(f)) AND (NOT EOF(g)) th phn t cui ca cc tp s cha
kp c so snh, trong khi ta mun tn trng nguyn tc: sau khi so snh t v p th mt
trong hai bin, t hoc p phi c gii phng. C th thc hin nguyn tc ny bng k
thut sn ui nh sau: dng bin lgic ef ghi nhn trng thi ht tp f sm hn mt
nhp. iu c ngha khi ef=FALSE bin t vn ang cha gi tr cha x l (cha so
snh vi p v do cha c ghi vo tp h). Ch rng d ef = FALSE nhng c
th ta vn c EOF(f)=TRUE. Mt bin eg tng t cng c to cho tp g. V bn
cht c th hiu cc bin ef v eg khi chng nhn gi tr TRUE l thc s c c
1 n v d liu t file.
(* Pascal *)
(*----------------------
Merge Files
----------------------*)
program MergeFiles;
uses crt;
const
BL = #32; MN = 12;
fn = 'data1.inp'; gn = 'data2.inp';
hn = 'data.out';
{---------------------------------
Tron tep fn va gn ghi vao hn
----------------------------------}
procedure FMerge;
var
f,g,h: text;
ef, eg: Boolean;
t, p: integer;
d: longint; {so phan tu trong tep out}
begin
assign(f,fn); reset(f);
assign(g,gn); reset(g);
assign(h,hn); rewrite(h);
ef := SeekEof(f);
if NOT eof then read(f,t);
eg := SeekEof(g);
if NOT eg then read(g,p);
d := 0;
while (NOT ef) AND (NOT eg) do
if t < p then
Sng to trong Thut ton v Lp trnh Tp I

152



begin
inc(d);
write(h,t,BL);
if d mod 10 = 0 then writeln(h);
ef := SeekEof(f);
if NOT ef then read(f,t);
end else
begin
inc(d);
write(h,p,BL);
if d mod 10 = 0 then writeln(h);
eg := SeekEof(g);
if NOT eg then read(g,p);
end;
while (NOT ef) do
begin
inc(d);
write(h,t,BL);
if d mod 10 = 0 then writeln(h);
ef := SeekEof(f);
if NOT ef then read(f,t);
end;
while (NOT eg) do
begin
inc(d);
write(h,p,BL);
if d mod 10 = 0 then writeln(p);
eg := SeekEof(g);
if NOT eg then read(g,p);
end;
close(f); close(g); close(h);
end;
BEGIN
FMerge;
END.
// C#
using System;
using System.IO;
namespace SangTao1
{
/*------------------------------------
* Tron 2 files sap tang
* -----------------------------------*/
class TronTep
{
static string gn = "Data.out"; // file ket qua
static string fn1 = "data1.inp"; // input 1
static string fn2 = "data2.inp";// input 2
static void Main()
{
Merge();
Test();
Sng to trong Thut ton v Lp trnh Tp I

153



Console.WriteLine("\n Fini");
Console.ReadLine();
}
// true neu ki tu c co phai la chu so
static public bool IsDigit(char c)
{ return (c >= '0' && c <= '9'); }
// true neu c la dau + hoac -
static public bool IsPlusMin(char c)
{ return (c == '+' || c == '-'); }
// true neu c la chu so hoac dau +, -
static public bool Legal(char c)
{ return IsDigit(c) || IsPlusMin(c); }
// true neu c la dau trang, bao gom
// dau cach, xuong dong, tab, het dong, cuoi string
static public bool IsWhite(char c)
{ return (c==' '||c=='\n'||c=='\t'||c=='\r'||c=='\0'); }
// doc 1 so nguyen co dau
static public bool ReadInt(StreamReader f, ref int s)
{
s = 0;
int sign = 1;
char c = ' ';
while (IsWhite(c) && !f.EndOfStream)
c=(char)f.Read();
if (!Legal(c)) return false;
if (IsPlusMin(c))
{
if (c == '-') sign = -1;
if (f.EndOfStream) return false;
c = (char)f.Read();
while (IsWhite(c) && !f.EndOfStream)
c = (char)f.Read();
if (!IsDigit(c)) return false;
}
while (IsDigit(c))
{
s = s * 10 + (int)(c - '0');
if (f.EndOfStream) break;
c = (char)f.Read();
}
s *= sign;
return true;
}
static void Merge()
{
StreamWriter g = File.CreateText(gn);
StreamReader f1 = File.OpenText(fn1);
StreamReader f2 = File.OpenText(fn2);
int x=0,y=0;
bool b1 = ReadInt(f1, ref x);
bool b2 = ReadInt(f2, ref y);
while (b1 && b2)
{
Sng to trong Thut ton v Lp trnh Tp I

154



if (x <= y)
{
g.WriteLine(x);
b1 = ReadInt(f1, ref x);
}
else
{
g.WriteLine(y);
b2 = ReadInt(f2, ref y);
}
}
while (b1){g.WriteLine(x);b1=ReadInt(f1,ref x);}
while (b2){g.WriteLine(y);b2=ReadInt(f2,ref y);}
f1.Close(); f2.Close(); g.Close();
}
static void Test()
{

Console.WriteLine("Inp1:\n"+File.ReadAllText(fn1));
Console.WriteLine("Inp2:\n"+File.ReadAllText(fn2));
Console.WriteLine("Out:\n"+File.ReadAllText(gn));
}
} // ChonTep
} // SangTao1
Ch thch Thc ra c th c d liu t hai file vo hai mng tng ng ri trn hai
mng ny. Tuy nhin chng ta mun minh ha li gii vi hn ch l mi ln ch c
php c mt n v d liu t mi file.
Hm bool ReadInt(StreamReader f, ref int i) c mi ln mt s nguyn i t file
text f. Nu c c, hm cho ra gi tr true v s i, ngc li, nu khng gp s
nguyn, hm cho ra gi tr false. Hm hot ng nh sau. Trc ht b qua cc k t
trng. Nu gp du tr - hm ghi nhn du , sau hm c tip dy s v tch ly
dn vo bin nguyn i.
Bi 5.6. Trn nhiu tp
Cho n tp vn bn m s t 1 n n. Tp th i cha d
i
phn t c sp tng.
Hy lp mt lch ch ra trnh t trn mi ln hai tp cui cng thu c mt
tp sp tng duy nht vi tng s ln ghi d liu vo tp l nh nht. Bit rng
th tc trn hai tp ch c th c tun t hoc ghi tun t mi ln mt phn
t.
D liu vo: Tp vn bn MF.INP.
- Dng u tin l s lng n cc tp cha d liu sp tng.
- Tip n l n s t nhin d
i
, i = 1..n cho bit s phn t trong tp th i. Mi
s ghi trn mt dng.
D liu ra: Tp vn bn MF.OUT.
- Dng u tin: m l s ln thc hin trn hai tp.
- Tip n l m dng, mi dng cha ba s t nhin i, j v k cho bit cn ly
tp i trn vi tp j v ghi kt qu vo tp k. Cc s trn cng mt dng
cch nhau qua du cch.
Sng to trong Thut ton v Lp trnh Tp I

155



Tp cha kt qu trung gian phi c m s khc vi m s ca cc tp to lp
trc .
Th d:
MF.INP MF.OUT

ngha: Cho 5 tp sp tng vi s phn t ln lt l
10, 5, 4, 4, 3. Cn thc hin 4 ln trn, mi ln 2 tp.
Ln th nht: trn tp 5 vi tp 3 ghi vo tp 6.
Ln th hai: trn tp 4 vi tp 2 ghi vo tp 7.
Ln th ba: trn tp 6 vi tp 7 ghi vo tp 8.
Ln th t: trn tp 1 vi tp 8 ghi vo tp 9.
Tng s ln ghi l 58.
5
10
5
4
4
3

4
5 3 6
4 2 7
6 7 8
1 8 9
58
Thut ton
Trc ht rng nu trn tp sp tng f gm n phn t vi tp sp tng g gm m
phn t thu c tp sp tng h th i vi cc phn t trong hai tp ngun ta ch cn
thc hin thao tc c, cn thao tc ghi ch thc hin i vi tp ch h. K hiu |f| l s
phn t trong tp f, ta c:
| f | = n, | g | = m
Do tng s cc phn t ca hai tp l m + n nn s phn t trong tp ch h s l
| h | = n + m = | f | + | g |
v do s ln ghi (ti thiu) cc phn t vo tp h s l n + m.
Ta c nhn xt sau: Mun xy dng mt quy trnh trn mi ln hai tp cho nhiu
tp ban u vi yu cu tng s thao tc ghi tp l ti thiu th ta phi to ra cc tp
trung gian cng t phn t cng tt.
Ta dng k hiu f g h vi ngha l trn hai tp ngun f v g thu c tp
h. Ta c
Nu f g h th | h | = |f | + | g |
rng trn tp f vi tp g hay trn tp g vi tp f th s thao tc ghi tp nh
nhau v cng bng | f | + | g |. Gi s ta c ba tp vi s phn t tng ng l
s[1..3] = (5, 1, 2).
Gi s ta thc hin quy trnh ( C) C nh sau:
Bc 1: Trn tp vi tp C ghi tm vo tp . S thao tc ghi s l (5 + 1) = 6
v tp c 6 phn t.
Bc 2: Trn tp vi tp C ghi vo tp C. S thao tc ghi s l 6 + 2 = 8 v tp
C c 8 phn t.
Kt qu thu c tp C. Tng s thao tc ghi trong c hai bc trn s l:
6 + 8 = 14.
Tng qut, vi ba tp a, b v c c trn theo quy trnh:
(a b) c
ta d dng tnh c tng s thao tc ghi tp cho quy trnh trn l
(| a | + | b |) + (| a | + | b |) + c = 2(| a | + | b |) + c.
Bng di y tnh ton cho ba phng n pht hin ra phng n ti u.
Sng to trong Thut ton v Lp trnh Tp I

156



Phng n Quy trnh thc hin Tng s thao tc ghi tp
1 ( C) C 2(5 + 1) + 2 = 2.6 + 2 = 14
2 ( C) C 2(5 + 2) + 1 = 2.7 + 1 = 15
3 (C C) 2(1 + 2) + 5 = 2.3 + 5= 11
(phng n ti u)
Kho st cc quy trnh trn ba tp
s[1..3] = (5, 1, 2)
Thut ton tham lam khi s nh sau:
Thut ton Huffman
Lp (n khi ch cn mt tp duy nht)
Ly hai tp u v v c s phn t nh nht.
Trn u v h. Ta c | h | = | u | + | |v |.
Loi b u v v khi danh sch cc tp cn x l.
Kt np h vo danh sch cc tp cn x l
xong lp
Vi n tp ban u, d thy rng mi ln lp ta loi b c hai tp (u v v c s
phn t min) v thm mt tp (h) tc l mi ln lp ta loi b c mt tp, do s
ln lp s l n 1.
Thut ton trn mang tn nh ton hc M Huffman l ngi u tin xut.
Ta minh ho thut ton trn vi d liu vo nh sau:
s[1..5] = (10, 5, 4, 4, 3).
ngha: Trn 5 tp sp tng vi s phn t ln lt l 10, 5, 4, 4 v 3 thu c
mt tp sp tng duy nht.
Ln
lp
Danh sch cc tp
cn x l
Hai tp c s
phn t min
Trn S thao
tc
ghi tp
1 (:10,C:5,C:4,:4,C:3) C:3 , C:4
C C C 7
2 (:10,C:5,:4,C:7) C:5 , :4
C C 9
3 (:10,C:7, C: 9) C:7 , C:9
C C 16
4 (:10,: 16) :10 , :16
26
Kt
qu
(: 26) 58
Minh ho thut ton Huffman vi d liu vo
(:10,C:5,C:4,:4,C:3)
V n = 5 nn s ln lp s l n 1 = 4. Sau 4 ln lp ta thu c tp m s 9 vi 26
phn t. tnh tng s thao tc ghi ta ch cn ly tng s phn t ca cc tp tham gia
trong mi ln trn hai tp. Tng l:
tt = (3 + 4) + (5 + 4) + (7 + 9) + (10 + 16) = 7 + 9 + 16 + 26 = 58.
Sng to trong Thut ton v Lp trnh Tp I

157



Ta chn phng n ci t sau y cho thut ton Huffman. Phng n ny t ra
tin li trong nhiu ng dng. Li th ca n l khng xo i cc i tng (tp) x
l m ch nh du chng khi cn c th khi phc li v gii trnh kt qu.
C th l ta s xy dng mt cy nh phn gm 2n 1 nh v gi l cy Huffman
nh sau.
Cc nh c m s t 1..2n 1. Mi nh nhn mt gi tr nguyn dng gi l
trng s ca nh .
Trn hnh v, nh c th hin trong hnh trn, cnh l gi tr ca trng s.
Trong bi ton trn tp ny m s ca nh chnh l m s ca tp, trng s ca nh
chnh l s phn t c trong tp tng ng.

Thut ton to cy Huffman
Khi to: n nh ri nhau 1..n c trng s s(1),..., s(n).
h:= n;
Lp n 1 ln
Ly hai nh u v v c s(u) v s(v) min.
nh du u v v l x l.
h:= h + 1
To nh mi h tr n u v v v s(h) = s(u) + s(v).
xong lp

t chc d liu cho cy Huffman chng ta dng ba mng nguyn s, t v p kch
thc 2n 1 phn t. Vi mi nh i, s[h] cho bit trng s ca nh h, t[h] tr n con tri
ca nh h, p[h] tr n con phi ca nh h. Hai con tri t[h] v phi p[h] chnh l hai nh
t trng s min trong mi ln lp, h chnh l nh mi c to lp t hai nh c trng s
min. Ngoi ra ta dng mt mng nguyn d nh du cc nh x l, d[i] = 0 cho bit
nh i cha c x l, d[i] = 1 cho bit nh i x l. Cc nh mi c to lp v thm
vo cy ln lt nhn m s l n + 1, n + 2,, 2n 1, do nh cui cng s c m s l
h = 2n 1. Th tc to cy Huffman h khi s nh sau:















C
3
C
4

4
C
7
C
5
C
9

16

10
Cy Huffman h xy dng t 5 nt ban u
s[1..5] = (10,5,4,4,3)
h =
d = 7 + 9 + 16 + 26 = 58

26
Sng to trong Thut ton v Lp trnh Tp I

158







{-----------------------------
Tao cay Huffman h = 2n-1
tu cac trong so s[1..n]
-----------------------------}
procedure Huffman;
var i,u,v: integer;
begin
fillchar(d,sizeof(d),0);
fillchar(t,sizeof(t),0);
fillchar(p,sizeof(p),0);
h := n; tt := 0; {tong trong so}
for i := 1 to n-1 do
begin
min2(u,v); {u,v dat trong so min }
h := h+1; {ma so cua dinh moi}
s[h] := s[u]+s[v]; {trong so cua dinh moi }
tt := tt+s[h]; {tong trog so }
t[h] := u; {tro toi con trai }
p[h] := v; {tro toi con phai }
end;
end;
Th tc min2(u,v) tm trong s cc nh cha x l hai nh u v v t trng s
min. Th tc ny gi hai ln hm min1, mi ln tm mt nh t trng s min trong
s cc nh cha x l v nh du lun nh tm c (l x l).
{--------------------------------
Tim trong so cac dinh chua xu li
hai dinh u va v dat trong so min.
----------------------------------}
procedure min2(var u,v: integer);
begin
u := min1; v := min1;
end;
{--------------------------------
Tim trong so cac dinh chua xu li
mot dinh dat trong so min
va danh dau dinh tim duoc.
----------------------------------}
function min1: integer;
var i, imin, vmin: integer;
begin
vmin := MaxInt;
Sng to trong Thut ton v Lp trnh Tp I

159



for i := 1 to h do
if d[i]=0 then {dinh i chua xu li }
if s[i] < vmin then
begin
vmin := s[i]; imin := i;
end;
d[imin] := 1; min1 := imin;
end;
Sau khi to xong cy Huffman, ghi kt qu, ta ch cn duyt cc nh c to
mi, tc l cc nh c m s t n + 1 n h = 2n 1 ly hai con tri v phi ca
mi nh.
{---------------------------------
Duyet cac dinh tu n+1 den 2n-1,
ghi thong tin vao tep.
----------------------------------}
procedure Ghi;
var i: integer;
begin
assign(g,gn);
rewrite(g);
writeln(g,n-1);
for i := n+1 to h do
writeln(g,t[i],BL,p[i],BL,i);
writeln(g,tt);
close(g);
end;
(* Pascal *)
(*-----------------------------------
Tron nhieu tep
------------------------------------*)
uses crt;
const
fn = 'MF.INP';
gn = 'MF.OUT';
MN = 200;
BL = #32; {Dau cach}
NL = #13#10; {xuong dong}
type
MI1 = array[0..MN] of integer;
MB1 = array[0..MN] of byte;
var
s,t,p: MI1;
{s[i] - so phan tu trong tep i}
{t[i] - tro trai}
{p[i] - tro phai i}
Sng to trong Thut ton v Lp trnh Tp I

160



d: MB1; {danh dau tep da xu li}
n: integer; {so luong tep ban dau}
h: integer; {cay Huffman}
f,g: text;
tt: longint;
procedure Doc;
var i: integer;
begin
assign(f,fn); reset(f); read(f,n);
for i := 1 to n do read(f,s[i]);
close(f);
end;
{--------------------------------
Tim trong so cac dinh chua xu li
mot dinh dat trong so min
va danh dau dinh tim duoc.
----------------------------------}
function min1: integer; t vit
{--------------------------------
Tim trong so cac dinh chua xu li
hai dinh u va v dat
trong so min, U < v.
----------------------------------}
procedure min2(var u,v: integer); t vit
{-----------------------------
Tao cay Huffman h = 2n-1
tu cac trong so s[1..n]
-----------------------------}
procedure Huffman; t vit
{------------------------------
Duyet cac dinh tu n+1 den 2n-1,
ghi thong tin vao tep.
-------------------------------}
procedure Ghi; t vit
BEGIN
Doc; Huffman; Ghi;
END.
// C#
using System;
using System.IO;
namespace SangTao1
{
/*----------------------------
* Cay Huffman
* Tron n file sap tang
* --------------------------*/
Sng to trong Thut ton v Lp trnh Tp I

161



class HuffmanTree
{
static string fn = "MF.inp"; // file ket qua
static string gn = "MF.out"; // file ket qua

static int[] t; // tro trai
static int[] p; // tro phai
static int[] v; // trong so dinh
static int[] d; // danh dau dinh da xu ly
static int n = 0; // so phan tu
static int n2; // n2 = 2*n
static int h = 0; // Goc cua cay Huffman
static int tt = 0; // tong trong so
static void Main()
{
Doc(); Huffman();Ghi(); Test();
Console.WriteLine("\n Fini");
Console.ReadLine();
} // Main
static void Ghi()
{
StreamWriter f = File.CreateText(gn);
for (int i = n + 1; i <= h; ++i)
f.WriteLine(t[i] + " " + p[i] + " " + i);
f.WriteLine(tt);
f.Close();
}
static void Huffman()
{
h = n; // goc cay Huffman
tt = 0; // tong trong so
int m1 = 0, m2 = 0;
int x;
for (int i = 1; i < n; ++i)
{
m1 = MinV(); m2 = MinV();
if (m1 > m2)
{x = m1; m1 = m2; m2 = x;}
// m1 < m2
++h; // them dinh moi
v[h] = v[m1] + v[m2];
t[h] = m1; // tro trai
p[h] = m2; // tro phai
tt += v[h];
}
}
// Tim dinh chua xu ly co trong so min
static int MinV()
{
int imin = 0;
for (int i = 1; i <= h; ++i)
if (d[i] == 0) // dinh i chua x li
if (v[i] < v[imin]) imin = i;
Sng to trong Thut ton v Lp trnh Tp I

162



d[imin] = 1; // danh dau dinh i
return imin;
}
static void Doc()
{
char[] cc = new char[] {'\n',' ','\t','\0','\r'};
int [] a =
Array.ConvertAll((File.ReadAllText(fn)).Split(cc,
StringSplitOptions.RemoveEmptyEntries),
new Converter<string,int>(int.Parse));
n = a[0]; n2 = 2*n;
v = new int[n2];
t = new int[n2];
p = new int[n2];
d = new int[n2];
v[0] = int.MaxValue; // linh canh
// Khoi tri cac nut cua cay
for (int i = 0; i < n2; ++i)
t[i] = p[i] = d[i] = 0;
for (int i = 1; i <= n; ++i)
v[i] = a[i];
}
static void Print(int[] a, int n) t vit
static void Test() t vit
} // Huffmantree
} // SangTao1

Ch
Thut ng tham lam khng c ngha l ly nhiu nht m ch l xc nh mt
chin lc x l d liu sao cho c hiu qu nht.



Sng to trong Thut ton v Lp trnh Tp I

163



CHNG 6
PHNG PHP QUAY LUI


Gi s ta phi tm trong mt tp d liu D cho trc mt dy d liu:
v = (v[1], v[2],..., v[n])
tho mn ng thi hai tnh cht P v Q. Trc ht ta chn mt trong hai tnh cht
cho lm nn, gi s ta chn tnh cht P.
Sau ta thc hin cc bc sau y:
Bc 1. (Khi tr) Xut pht t mt dy ban u v = (v[1],..., v[i]) no ca
cc phn t trong D sao cho v tho P.
Bc 2. Nu v tho Q ta dng thut ton v thng bo kt qu l dy v, ngc
li ta thc hin Bc 3.
Bc 3. Tm tip mt phn t v[i + 1] b sung cho v sao cho
v = (v[1],..., v[i], v[i + 1]) tho P.
C th xy ra cc trng hp sau y:
3.1. Tm c phn t v[i + 1]: quay li bc 2.
3.2. Khng tm c v[i + 1] nh vy, tc l vi mi v[i + 1] c th ly trong
D, dy v = (v[1],..., v[i], v[i + 1]) khng tho P. iu ny c ngha l i theo
ng
v = (v[1],..., v[i])
s khng dn ti kt qu. Ta phi i hng ti mt v tr no . thot
khi ng ct ny, ta tm cch thay v[i] bng mt gi tr khc trong D. Ni cch
khc, ta loi v[i] khi dy v, gim i i mt n v ri quay li Bc 3.
Cch lm nh trn c gi l quay lui: li li mt bc.
D nhin ta phi nh du v[i] l phn t loi ti v tr i sau khng t li
phn t vo v tr i trong dy v.
Khi no th c th tr li l khng tn ti dy v tho ng thi hai tnh cht P v Q? Ni
cch khc, khi no th ta c th tr li l bi ton v nghim?
D thy, bi ton v nghim khi ta duyt ht mi kh nng. Ta ni l vt cn
mi kh nng. Ch rng c th n mt lc no ta phi li lin tip nhiu ln. T
suy ra rng, thng thng bi ton v nghim khi ta khng cn c th li c na.
C nhiu s gii cc bi ton quay lui, di y l hai s kh n gin, khng
quy.
S 1: Gii bi ton quay lui
(tm 1 nghim)
S 2: Gii bi ton quay lui
(tm 1 nghim)
Khi tr v: v tho P;
repeat
if (v tho Q) then
begin
Ghi nhn nghim;
exit;
Khi tr v: v tho P;
repeat
if (v tho Q) then
begin
Ghi nhn nghim;
exit;
Sng to trong Thut ton v Lp trnh Tp I

164



end;
if (Tm c 1 nc i)
then Tin
else
if (c th li c)
then Li
else
begin
Ghi nhn: v nghim;
exit;
end;
until false;
end;
if (Ht kh nng duyt)
then
begin
Ghi nhn v nghim;
exit;
end;
if (Tm c 1 nc i)
then Tin
else Li;
until false;
Thng thng ta khi tr cho v l dy rng (khng cha phn t no) hoc dy
c mt phn t. Ta ch yu cu dy v c khi tr sao cho v tho P. Lu l c
dy v tho P ch khng phi tng phn t trong v tho P.
C bi ton yu cu tm ton b (mi nghim) cc dy v tho ng thi hai tnh
cht P v Q. Nu bit cch tm mt nghim ta d dng suy ra cch tm mi nghim
nh sau: mi khi tm c mt nghim, ta thng bo nghim trn mn hnh hoc
ghi vo mt tp ri thc hin thao tc Li, tc l gi v nh khng cng nhn
nghim , do phi loi v[i] cui cng trong dy v tip tc tm hng khc.
Phng php ny c tn l phng php gi sai. Hai s trn s c sa mt
cht nh sau tm mi nghim.
S 3: Gii bi ton quay lui
(tm mi nghim)
S 4: Gii bi ton quay lui
(tm mi nghim)
Khi tr: v tho P;
d := 0; {m s nghim}
repeat
if (v tho Q) then
begin
d := d+1;
Ghi nhn nghim th d;
Li; { gi sai }
end;
if (Tm c 1 nc i)
then Tin
else if (c th li c)
then Li
else { ht kh nng }
begin
if d = 0 then
Ghi nhn: v nghim;
else
Ghi nhn: d nghim;
exit;
end;
until false;
Khi tr: v tho P;
d := 0; {m s nghim}
repeat
if (v tho Q) then
begin
d := d+ 1;
Ghi nhn nghim th d;
Li; { gi sai }
end;
if (Ht kh nng duyt)
then
begin
if d = 0 then
Ghi nhn: v nghim;
else
Ghi nhn: d nghim;
exit;
end;
if (Tm c 1 nc i)
then Tin
else Li;
until false;
Bi 6.1. Cc qun Hu
Qun Hu trn bn c Vua c th n theo hng, theo ct cha n hoc theo
ng cho ca hnh vung nhn n lm nh.
Sng to trong Thut ton v Lp trnh Tp I

165



a) Tm mt cch t N qun Hu trn bn c Vua kch thc N N sao cho
khng qun no n c qun no.
b) Tm mi cch t N qun Hu theo iu kin trn. Ghi kt qu vo mt tp
vn bn tn N_HAU.OUT.
Thut ton
Trc ht ta t cc qun Hu mp ngoi bn c. Hu th i s ng u ct th
i. Sau ta dch dn cc Hu vo trong cc dng ca bn c v ghi nhn v tr ca
chng vo mt mng v. Phn t v[i] ca mng v cho bit phi t Hu th i, tc l Hu
chim ct i ti dng v[i].
Th d, vi bn c 4 4 ta c li gii v = (2, 4,
1, 3) vi ngha:
- t Hu th nht ti (ct 1) dng 2,
Hu th 2 ti (ct 2) dng 4, Hu th
3 ti (ct 3) dng 1 v Hu th 4 ti
(ct 4) dng 3.
- Mi khi t c Hu th i ta chuyn
qua Hu tip theo i + 1. iu kin t
c Hu i trn dng d ca bn c l
n khng b cc Hu t trc ,
tc l cc Hu j = 1..(i - 1) chiu. y
chnh l tnh cht P.
- Hu j < i chiu (ng ) Hu i khi v ch khi v[j] = v[i] (cng hng) hoc i - j
= abs(v[i] - v[j]) (Hu i v Hu j nm trn hai nh i din ca hnh vung, do
hai cnh lin tip ca hnh vung ny phi bng nhau).
- Tnh cht Q khi s l: t c N Hu.
S tm mt nghim XepHau1 nh sau:
(*------------------------------------
Tim 1 nghiem: xep M quan hau tren
ban co M X M
------------------------------------*)
procedure XepHau1(M: byte);
var i: byte;
begin
if (M < 1) or (M > MN) then exit;
{MN = 20 la gioi han kich thuoc ban co}
n := M;
{Khi tr: t cc hu 1..N ngoi bn c.
Hu i t ti u ct i, i=1..N.}
for i := 1 to n do v[i] := 0;
i := 1; {Hu ang xt}
repeat
if i > n then {co nghiem v[1..n]}
begin
KetQua1(n);
exit;
end;
if i < 1 then {vo nghiem}
begin
KetQua1(0);
exit;
Sng to trong Thut ton v Lp trnh Tp I

166



end;
if Tim(i) {co cach di }
then inc(i) {Tien}
else
begin {Lui}
v[i] := 0;
dec(i);
end;
until false;
end;
Th tc c hai tnh hung, KetQua1(n): hin th mng v[1..n], trong v[i] l
dng t Hu i, KetQua1(0): thng bo v nghim.
Hm Tim(i) thc hin chc nng sau y: xut pht t dng Hu i ang ng l
v[i] y tip Hu i xung cc dng di tm c mt dng t n sao cho khng b
cc Hu t trc , tc l khng b cc Hu j = 1..(i 1) n.
Tim(i)=true: tm c mt v tr (dng) t Hu i, ngc li Tim=false.
(*---------------------------------------
Xuat phat tu dong v[i]+1, tim dong moi
co the dat duoc Hau i
--------------------------------------*)
function Tim(i: byte): Boolean;
begin
Tim := true;
while v[i] < n do
begin
inc(v[i]);
if DatDuoc(i) then exit;
end;
Tim := false;
end;
Hm Boolean DatDuoc(i) cho gi tr true nu Hu i khng b cc Hu
j = 1, 2,, i 1 t trc n. Ngc li, nu Hu i b mt Hu no n th hm
cho ra gi tr false.
(*--------------------------------------
Kiem tra xem co dat duoc Hau i
tai o (v[i],i) cua ban co khong ?
--------------------------------------*)
function DatDuoc(i: byte): Boolean;
var j: byte;
begin
DatDuoc := false;
for j := 1 to i-1 do
if (v[i] = v[j]) or (i-j = abs(v[i]-v[j]))
{Hau j an duoc Hau i}
then exit;
DatDuoc := true;
end;
Thao tc Tin n gin l chuyn qua xt Hu k tip, Hu i + 1.
Tien: Chuyn qua Hu tip theo
inc(i);
Sng to trong Thut ton v Lp trnh Tp I

167



Thao tc Li a Hu ra ngoi bn c, chuyn qua xt Hu trc , Hu i 1.
Lui: a Hu ra ngoi bn c, chuyn qua Hu trc
v[i ]:= 0; dec(i);
Ta vit th tc XepHau tm mi nghim ca bi ton. Vi bn c 8 8 ta thu
c 92 nghim. Vi bn c 10 10 ta thu c 724 nghim.
(*---------------------------------------
Tim moi cach dat M Hau tren ban co
M X M
--------------------------------------*)
procedure XepHau(M: byte);
var
i: byte;
d: integer; {dem so nghiem}
begin
if (M < 1) or (M > MN) then exit;
n := m;
for i := 1 to n do v[i] := 0;
assign(g,gn);
rewrite(g);
i := 1; {Hau dang xet}
d := 0; {dem so nghiem}
repeat
if i > n then {Tim duoc 1 nghiem}
begin
inc(d);
KetQua(d); {v[1..n] la nghiem thu d}
i := n; {gia sai}
end;
if i < 1 then {Tim het cac nghiem}
begin
writeln(g,'Tong cong ',d,' nghiem ');
close(g);
writeln('Xem ket qua trong file ',gn);
readln;
exit;
end;
if Tim(i) then inc(i)
else begin
v[i] := 0;
dec(i);
end;
until false;
end;
(* Pascal *)
(*============================
N Hau
==============================*)
{$B-}
uses crt;
const
MN = 20;
Sng to trong Thut ton v Lp trnh Tp I

168



gn = 'N_HAU.OUT';
BL = #32; {dau cach}
var
v: array[0..MN] of byte;
n: byte; {so quan hau, kich thuoc ban co}
g: text; {tep ket qua}
function DatDuoc(i: byte): Boolean; t vit
function Tim(i: byte): Boolean; t vit
(*---------------------------------------
Hien thi nghiem tren man hinh
Cho bai toan tim 1 nghiem
k=0: vo nghiem
k=n: co nghiem v[1..n]
--------------------------------------*)
procedure KetQua1(k: byte);
var i: byte;
begin
writeln;
if k = 0 then write('Vo nghiem')
else
for i := 1 to k do write(v[i]:3);
writeln;
end;
(*------------------------------------
Tim 1 nghiem: xep M quan hau tren
ban co M X M
------------------------------------*)
procedure XepHau1(M: byte); t vit
(*---------------------------------------
Ghi nghiem thu d vao tep g 'N_Hau.out'
Bai toan tim moi nghiem
--------------------------------------*)
procedure KetQua(d: integer);
var i: byte;
begin
write(g,'Nghiem thu ',d,': ');
for i := 1 to n do write(g,v[i],BL);
writeln(g);
end;
(*---------------------------------------
Tim moi cach dat M Hau tren ban co M X M
--------------------------------------*)
procedure XepHau(M: byte); t vit
BEGIN
XepHau1(8); {tim 1 nghiem}
XepHau(8); {tim du 92 nghiem}

END.
Phng n ci tin
Ta xt mt phng n ci tin tp trung vo vic nng cao tc tnh ton khi
kim tra hai hu ng nhau. Mi khi tm v tr t hu th i trn bn c ta cn kim
Sng to trong Thut ton v Lp trnh Tp I

169



tra xem hu i c ng vi tt c (i-1) hu t trc khng. Thi gian chi ph
tp trung chnh im ny.
ci tin, ta s s dng thm 3 mng nh du cc dng v cc ng cho ca
cc hu t trn bn c vi ngha l sau y:
- Mng dd[1..n] dng nh du dng. Nu dd[i] = 0 tc l cha c hu no
chim dng i, do c th chn dng i ny t mt hu khc. Ngc li,
nu dd[i] = 1 c ngha l c hu no c t trn dng i. Cc hu khc
khng c php chim dng i na.
- Mng c1[-(n-1)..(n-1)] kim sat cc ng cho theo hng Ty Bc - ng
Nam. Ta tm gi l cc ng cho chnh. C c thy 2n-1 ng cho trong
bn c vung cnh n. Nu hu i t trn dng j th s kim sot ng cho
chnh i-j. Nh vy khi c1[i-j] = 1 c ngha l c hu kim sot ng cho
ny. Ngc li, khi c1[i-j] = 0 th ng cho ny ri v ta c th t mt qun
hu vo (x,y) ca bn c, nu y-x = i-j, trong , x, i l cc ta dng v y, j
l cc ta ct.
- Mng c2[2..2n] kim sat cc ng cho theo hng ng Bc - Ty Nam.
Ta tm gi l cc ng cho ph. Nu hu i t trn dng j th s kim sot
ng cho ph i+j. Nh vy khi c1[i+j] = 1 c ngha l c hu kim sot
ng cho ny. Ngc li, khi c1[i+j] = 0 th ng cho ny ri v ta c th
t mt qun hu vo (x,y) ca bn c, nu y+x = i+j, trong , x, i l cc ta
dng v y, j l cc ta ct.
iu kin hu i c th t trn dng j khi s l:
(dd[j] = 0) and (c1[i-j] = 0) and (c2[i+j] = 0), hay
(dd[j] + c1[i-j] + c2[i+j] = 0)
(* Pascal *)
(*============================
N Hau
==============================*)
{$B-}
uses crt;
const
MN = 20;
gn = 'N_HAU.OUT';
BL = #32; {dau cach} nl = #13#10; { Chuyen dong }
type mi1 = array[0..MN] of integer;
var
v: mi1; { vi tri dat hau }
c1: array[-mn..mn] of integer; { cheo 1 }
c2: array[0..2*mn] of integer; { cheo 2 }
dd: mi1; { dong }
n: integer; { so quan hau, kich thuoc ban co }
g: text; { file ket qua }

(*--------------------------
Nhac Hau i khoi ban co
--------------------------*)
procedure NhacHau(i: integer);
begin
if v[i] = 0 then exit;
c1[i-v[i]] := 0; c2[i+v[i]] := 0;
Sng to trong Thut ton v Lp trnh Tp I

170



dd[v[i]] := 0;
end;
(*--------------------------
Dat Hau i vao dong j
--------------------------*)
procedure DatHau(i,j: integer);
begin
c1[i-j] := 1; c2[i+j] := 1;
dd[j] := 1;
end;
(*---------------------------------------
Xuat phat tu dong v[i]+1,
tim dong j co the dat duoc Hau i
--------------------------------------*)
function Tim(i: integer): integer;
var j: integer;
begin
Tim := 0;
for j := v[i] + 1 to n do
if ( c1[i-j] + c2[i+j] + dd[j] = 0 ) then
begin
Tim := j;
exit;
end;
end;
(*---------------------------------------
Hien thi nghiem tren man hinh
Cho bai toan tim 1 nghiem
k = 0: vo nghiem
k = n: co nghiem v[1..n]
--------------------------------------*)
procedure Ket1(k: integer);
var i: integer;
begin
writeln;
if k = 0 then write('Vo nghiem')
else for i := 1 to k do write(v[i]:3);
writeln;
end;
(*--------------------------------------
Tim 1 nghiem: xep M quan hau tren
ban co M X M
--------------------------------------*)
procedure XepHau1(M: integer);
var i,j: integer;
begin

if (M < 1) or (M > MN) then exit;
fillchar(c1,sizeof(c1),0);
fillchar(c2,sizeof(c2),0);
fillchar(dd,sizeof(dd),0);
fillchar(v,sizeof(v),0);
n := M; i := 1; { Dang xet Hau i }
Sng to trong Thut ton v Lp trnh Tp I

171



repeat
if i > n then
begin
Ket1(n); { co nghiem v[1..n] }
exit;
end;
if i < 1 then
begin
Ket1(0); {vo nghiem}
exit;
end;
NhacHau(i); j := Tim(i);
if j > 0 then
begin { Tien: Dat Hau i tai dong j }
DatHau(i,j);
v[i] := j; inc(i); { Xet Hau i+1 }
end
else
begin { Lui: Dat Hau i ra ngoai ban co }
v[i] := 0; dec(i); { Xet Hau i-1 }
end;
until false;
end;
(*---------------------------------------
Ghi nghiem thu d vao tep g 'N_Hau.out'
Bai toan tim moi nghiem
--------------------------------------*)
procedure Ket(d: integer);
var i: integer;
begin
write(g,'Nghiem thu ',d,': ');
for i := 1 to n do write(g,v[i],BL);
writeln(g);
end;
(*---------------------------------------
Tim moi cach dat M Hau
tren ban co M X M
--------------------------------------*)
procedure XepHau(M: integer);
var i,j: integer;
d: integer; { dem so nghiem }
begin
if (M < 1) or (M > MN) then exit;
n := m;
fillchar(v,sizeof(v),0);
fillchar(c1,sizeof(c1),0);
fillchar(c2,sizeof(c2),0);
fillchar(dd,sizeof(dd),0);
assign(g,gn); rewrite(g);
i := 1; {Hau dang xet}
d := 0; {dem so nghiem}
repeat
if i > n then
Sng to trong Thut ton v Lp trnh Tp I

172



begin
inc(d);
Ket(d); { v[1..n] la nghiem thu d }
i := n;
end;
if i < 1 then
begin
writeln(g,'Tong cong ',d,' nghiem ');
close(g);
writeln('Xem ket qua trong file ',gn);
exit;
end;
NhacHau(i); j := Tim(i);
if j > 0 then
begin { Tien }
DatHau(i,j); v[i] := j; inc(i);
end
else
begin { Lui }
v[i] := 0; dec(i);
end;
until false;
end;
procedure Test;
begin
XepHau1(8); { tim 1 nghiem }
XepHau(8); { tim du 92 nghiem }
readln;
end;
BEGIN
Test;
END.
// C#
using System;
using System.IO;
namespace SangTao1
{
/*------------------------------------
* Bai toan Tam Hau
* Phuong an tong quat cho N Hau
* -----------------------------------*/
class TamHau
{
static int mn = 20;
static int mn2 = 2 * mn;
static int[] v = new int[mn + 1];
// Vet tim kiem, v[i] - dong dat Hau i
static int[] dd = new int[mn + 1];
// dd[i] = 1: dong i bi cam
static int[] c1 = new int[mn2 + 1];
// c1[i] = 1 duong cheo chinh i bi cam
static int[] c2 = new int[mn2 + 1];
Sng to trong Thut ton v Lp trnh Tp I

173



// c2[i] = 1 duong cheo phu i bi cam
static int n = 0; // kich thuoc ban co
static void Main()
{
Console.WriteLine("\n Test 1: Tim 1 nghiem " +
" voi n = 1..10 ");
Test1();
Console.ReadLine();
Console.WriteLine("\n Test 2: Tim moi nghiem " +
" voi n = 8");
Test2();
Console.WriteLine("\n Fini ");
Console.ReadLine();
} // Main
// Test 1: tim 1 nghiem voi n = 1..10
static void Test1()
{
for (int i = 1; i <= 10; ++i)
{
Console.Write(" \n n = " + i + ": ");
if (XepHau(i)) Print(v, n);
else Console.WriteLine(" Vo Nghiem");
}
}
static bool XepHau(int SoHau)
{
if (SoHau > mn || SoHau < 1) return false;
n = SoHau;
Array.Clear(v,0,v.Length);
Array.Clear(dd,0,dd.Length);
Array.Clear(c1,0,c1.Length);
Array.Clear(c2,0,c2.Length);
int k = 1; // Hau dang xet
int dong = 0;// dong dat Hau k
do
{
if (k > n) return true;
if (k < 1) return false;
NhacHau(k);
if ((dong = TimNuocDi(k)) > 0)
{
DatHau(k, dong);
v[k++] = dong;// tien
}
else v[k--] = 0; // lui
} while (true);
}
// Nhac Hau k khoi vi tri dang dat
static public void NhacHau(int k)
{
if (v[k] == 0) return;
dd[v[k]] = c1[n+(k-v[k])] = c2[k+v[k]] = 0;
}
Sng to trong Thut ton v Lp trnh Tp I

174



// Dat Hau k tai dong i
static public void DatHau(int k, int i)
{
dd[i] = c1[n+(k-i)] = c2[k+i] = 1;
}
// Test2: Tim moi nghiem
static void Test2()
{
Console.WriteLine("\n Tong cong " +
XepHauNN(8) + " nghiem");
}
// Phuong an tim moi nghiem
// Phuong phap gia sai
static int XepHauNN(int SoHau)
{
int soNghiem = 0;
if (SoHau > mn || SoHau < 1) return 0;
Array.Clear(v, 0, v.Length);
Array.Clear(dd, 0, dd.Length);
Array.Clear(c1, 0, c1.Length);
Array.Clear(c2, 0, c2.Length);
StreamWriter f =
File.CreateText("N_HAU.OUT");
n = SoHau;
int k = 1;
int dong = 0;
do
{
if (k > n)
{
++soNghiem;
Console.Write("\n Nghiem thu "+
soNghiem + ": ");
Print(v, n);
for (int j = 1; j <= n; ++j)
f.Write(v[j] + " ");
f.WriteLine();
k = n;
}
if (k < 1)
{
f.WriteLine(soNghiem);
f.Close();
return soNghiem;
}
NhacHau(k);
if ((dong = TimNuocDi(k)) > 0)
{
DatHau(k, dong);
v[k++] = dong;// tien
}
else v[k--] = 0; // lui
} while (true);
Sng to trong Thut ton v Lp trnh Tp I

175



}
// Dich hau k tu vi tri hien tai v[k]
// xuong den dong cuoi (n)
// tim mot vi tri dat hau k
static int TimNuocDi(int k)
{
for (int i = v[k] + 1; i <= n; ++i)
if ((dd[i] + c1[n+(k-i)] + c2[k+i]) == 0)
return i;
return 0;
}
static void Print(int[] a, int n)
{
for (int i = 1; i <= n; ++i)
Console.Write(a[i] + " ");
}
} // TamHau
} // SangTao1
Bi 6.2. T chun
Mt t loi M l mt dy cc ch s, mi ch s nm trong khong t 1 n M.
S lng cc ch s c mt trong mt t c gi l chiu di ca t . T
loi M c gi l t chun nu n khng cha hai khc (t con) lin nhau m
ging nhau.
a) Vi gi tr N cho trc, hin th trn mn hnh mt t chun loi 3 c chiu
di N.
b) Vi mi gi tr N cho trc, tm v ghi vo tp vn bn tn TUCHUAN.OUT
mi t chun loi 3 c chiu di N.
1 s N s 40000.
Th d:
1213123 l t chun loi 3, chiu di 7.
1213213 khng phi l t chun v n cha lin tip hai t con ging nhau l
213.
Tng t, 12332 khng phi l t chun v cha lin tip hai t con ging
nhau l 3.
Bi gii
Ta dng mng v[1..n] lu t cn tm. Ti mi bc i ta xc nh gi tr v[i] trong
khong 1..m sao cho v[1..i] l t chun.
iu kin P: v[1..i] l t chun.
iu kin Q: Dng thut ton theo mt trong hai tnh hung sau y:
nu i = n th bi ton c nghim v[1..n].
nu i = 0 th bi ton v nghim.
TimTu1: Tm mt nghim.
{Khi tr mi v tr bng 0 }
for i := 1 to n do v[i] := 0;
i := 1;
repeat
if i > n then {co nghiem v[1..n]}
begin
KetQua1(n); {in nghiem v[1..n]}
Sng to trong Thut ton v Lp trnh Tp I

176



exit;
end;
if i < 1 then {vo nghiem}
begin
KetQua1(0);
exit;
end;
j := Tim(i);
if j > 0 then
begin
v[i] := j;
inc(i) {tin}
end
else
begin {Li}
v[i] := 0;
dec(i);
end;
until false;
Hm Tim hot ng nh sau: duyt cc gi tr ti v tr v[i] ca t v[1..i] k t
v[i] + 1 n m sao cho v[1..i] l t chun.
Tim = true nu tn ti mt gi tr v[i] nh vy. Ngc li, nu vi mi
v[i] = v[i] + 1..m t v[1..i] u khng chun th Tim = false.
function Tim(i: integer): Boolean;
begin
Tim := true;
while v[i] < 3 do
begin
inc(v[i]);
if Chuan(i) {v[1..i] la tu chuan}
then exit;
end;
Tim := false;
end;
kim tra tnh chun ca t v[1..i], ta lu rng t v[1..i-1] chun (tnh cht
P), do ch cn kho st cc cp t c cha v[i], c th l kho st cc cp t c chiu
di k ng cui t v. l cc cp t v[(ikk+1)..(ik)] v v[ik+1..i] vi k = 1..(i div
2). Nu vi mi k nh vy hai t u khc nhau th Chuan=true. Ngc li, Chuan
= false.
function Chuan(i: integer): Boolean;
var k: integer;
begin
Chuan := false;
for k := 1 to (i div 2) do
if Bang(i,k) then exit;
Chuan := true;
end;
Hm Bang(i,k) kim tra xem hai t k nhau chiu di k tnh t i tr v trc c
bng nhau hay khng.
Hai t c xem l khc nhau nu chng khc nhau ti mt v tr no .
function Bang(i,k: integer): Boolean;
Sng to trong Thut ton v Lp trnh Tp I

177



var j: integer;
begin
Bang := false;
for j := 0 to k-1 do
if v[i-j] <> v[i-k-j] then exit;
Bang := true;
end;
Th tc TimTu tm mi nghim ca bi ton.
(* Pascal *)
(*------------------------
Tu chuan
-----------------------*)
{$B- }
uses crt;
const
MN = 40; {Cho cau b: tim moi nghiem }
MN1 = 40000; {Cho cau a: tim 1 nghiem }
gn = 'TuChuan.OUT';
var
v: array[0..MN1] of byte; {chua nghiem }
n: integer; {chieu dai tu: tinh chat Q }
g: text; {output file }
(*----------------------------------------
Kiem tra hai tu ke nhau, chieu dai k
tinh tu vi tri i tro ve truoc co bang nhau ?
----------------------------------------*)
function Bang(i,k: integer): Boolean; t vit
(*-------------------------------------------
Kiem tra tu v[1..i] co la tu chuan ?
------------------------------------------*)
function Chuan(i: integer): Boolean; t vit
(*------------------------------------
Sua v[i] de thu duoc tu chuan
Tim = true: Thanh cong
Tim = false: That bai
-------------------------------------*)
function Tim(i: integer): Boolean; t vit
(*-------------------------------------
Hien thi ket qua, tu v[1..n]
(Cau a: tim 1 nghiem)
-------------------------------------*)
procedure KetQua1(k: integer);
var i: integer;
begin
writeln;
if k = 0 then write('Vo nghiem')
else for i := 1 to k do write(v[i]);
writeln;
end;
(*----------------------------------------
Quay lui: tim 1 nghiem cho bai toan
tu chuan chieu dai len, chi chua cac
Sng to trong Thut ton v Lp trnh Tp I

178



chu so 1..lim
----------------------------------------*)
procedure TimTu1(len: integer); t vit
(*--------------------------------
Test cau a: Tu chuan dai 200
chi chua cac chu so 1, 2, 3
--------------------------------*)
procedure Test1;
begin
clrscr;
TimTu1(200);
readln;
end;
(*---------------------------------
Ghi mot nghiem vao file
---------------------------------*)
procedure KetQua(d: integer);
var i: integer;
begin
if d = 0 then write(g,'Vo nghiem')
else
begin
write(g,'Nghiem thu ',d,': ');
for i := 1 to n do write(g,v[i]);
writeln(g);
end;
end;
(*--------------------------------------------
Cau b: Liet ke toan bo cac tu chuan
chieu dai len, chi chua cac chu so 1, 2,3
---------------------------------------------*)
procedure TimTu(len: integer);
var
i: integer;
d: longint;
begin
if (len < 1) or (len > MN) then exit;
n := len;
for i := 1 to n do v[i] := 0;
assign(g,gn);
rewrite(g);
i := 1;
d := 0;
repeat
if i > n then {tim duoc 1 nghiem v[1..n]}
begin
inc(d);
KetQua(d);
i := n;
end;
if i < 1 then {da vet het}
begin
if d = 0 then KetQua(0);
Sng to trong Thut ton v Lp trnh Tp I

179



close(g);
write('OK'); readln;
exit;
end;

if Tim(i) then inc(i) {tin }
else {Lui }
begin
v[i] := 0;
dec(i);
end;
until false;
end;
(*------------------------------------------
Test cau b: Liet ke toan bo cac
tu dai 16, chi chua cac chu so 1, 2,3
Ket qua ghi trong tep TuChuan.out
------------------------------------------*)
procedure Test;
begin
clrscr;
TimTu(16);
end;
BEGIN
Test;
END.
Vi N = 16, M = 3, c tng cng 798 nghim, tc l 798 t chun chiu di 16 to
t cc ch s 1, 2 v 3. Di y l 20 nghim u tin tm c theo thut ton.
Nghiem thu 1: 1213123132123121
Nghiem thu 2: 1213123132123213
Nghiem thu 3: 1213123132131213
Nghiem thu 4: 1213123132131231
Nghiem thu 5: 1213123132131232
Nghiem thu 6: 1213123132312131
Nghiem thu 7: 1213123132312132
Nghiem thu 8: 1213123132312321
Nghiem thu 9: 1213123212312131
Nghiem thu 10: 1213123212312132
Nghiem thu 11: 1213123212313212
Nghiem thu 12: 1213123212313213
Nghiem thu 13: 1213123212313231
Nghiem thu 14: 1213123213121321
Nghiem thu 15: 1213123213121323
Nghiem thu 16: 1213123213231213
Nghiem thu 17: 1213123213231232
Nghiem thu 18: 1213123213231321
Nghiem thu 19: 1213212312131231
Nghiem thu 20: 1213212312131232
Sng to trong Thut ton v Lp trnh Tp I

180



// C#
using System;
using System.IO;
namespace SangTao1
{
/*------------------------
* Tu chuan
* -----------------------*/
class TuChuan
{
static int mn = 500000;
static string fn = "TuChuan.out";
static int[] v = new int[mn + 1];
static int n = 0; // kich thuoc ban co
static int k = 0;
static void Main()
{
int sl = 10;
Console.WriteLine("Test 1: Tim 1 nghiem voi n = "+sl);
Test1(sl);
Console.WriteLine("Test 2: Tim moi nghiem voi n "+sl);
Test2(sl);
Console.WriteLine("\n Doc lai Ket qua:\n");
Console.WriteLine(File.ReadAllText(fn));
Console.WriteLine("\n Fini");
Console.ReadLine();
}
// Test 2: tim moi nghiem
static void Test2(int sl)
{
Console.WriteLine(" Tong cong " +
TimMoiTu(sl) + "
nghiem");
}
// Tim moi nghiem. Phuong phap gia sai
static int TimMoiTu(int len)
{
if (len > mn || len < 1) return 0;
StreamWriter f = File.CreateText(fn);
n = len;
int soNghiem = 0;
Array.Clear(v,0,v.Length);
k = 1;
do
{
if (k > n)
{
++soNghiem;
for (int i = 1; i <= n; ++i)
f.Write(v[i]);
f.WriteLine();
k = n;
}
Sng to trong Thut ton v Lp trnh Tp I

181



if (k < 1)
{
f.WriteLine(soNghiem);
f.Close();
return soNghiem;
}
if (CoNuocDi()) k++;// tien
else v[k--] = 0; // lui
} while (true);
}
// Test 1: tim 1 nghiem
static void Test1(int sl)
{
if (TimTu(sl)) Print(v, n);
else Console.WriteLine("\n Vo Nghiem");
}
static bool TimTu(int len)
{
if (len > mn || len < 1) return false;
n = len;
for (int i = 0; i <= n; ++i) v[i] = 0;
k = 1;
do
{
if (k > n) return true;
if (k < 1) return false;
if (CoNuocDi()) k++;// tien
else v[k--] = 0; // lui
} while (true);
}
static bool CoNuocDi()
{
while (v[k] < 3)
{
++v[k];
if (Chuan()) return true;
}
return false;
}
// Kiem tra v[1..k] la tu chuan
static bool Chuan()
{
int k2 = k / 2;
for (int j = 1; j <= k2; ++j)
if (Bang(j)) return false;
return true;
}
// v[k-2d+1..k-d]==v[k-d+1..k] ?
static bool Bang(int d)
{
int kd = k - d;
for (int i = 0; i < d; ++i)
if (v[k - i] != v[kd - i]) return false;
Sng to trong Thut ton v Lp trnh Tp I

182



return true;
}
static void Print(int[] a, int n)
{ // moi dong 50 ki tu
for (int i = 1; i <= n; ++i)
Console.Write(a[i]+
((i%50==0)?"\n":""));
Console.WriteLine();
}
} // TuChuan
} // SangTao1
Bi 6.3. Tm ng trong m cung.
M cung l mt th v hng bao gm N nh, c m s t 1 n N, vi
cc cnh, mi cnh ni hai nh no vi nhau. Cho hai nh S v T trong
mt m cung. Hy tm mt ng i bao gm cc cnh gi u nhau lin tip
bt u t nh S, kt thc ti nh T sao cho khng qua nh no qu mt ln.
D liu vo: Tp vn bn tn MECUNG.INP vi cu trc nh sau:
- Dng u tin, c gi l dng 0, cha ba s t nhin N, S v T ghi cch
nhau bi du cch, trong N l s lng nh ca m cung, S l nh xut
pht, T l nh kt thc.
- Dng th i, i = 1..(N - 1) cho bit c hay khng cnh ni nh i vi nh j,
j = (i + 1)..N.
Th d:
cho bit:
- Dng 0: 9 6 7 - m cung gm 9 nh m
s 1..9, cn tm ng i t nh 6 n nh 7.
- Dng 1: 1 0 1 1 1 0 0 0 - nh 1 c ni
vi cc nh 2, 4, 5, v 6. Khng c cnh ni nh 1
vi cc nh 3, 7, 8 v 9.
- ...
- Dng 8: 1 nh 8 c ni vi nh 9.
V th l v hng nn cnh ni nh x vi
nh y cng chnh l cnh ni nh y vi nh x.
Thng tin v nh N khng cn thng bo, v vi
mi nh i ta ch lit k cc nh j > i to thnh cnh (i, j).
Kt qu ra ghi trong tp vn bn MECUNG.OUT:
- Dng u tin ghi s t nhin k l s nh trn ng i t s n t, nu v
nghim, ghi s 0.
- T dng tip theo ghi ln lt cc nh c trn ng i.
Vi th d cho kt qu c th l:

T nh 6 c th n c nh 7, qua 5 nh theo
ng bn khc:
6 4 2 3 7.

MECUNG.INP
9 6 7
1 0 1 1 1 0 0 0
1 1 0 0 0 0 0
0 0 0 1 0 0
0 1 1 0 0
0 0 0 0
0 0 0
0 0
1

MECUNG.OUT
5
6 4 2 3 7
Sng to trong Thut ton v Lp trnh Tp I

183



Vi m cung cho, nu yu cu tm ng i t nh 6 n nh 9, tc l vi d liu vo
nh trn th s nhn c kt qu 0 vi ngha l khng c ng i t nh 6 n nh 9,
do m cung cho khng lin thng, nh 6 v nh 9 nm trong hai vng lin thng khc
nhau.











Thut ton
Xut pht t nh v[1] = s, mi bc lp i ta thc hin cc kim tra sau. Gi k l s nh
i qua v c tch lu trong mng gii trnh ng i v, c th l xut pht t nh v[1]
= s, sau mt s ln duyt ta quyt nh chn ng i qua cc nh v[1], v[2], v[3],, v[k].
C th gp cc tnh hung sau:
a) (n ch?) nu v[k] = t tc l n c nh t: thng bo kt qu, dng thut
ton, ngc li thc hin b.
b) (Tht bi?) k = 0: nu quay tr li v tr xut pht v[i] = s m t khng cn
ng i no khc th phi li mt bc na, do k = 0. Trng hp ny chng t bi
ton v nghim, tc l, do th khng lin thng nn khng c ng i t nh s n
nh t. Ta thng bo v nghim v dng thut ton.
c) (i tip?) nu t nh v[k] tm c mt cnh cha i qua v dn n mt nh i
no th tin theo ng , nu khng: thc hin bc d.
d) (Li mt bc) B nh v[k], li li nh v[k-1].
Thut ton trn c tn l si ch Arian c phng theo mt truyn thuyt c
Hy Lp sau y. Anh hng Te-dy phi tm dit con qui vt nhn ngu (u ngi,
mnh tru) Minotav n nu trong mt phng ca m cung c nhiu ng ngch rc ri
tng lm lc bc nhiu dng s v nhng ngi ny u tr thnh nn nhn ca
Minotav. Ngi yu ca chng Te-dy l cng cha ca x Mino a cho chng mt
cun ch v dn chng nh sau: Chng hy buc mt u ch vo ca m cung (phng
xut pht s), sau , ti mi phng trong m cung, chng hy tm xem c Minotav n
trong khng. Nu c, chng hy chin u dng cm h th n ri cun ch quay
ra ca hang, ni em trng ngng chng. Nu cha thy Minotav ti phng , chng
hy kim tra xem ch c b ri hay khng. Cun ch bt u ri khi no t phng chng
ng c hai si ch i ra hai ca khc nhau. Nu ch ri nh vy, chng hy cun ch li
li mt phng v nh nh du ng i khi lc bc vo ln th hai.
Nu khng gp ch ri th chng hy yn tm d tm mt ca cha i qua phng
khc. i n u chng nh nh ch theo n . Nu khng c ca i tip hoc t phng
chng ang ng, mi ca ra u c chng i qua ri, th chng hy cun ch li li
mt phng ri tip tc tm ca khc.
Ta xut pht t s tng qut cho lp bi ton quay lui.
1
1
2
4 6 5 9
8 3
7
Sng to trong Thut ton v Lp trnh Tp I

184



(* Pascal *)
(*----------------------------------------
MC - Tim duong trong me cung
(Thuat toan Arian)
s: dinh xuat phat
t: dinh ket.
------------------------------------------*)
procedure MC;
var i: byte;
begin
Doc; {doc du lieu}
{----------------------------
khoi tao mang d,
danh dau cac dinh da tham:
d[i] = 1: dinh da tham
d[i] = 0: dinh chua tham
-----------------------------}
fillchar(d,sizeof(d),0);
k := 1; {k dem so dinh da chon }
v[k] := s; {dinh xuat phat }
d[s] := 1; {da tham dinh s }
repeat
if v[k] = t then {den dich }
begin
ket(k); {ghi ket qua: giai trinh duong di }
exit;
end;
if k < 1 then {vo nghiem }
begin
ket(0);
exit;
end;
i := Tim;
{tu dinh v[k] tim 1 dinh chua tham i }
if i > 0 then
{neu tim duoc, i > 0, di den dinh i }
NhaChi(i)
else CuonChi;
{neu khong tim duoc, }
{ i = 0: lui 1 buoc - bo dinh v[k] }
until false;
end;
Th tc Doc - c d liu t tp MECUNG.INP vo mng hai chiu a. y chnh
l ma trn k ca th biu din m cung. Mng a s i xng v m cung l th v
hng. y cng chnh l l do gii thch d liu vo ch cho di dng na trn ca ma
trn k.
(*-------------------------
Doc du lieu
------------------------*)
procedure Doc;
var i,j: byte;
begin
Sng to trong Thut ton v Lp trnh Tp I

185



assign(f,fn);
reset(f);
read(f,n,s,t);
fillchar(a,sizeof(a),0);
if (n < 1) or (n > MN) then exit;
for i := 1 to n-1 do
for j := i+1 to n do
begin
read(f,a[i,j]);
a[j,i] := a[i,j]; {lay doi xung }
end;
close(f);
end;
Th tc Xem hin th d liu trn mn hnh kim tra vic c c ng khng.
Vi nhng ngi mi lp trnh cn lun lun vit th tc Xem. Khi np bi th c th b
li gi th tc ny. Cc hng kiu string bl = #32 l m ASCII ca du cch,
hng nl = #13#10 l mt xu cha hai k t iu khin c m ASCII l xung dng
#13, tc l ng vi phm RETURN v a con tr mn hnh v u dng #10. Khi
lnh writeln s tng ng vi lnh write(nl).
(*------------------------
Xem du lieu
-------------------------*)
procedure xem;
var i,j: byte;
begin
write(nl,n,bl,s,bl,t,nl);
for i := 1 to n do
begin
for j := 1 to n do
write(a[i,j],bl);
write(nl);
end;
end;
Th tc Ket(k) - ghi ng i v[1..k] t s n t tm c vo tp output.
Ket(0): thng bo v nghim.
(*------------------------------
Ghi ket qua.
k = 0: vo nghiem
k > 0: co duong tu s den t
gom k canh
------------------------------*)
procedure Ket(k: byte);
var i: byte;
begin
assign(g,gn); rewrite(g);
write(g,k,nl);
if k > 0 then
begin
write(g,v[1]);
for i := 2 to k do
write(g,bl,v[i]);
Sng to trong Thut ton v Lp trnh Tp I

186



end;
close(g);
end;
Hm Tim - t nh v[k] tm mt bc i n nh i. iu kin: i phi l nh cha
thm v ng nhin c cnh i t v[k] n i, ngha l gi tr a[v[k], i] trong ma trn k
phi l 1. Ta dng mt mng d nh du nh i thm cha. d[i] = 0 nh i cha
thm, d[i] = 1 nh i thm v tng c chn a vo mng v l mng gii
trnh ng i. Nu tm kim thnh cng ta gn cho hm Tim gi tr i, chnh l nh cn
n. Ngc li, khi vic tm kim tht bi, ngha l khng tm c nh i c th i
t nh v[k] n , ta gn cho hm Tim gi tr 0.
Ta lu l mi nh ch i n khng qu mt ln. ng nhin khi li th ta buc
phi quay li nh n, do , chnh xc hn ta phi gi d[i]=1 l gi tr nh du khi
tin n nh i.
(*-------------------------------------
Tu dinh v[k] tim duoc mot buoc di
den dinh i. Dieu kien:
d[i] = 0 - dinh i chua xuat hien
trong lich trinh v
d[i] = 1 - dinh i da xuat hien
trong lich trinh v.
--------------------------------------*)
function Tim: byte;
var i: byte;
begin
Tim := 0;
for i := 1 to n do
if d[i] = 0 then {dinh i chua tham }
if a[v[k],i] = 1 {co duong tu v[k] den i }
then
begin
Tim := i;
exit;
end;
end;
Nu tm c nh cha thm tho cc iu kin ni trn ta tin thm mt bc
theo cnh (v[k], i). Ta cng nh du nh i l thm bng lnh gn d[i]: = 1. l
ni dung ca th tc NhaChi (nh ch).
(*---------------------------
Di 1 buoc tu v[k] den i
----------------------------*)
procedure NhaChi(i: byte);
begin
inc(k);
v[k] := i; {tien them 1 buoc }
d[i] := 1; {danh dau dinh da qua }
end;
Nu t nh v[k] ta khng tm c nh no i tip th ta phi thc hin th tc
CuonChi (cun ch) nh di y. Th tc ny ch n gin l li mt bc t nh
Te-dy hin ang ng tr v nh trc , nu c, tc l k > 1, ta nh du cnh (v[k -
1], v[k]) l i hai ln. Ta nhn xt rng, nu khng tnh ln tr li mt nh khi phi
Sng to trong Thut ton v Lp trnh Tp I

187



li mt bc th mi nh trong m cung ch cn thm ti a l mt ln, do thay v
nh du cnh ([v[k - 1], v[k]) ta ch cn nh du nh v[k] l .
(*-------------------------------------
Lui 1 buoc vi tu dinh v[k] khong
co kha nang nao dan den ket qua
-------------------------------------*)
procedure CuonChi;
begin
dec(k);
end;
(* Pascal *)
(*------------------------------------
MECUNG.PAS Tim duong trong me cung
-------------------------------------*)
{$B-}
uses crt;
const
MN = 100; {So dinh toi da }
fn = 'MECUNG.INP'; {input file }
gn = 'MECUNG.OUT'; {output file }
nl = #13#10; {xuong dong moi }
bl = #32; {dau cach }
type
MB1 = array[0..MN] of byte;
MB2 = array[0..MN] of MB1;
var
a: MB2; {ma tran ke, doi xung }
v: MB1; {vet tim kiem }
d: MB1; {danh dau dinh da chon }
n: byte; {so dinh }
s: byte; {dinh xuat phat }
t: byte; {dinh ket thuc }
k: byte; {buoc duyet }
f,g: text; {f: input file; g: output file}
(*-----------------------
Doc du lieu
------------------------*)
procedure Doc; t vit
(*------------------------
Xem du lieu
-------------------------*)
procedure xem; t vit
(*---------------------------------------
Ghi ket qua.
k = 0: vo nghiem
k > 0: co duong tu s den t gom k canh
----------------------------------------*)
procedure Ket(k: byte); t vit
(*--------------------------------------------
Tu dinh v[k] tim duoc mot buoc di den dinh i.
Dieu kien:
Sng to trong Thut ton v Lp trnh Tp I

188



d[i] = 0 - dinh i chua xuat hien
trong lich trinh v
d[i] = 1 - dinh i da xuat hien
trong lich trinh v,
---------------------------------------------*)
function Tim: byte; t vit
(*---------------------------
Di 1 buoc tu v[k] den i
----------------------------*)
procedure NhaChi(i: byte); t vit
(*-------------------------------------
Lui 1 buoc vi tu dinh v[k] khong co kha nang nao
dan den ket qua
-------------------------------------*)
procedure CuonChi; t vit
(*-------------------------------
Tim duong trong me cung
(Thuat toan Soi chi Arian)
s: dinh xuat phat
t: dinh ket.
-------------------------------*)
procedure MC; t vit
BEGIN
MC; write(nl,'fini');
END.
Vi th d cho trong bi, bn hy chy th chng trnh MECUNG.PAS vi
hai d liu kim th, mt d liu kim th c nghim v mt d liu kim th v
nghim.
Ch
ng i tm c khng phi l ng ngn nht. Trong chng 7 ta s dng
thut gii Dijkstra tm ng i ngn nht.
// C#
using System;
using System.IO;
namespace SangTaoT1
{
/*------------------------------------
* Tim duong trong me cung
* -----------------------------------*/
class MeCung
{
static string fn = "MeCung.INP";
static string gn = "MeCung.OUT";
static int mn = 200; // So dinh toi da
static int[] v; // vet duong di
static int[] d;// dinh dang xet
static int[,] c; // ma tran ke 0/1
static int n = 0; // So dinh
static int s = 0; // Dinh xuat phat
static int t = 0; // Dinh ket
static int k = 0; // buoc duyet
Sng to trong Thut ton v Lp trnh Tp I

189




static void Main()
{
Doc(); Show(); Ghi(MC());
// Doc lai de kiem tra
Console.WriteLine("\n Kiem tra");
Console.WriteLine("\n Input: \n");
Console.WriteLine(File.ReadAllText(fn));
Console.WriteLine("\n Output: ");
Console.WriteLine(File.ReadAllText(gn));
Console.WriteLine("\n Fini ");
Console.ReadLine();
} // Main
static void Doc()
{
int[] a = Array.ConvertAll(
((File.ReadAllText(fn)).Trim()).
Split(new char[] { ' ', '\n', '\r', '\t', '\0' },
StringSplitOptions.RemoveEmptyEntries),
new Converter<String, int>(int.Parse));
n = a[0]; // so dinh
s = a[1]; // dinh xuat phat
t = a[2]; // dinh ket
c = new int[n + 1, n + 1];
// c ma tran ke
v = new int[n + 1]; // vet duong di
d = new int[n + 1];
// d[i] = 1: da tham dinh i
k = 2;
for (int i = 1; i <= n; ++i)
{
c[i, i] = 0;
for (int j = i + 1; j <= n; ++j)
c[i, j] = c[j,i] = a[++k];
}
}
// Hien thi de kiem tra
// thu tuc doc du lieu
static void Show()
{
Console.WriteLine("\n" + n + " "
+ s + " " + t);
for (int i = 1; i <= n; ++i)
{
Console.WriteLine();
for (int j = 1; j <= n; ++j)
Console.Write(c[i, j] + " ");
}
}
static void Ghi(bool Ket)
{
StreamWriter f = File.CreateText(gn);
if (Ket) // co nghiem
Sng to trong Thut ton v Lp trnh Tp I

190



{
f.WriteLine(k);
for (int i = 1; i <= k; ++i)
f.Write(v[i] + " ");
}
else f.WriteLine(0);// vo nghiem
f.Close();
}
static bool MC()
{
Array.Clear(v, 0, v.Length);
Array.Clear(v, 0, v.Length);
k = 1; // Buoc duyet
v[k] = s; d[s] = 1;
// danh dau phong da den
int phong = 0;
do
{
if (v[k] == t)
return true; // den dich
if (k < 1)
return false; // het cach
if ((phong = Tim()) > 0)
{ // Tien them 1 buoc
// nha chi, danh dau
v[++k] = phong; d[phong] = 1;
}
else --k; // lui
} while (true);
}
// Tu phong v[k] tim duoc
//mot duong sang phong khac
static int Tim()
{
for (int j = 1; j <= n; ++j)
if (d[j] == 0)// phong j chua tham
if (c[v[k], j] > 0)
//co hanh lang toi j
return j;
return 0;
}
} // MeCung
} // SangTao1



Sng to trong Thut ton v Lp trnh Tp I

191



CHNG 7
QUY HOCH NG


Cc bi ton quy hoch ng chim mt v tr kh quan trng trong t chc hot
ng v sn xut. Chnh v l m trong cc k thi hc sinh gii quc gia v quc t
chng ta thng gp loi ton ny.
Thng thng nhng bn no dng phng php quay lui, vt cn cho cc bi ton
quy hoch ng th ch c th vt c cc tp d liu nh, kch thc chng vi chc
byte. Nu tm c ng h thc th hin bn cht quy hoch ng ca bi ton v
kho t chc d liu th ta c th x l c nhng tp d liu kh ln.
C th tm lc nguyn l quy hoch ng do Bellman pht biu nh sau:
Quy hoch ng
Quy hoch ng l lp cc bi ton m quyt nh
bc th i ph thuc vo quyt nh cc bc
x l trc hoc sau .
gii cc bi ton quy hoch ng, ta c th theo s sau y:
S gii bi ton quy hoch ng
1. Lp h thc: Lp h thc biu din tng quan quyt nh ca bc
ang x l vi cc bc x l trc . Khi c h thc tng quan
chng ta c th xy dng ngay thut gii, tuy nhin cc h thc ny
thng l cc biu thc quy, do d gy ra hin tng trn min
nh khi ta t chc chng trnh trc tip bng quy.
2. T chc d liu v chng trnh: T chc d liu tnh ton dn theo
tng bc. Nn tm cch kh quy. Trong cc bi ton quy hoch ng
thuc chng trnh ph thng thng i hi mt vi mng hai chiu.
3. Lm tt: Lm tt thut ton bng cch thu gn h thc quy hoch ng
v gim kch thc min nh.
Bi 7.1. Chia thng
Cn chia ht m phn thng cho n hc sinh sp theo th t t gii tr xung
sao cho mi bn khng nhn t phn thng hn bn xp sau mnh.
1 s m, n s 70.
Hy tnh s cch chia.
Th d, vi s phn thng m = 7, v s hc sinh n = 4 s c 11 cch chia 7
phn thng cho 4 hc sinh theo yu cu ca u bi. l:

Sng to trong Thut ton v Lp trnh Tp I

192



Phng n C C
1 7 0 0 0
2 6 1 0 0
3 5 2 0 0
4 5 1 1 0
5 4 3 0 0
6 4 2 1 0
7 3 3 1 0
8 3 2 2 0
9 4 1 1 1
10 3 2 1 1
11 2 2 2 1
Bi gii
1. Lp h thc
Gi Chia(i, j) l s cch chia i phn thng cho j hc sinh, ta thy:
- Nu khng c hc sinh no (j = 0) th khng c cch chia no (Chia = 0).
- Nu khng c phn thng no (i = 0) th ch c mt cch chia
(Chia(0,j) = 1 - mi hc sinh nhn 0 phn thng). Ta cng quy c
Chia(0, 0) = 1.
- Nu s phn thng t hn s hc sinh (i < j) th trong mi phng n chia,
t hc sinh th i + 1 tr i s khng c nhn phn thng no:
Chia(i, j) = Chia(i, i) nu i < j.
Ta xt tt c cc phng n chia trong trng hp i > j. Ta tch cc phng n chia
thnh hai nhm khng giao nhau da trn s phn thng m hc sinh ng cui bng
thnh tch, hc sinh th j, c nhn:
- Nhm th nht gm cc phng n trong hc sinh th j khng c
nhn thng, tc l i phn thng ch chia cho j - 1 hc sinh v do , s
cch chia, tc l s phn t ca nhm ny s l: Chia(i, j - 1).
- Nhm th hai gm cc phng n trong hc sinh th j cng c nhn
thng. Khi , do hc sinh ng cui bng thnh tch c nhn thng
th mi hc sinh khc cng s c thng. Do ai cng c thng nn ta
bt ca mi ngi mt phn thng ( h lnh sau), s phn thng cn
li (i - j) s c chia cho j hc sinh. S cch chia khi s l Chia(i - j, j).
Tng s cch chia cho trng hp i > j s l tng s phn t ca hai nhm, ta c:
Chia(i, j) = Chia(i, j - 1) + Chia(i - j, j).
Tng hp li ta c:

iu kin
i: s phn thng
j: s hc sinh
Chia(i, j)
j = 0 Chia(i, j) = 0
i = 0 and j = 0 Chia(i, j) = 1
Sng to trong Thut ton v Lp trnh Tp I

193



i < j Chia(i, j) = Chia(i, i)
i > j Chia(i, j) = Chia(i, j 1) + Chia(i j, j)
Cc tnh cht ca hm Chia(i, j)
Chia i phn thng cho j hc sinh
2. T chc d liu v chng trnh
Ta c phng n u tin ca gii thut Chia nh sau:
(*-------------------------------------
PHUONG AN 1: de quy.
So cach Chia i phan thuong cho j hs
--------------------------------------*)
function Chia(i,j: integer):longint;
begin
if j = 0 then Chia := 0
else {j > 0 }
if i = 0 then {i = 0; j > 0 }
Chia := 1
else {i,j > 0 }
if i < j then {0 < i < j }
Chia := Chia(i,i)
else {i >= j > 0 }
Chia := Chia(i,j-1)+Chia(i-
j,j);
end;

Phng n ny chy chm v pht sinh ra qu
nhiu ln gi hm trng lp. Bng di y lit k s
ln gi hm Chia khi gii bi ton chia thng vi by
phn thng (m = 7) v 4 hc sinh (n = 4). Th d, hm
Chia(1,1) s c gi 9 ln, Tng s ln gi hm
Chia l 79. 79 ln gi hm sinh ra kt qu 11 l qu
tn km.
Lm tt ln 1: Phng n 1 kh d trin khai nhng
chng trnh s chy rt lu, bn hy th gi
Chia(66,32) tri nghim c iu trn. Din t
quy thng trong sng, nhn tn, nhng khi thc hin s
sinh ra hin tng gi lp li nhng hm quy. Ci tin
u tin l trnh nhng ln gi lp nh vy. Mun th
chng ta tnh sn cc gi tr ca hm theo cc tr ca u
vo khc nhau v in vo mt mng hai chiu cc.
Mng cc c m t nh sau:
O O O O O
0 9 1 1 0
9 9 2 1 0
C 6 6 1 0 0
C 5 5 2 1 1
3 3 1 1 0
C 2 2 1 0 0
C 1 1 0 0 0
C 1 1 1 1 1
S ln gi hm Chia cc b
khi tnh hm Chia(C,O)

j - 1 j

i - j
[i-j,j]
... ...
Sng to trong Thut ton v Lp trnh Tp I

194



const
MN = 70;{ gioi han tren
cua m va n }
type
ml1 = array[0..MN] of longint;
ml2 = array[0..mn] of ml1;
var cc: ml2;
Ta quy c cc[i, j] cha s cch chia i phn thng cho j hc sinh.
Theo phn tch ca phng n 1, ta c:
cc[0, 0] = 1; cc[i, 0] = 0, vi i:=1..m.
cc[i, j] = cc[i, i], nu i < j
cc[i, j] = cc[i, j-1]+cc[i-j, j], nu i > j.
T ta suy ra quy trnh in tr vo bng cc nh sau:
Khi tr
cc[0,0 ]:= 1;
vi i := 1..m: cc[i,0] := 0;
in bng: Ln lt in theo tng ct j:= 1..n. Ti mi ct j ta t:
vi i := 0..j-1: cc[i,j] := cc[i,i];
vi i := j..m: cc[i,j] := cc[i,j-1]+cc[i-j,j];
Nhn kt qu: Sau khi in bng, gi tr cc[m, n] chnh l kt qu cn tm.
(*-------------------------------------
PHUONG AN 2: dung mang 2 chieu cc
cc[i,j] = Chia(i,j) - so cach chia i
phan thuong cho j hs
-------------------------------------*)
function Chia2(m,n: integer):longint;
var i,j: integer;
begin
cc[0,0] := 1;
for i := 1 to m do cc[i,0] := 0;
for j := 1 to n do
begin
for i := 0 to j-1 do cc[i,j] := cc[i,i];
for i := j to m do
cc[i,j] := cc[i,j-1]+cc[i-j,j];
end;
Chia2 := cc[m,n];
end;
Lm tt ln 2: Dng mng hai chiu chng ta ch c th tnh ton c vi d liu
nh. Bc ci tin sau y kh quan trng: chng ta dng mng mt chiu. Quan st k
quy trnh gn tr cho mng hai chiu theo tng ct chng ta d pht hin ra rng ct th
j c th c tnh ton t ct th j - 1. Nu gi c l mng mt chiu s dng, ta cho s
hc sinh tng dn bng cch ln lt tnh j bc, vi j := 1..n. Ti bc th j, c[i] chnh
l s cch chia i phn thng cho j hc sinh. Nh vy, ti bc th j ta c:
- c[i] ti bc j = c[i] ti bc (j 1), nu i < j. T y suy ra on c[0..(j 1)]
c bo lu.
- c[i] ti bc j = c[i] ti bc (j 1) + c[i j] ti bc j, nu i > j.
Biu thc th hai cho bit khi cp nht mng c t bc th j 1 qua bc th j ta phi
tnh t trn xung, ngha l tnh dn theo chiu tng ca i := j..m.
Mng c c khi tr bc j = 0 nh sau:
i [i,j-1] [i,j]

Sng to trong Thut ton v Lp trnh Tp I

195



- c[0] = 1; c[i] = 0, vi i := 1..m.
Vi ngha l, nu c 0 hc sinh th chia 0 phn thng cho 0 hc sinh s c
quy nh l 1. Nu s phn thng m khc 0 th chia m phn thng cho 0 hc sinh s
c 0 phng n.
Ta c phng n ba, dng mt mng mt chiu c nh sau:
(*----------------------------------------
PHUONG AN 3: dung mang 1 chieu c
Tai buoc j, c[i] = so cach chia i
phan thuong cho j hoc sinh.
-----------------------------------------*)
function Chia1(m,n: integer):longint;
var i,j: integer;
begin
fillchar(c,sizeof(c),0);
c[0] := 1;
for j := 1 to n do
for i := j to m do c[i] := c[i]+c[i-j];
Chia1 := c[m];
end;
so snh cc phng n bn hy t mt b m nhp ca my nh sau:
nhip: longint absolute $0000:$046c;
{xac dinh nhip thoi gian }
t: longint; {ghi nhan nhip }
Sau bn to mt d liu kim th so snh ba phng n phn tch phn
trn nh sau:
procedure test;
begin
randomize; {Khoi dong bo sinh so ngau nhien }
repeat
m := random(mn)+1; {sinh ngau nhien so phan
thuong m }
n := random(mn)+1; {sinh ngau nhien so hs n }
writeln(m,bl,n); {xem du lieu vao }
t := Nhip; {dat nhip cho PA 3 }
{Phuong an 3 }
writeln('Mang 1 chieu: ',Chia1(m,n));
{bao thoi gian }
writeln((Nhip-t)/18.2):0:0,' giay');
t := Nhip; {dat nhip cho PA 2}
writeln('Mang 2 chieu: ',Chia2(m,n)); {PA 2 }
{bao thoi gian }
writeln((Nhip-t)/18.2):0:0,' giay');
t := Nhip; {dat nhip cho PA 1 }
writeln('De quy: ',Chia(m,n));
{bao tgian}
writeln((Nhip-t)/18.2):0:0,' giay');
until readkey = #27; {lap den khi bam ESC }
end;
Cc gi tr m s phn thng v n s hc sinh c sinh ngu nhin nh hm
random. Trc cn gi th tc randomize chun b khi to b sinh s ngu
nhin.
Sng to trong Thut ton v Lp trnh Tp I

196



Trong b nh ca my tnh c 4 byte bt u t a ch $0000:$046c dng
ghi s nhp ca my tnh. Mi ln c gi tr ca bin Nhip ta c th ly c s nhp
hin hnh ca my. Hiu s hai ln c nhp lin tip s cho ta tng s nhp tnh t ln
c th nht n ln c th hai. Chia gi tr ny cho 18.2 ta c th quy ra lng thi
gian chy my tnh bng giy. Lnh write(r:d:p) hin th s thc r vi d v tr v p
ch s sau du phy. Nu t d = p = 0 th s thc r s c hin th y .
(* Pascal *)
uses crt;
const
MN = 70; {gioi han tren cua m va n }
nl = #13#10; {xuong dong }
bl = #32; {dau cach }
type
ml1 = array[0..MN] of longint;
ml2 = array[0..mn] of ml1;
var
cc: ml2; {cho phuong an 2 - mang 2 chieu }
m,n: integer;
c: ml1; {cho phuong an 3 mang 1 chieu }
nhip: longint absolute $0000:$046c;
{xac dinh nhip thoi gian }
t: longint; {ghi nhan nhip }
(*-------------------------------------
PHUONG AN 1: de quy
So cach Chia i phan thuong cho j hs
--------------------------------------*)
function Chia(i,j: integer):longint; t vit
(*-------------------------------------
PHUONG AN 2: dung mang 2 chieu cc
cc[i,j] = so cach chia i phan thuong
cho j hs
-------------------------------------*)
function Chia2(m,n: integer):longint; t vit
(*----------------------------------------
PHUONG AN 3: dung mang 1 chieu c
Tai buoc j, c[i] = so cach chia i
phan thuong cho j hoc sinh.
-----------------------------------------*)
function Chia1(m,n: integer):longint; t vit
procedure test; t vit
BEGIN
Test;
END.
Quan st hot ng ca chng trnh bn s rt ra c ngha ca cc phng n
ci tin.
Ch thch
Bi ton trn cn c cch pht biu khc nh sau: Hy tnh s cch biu din s
t nhin m thnh tng ca n s t nhin sp theo trt t khng tng. Th d, vi
m = 7, n = 4 ta c:
7 = 7 + 0 + 0 + 0 = 6 + 1 + 0 + 0 = ...
Sng to trong Thut ton v Lp trnh Tp I

197



// C#
using System;
using System.IO;
namespace SangTao1
{
/*------------------------------------
* Chia thuong
* -----------------------------------*/
class ChiaThuong
{
static void Main()
{
Console.WriteLine(Chia(7, 4));
Console.WriteLine("\n Fini");
Console.ReadLine();
} // Main
static long Chia(int m, int n)
{
long[] c = new long[m+1];
Array.Clear(c, 0, c.Length);
c[0] = 1;
for (int j = 1; j <= n; ++j)
for (int i = j; i <= m; ++i)
c[i] += c[i - j];
return c[m];
}
} // ChiaThuong
} // SangTao1

Bi 7. 2. Palindrome
Olympic Quc t, nm 2000, Bc Kinh, Trung Quc.
Dy k t s c gi l i xng (palindrome) nu cc phn t cch u u
v cui ging nhau. Cho dy s to bi n k t gm cc ch ci hoa v thng
phn bit v cc ch s. Hy cho bit cn xo i t s t nht l bao nhiu k
t thu c mt dy i xng. Gi thit rng sau khi xo bt mt s k t
t s th cc k t cn li s t ng xch li st nhau.
D liu vo ghi trong tp vn bn PALIN.INP vi cu trc nh sau:
Dng u tin l gi tr n, 1 s n s 1000.
Dng th hai l n k t ca dy vit lin
nhau.
D liu ra ghi trong tp vn bn PALIN.OUT: s lng k t cn xa.
Th d, vi dy s gm 9 k t, s = 'baeadbadb' th cn xo t nht 4 k t, chng
hn, cc k t th 5, 7, 8 v 9 s thu c dy i xng chiu di 5 l baeab:
baeadbadb baeab
D nhin l c nhiu cch xo. Th d, c th xo cc k t th 2, 3, 4 v 6 t dy s
thu c dy con i xng khc l bdadb vi cng chiu di 5:
baeadbadb bdadb
PALIN.INP PALIN.OUT
9
baeadbadb
4

Sng to trong Thut ton v Lp trnh Tp I

198



Tuy nhin p s l s t nht cc k t cn loi b khi s th l duy nht v bng 4.
Bi gii
Bi ton ny c nhiu bn c cng b li gii vi mt mng hai chiu kch
thc n
2
hoc vi ba mng mt chiu kch thc n, trong n l chiu di ca d liu
vo.
Vi mt nhn xt nh ta c th pht hin ra rng ch cn dng mt mng mt chiu
kch thc n v mt vi bin n l .
Gi dy d liu vo l s. Ta tm chiu di ca dy con i xng v di nht trch t
s. Khi s k t cn xo t s s l t = length(s) - length(v). Dy con y c hiu l
dy thu c t s bng cch xo i mt s phn t trong s. Th d vi dy
s = baeadbadb th dy con i xng di nht ca s s l baeab hoc bdadb,
Cc dy ny u c chiu di 5.
Lp h thc: Gi p(i, j) l chiu di ca dy con di nht thu c khi gii bi ton
vi d liu vo l on s[i..j]. Khi p(1, n) l chiu di ca dy con i xng di nht
trong dy n k t s[1..n] v do s k t cn loi b khi dy s[1..n] s l
n-p(1,n)
chnh l p s ca bi ton.
Ta lit k mt s tnh cht quan trng ca hm hai bin p(i, j). Ta c:
- Nu i > j, tc l ch s u tri ln hn ch s u phi, ta quy c t p(i, j) = 0.
- Nu i = j th p(i, i) = 1 v dy kho st ch cha ng 1 k t nn n l i xng.
- Nu i < j v s[i] = s[j] th p(i, j) = p(i + 1, j 1) + 2. V hai k t u v cui dy
s[i,j] ging nhau nn ch cn xc nh chiu di ca dy con i xng di nht trong
on gia l s[i + 1, j 1] ri cng thm 2 n v ng vi hai k t u v cui dy
l c.
- Nu i < j v s[i] = s[j], tc l hai k t u v cui ca dy con s[i..j] l khc nhau th
ta kho st hai dy con l s[i..(j 1)] v s[(i + 1)..j] ly chiu di ca dy con i
xng di nht trong hai dy ny lm kt qu:
p(i,j) = max(p(i,j-1),p(i+1,j))
Vn t ra l cn tnh p(1, n). M mun tnh c p(1, n) ta phi tnh c cc
p(i, j) vi mi i, j = 1..n.
Phng n quy
Phng n quy di y nh m t trong hm nguyn rec(i, j) tnh trc tip
gi tr p(i, j) theo cc tnh cht lit k. p s cho bi ton khi s l n-
rec(1,n)
(*------------------------------------
Phuong an de quy
------------------------------------*)
function rec(i,j: integer): integer;
begin
if i > j then rec := 0
else if i = j then rec := 1
else {i < j}
if s[i] = s[j]
then rec := rec(i+1,j-1)+2
else {i < j & s[i] = s[j]}
rec := max(rec(i,j-1),rec(i+1,j));
Sng to trong Thut ton v Lp trnh Tp I

199



end;

j-1 j b a e a d b a d b

O O O O O O O O O
b

1 1 1 3 3 5 5 5 5
a
C
0 1 1 3 3 3 3 3 3
i [i,j-1] [i,j] e
C
0 0 1 1 1 1 3 3 3
i+1 [i+1,j-1] [i+1,j] a

0 0 0 1 1 1 3 3 3
d
C
0 0 0 0 1 1 1 3 3
b
C
0 0 0 0 0 1 1 1 3
a
C
0 0 0 0 0 0 1 1 1
d

0 0 0 0 0 0 0 1 1
b

0 0 0 0 0 0 0 0 1


Ga tr ca hm p(i,j) i vi dy baeadbadb
i,j=1..9


Dng mt mng hai chiu
Gi quy s pht sinh cc li gi hm trng lp nh phn tch trong bi ton
7.1. Ta khc phc iu ny bng cch s dng mt mng hai chiu tnh trc cc gi
tr ca hm p(i, j), mi gi tr c tnh ti a mt ln. Nu dng mt mng hai chiu,
th d mng p[0..n, 0..n] th gi tr ca p[i, j] s c in ln lt theo tng ct, t ct
th 1 n ct th n. Ti mi ct ta in t di ln trn. Ta lu :
- Phn t ti ct i, dng j l gi tr p[i, j] chnh l chiu di ca dy con i xng
di nht khi kho st dy con s[i..j].
- Vi cc tr i > j, ta quy nh p[i, j] = 0. Nh vy na tam gic di ca ma trn
p s cha ton 0.
- Nu i = j th p[i, j] = 1. Nh vy, mi tr trn ng cho chnh ca ma trn p s
l 1.
- Vi cc cn li, to (i, j) s tho iu kin i < j, nn p[i, j] s c tnh nh
sau:
if s[i] = s[j] then p[i,j] = p[i+1,j-1]+2
else p[i,j] := max(p[i,j-1],p[i+1,j])
Bn hy th in mt vi gi tr cho bng trn rt ra quy lut.
Hy bt u vi ct 1: p[1, 1] = 0;
Sau n ct 2:
p[2, 2] = 1; p[1, 2] = max(p[1, 1], p[2, 2]) = 1, v s[1] = s[2].
Ri n ct 3:
p[3,3]=1; p[2,3] = max(p[2, 2], p[3, 3]) = 1, v s[2] = s[3];
p[1,3] = max(p[1,2], p[2,3]) = 1, v s[1] = s[3],
Dng hai mng mt chiu
Sng to trong Thut ton v Lp trnh Tp I

200



Ta s khng theo ui phng n dng mng hai chiu m hy cn c vo quy
lut in mng hai chiu vn dng cho hai mng mt chiu l v[0..(n + 1)] v d[0..(n
+ 1)]. Theo kinh nghim, ta nn khai bo kch thc mng rng hn chng hai phn t
s dng cc phn t ny nh nhng lnh canh cha cc gi tr khi u phc v cho
cc trng hp ch s i, j nhn cc gi tr 0 hoc n + 1.
Gi s mng v cha cc gi tr in ca ct j 1 trong mng hai chiu p. Ta s
in cc gi tr cho ct j ca mng p vo mng mt chiu d. Nh vy, ti bc j, phn
t v[i] s ng vi phn t p[j 1, i] cn phn t d[i] s ng vi p[j, i]. Th tc in tr
cho ct d ti bc j da theo kt qu lu trong ct v ca bc j 1 khi s nh sau:
for i := j-1 downto 1 do
begin
if s[i] = s[j] then d[i] := v[i+1]+2
else d[i] := max(v[i],d[i+1]);
end;
Sau mi ln lp vi j := 1..n ta chuyn gi tr ca d cho v chun b cho bc tip
theo.
(*---------------------------------
Quy hoach dong voi 2 mang
1 chieu d, v
----------------------------------*)
procedure QHD2;
var i,j: integer;
begin
fillchar(v,sizeof(v),0);
for j := 1 to n do
begin
d[j] := 1;
for i := j-1 downto 1 do
begin
if s[i]= s[j] then d[i] := v[i+1]+2
else d[i] := max(v[i],d[i+1]);
end;
v := d;
end;
writeln(nl,n-d[1]); {dap so}
end;
Dng mt mng mt chiu
C th ch s dng mt mng mt chiu d cho bi ton ny vi nhn xt sau y.
Ti bc cp nht th j, vi mi i = (j 1)..1 ta c d[i] = p[i, j] v c tnh nh sau:
Nu s[i] = s[j] th d[i] ti bc j bng d[i + 1] ti bc j 1 cng vi 2.
Nu s[i] = s[j] th
d[i] ti bc j bng max(d[i] ti bc j 1, d[i + 1] ti bc j).
Nu ta tnh t di ln, tc l tnh d[i] vi i = n..1 th d[i + 1] c s b ghi . Ta
dng hai bin ph t v tr bo lu gi tr ny.
(*---------------------------------
Quy hoach dong voi mang 1 chieu d
----------------------------------*)
procedure QHD1;
var i,j,t,tr: integer;
Sng to trong Thut ton v Lp trnh Tp I

201



begin
for j := 1 to n do
begin
tr := 0;
d[j] := 1;
for i := j-1 downto 1 do
begin
t := d[i];
if s[i]= s[j] then d[i] := tr+2
else d[i] := max(d[i],d[i+1]);
tr := t;
end;
end;
writeln(nl,n-d[1]); {dap so}
end;

D nhin phng n dng mt mng mt chiu s c coi trng v tit kim c
min nh. Tuy nhin, tinh mt cht, bn s pht hin ra rng thi gian tnh ton theo
phng n ny khng t hn phng n dng hai mng mt chiu. Tht vy, tnh mi
phn t ta phi dng thm hai php gn, trong khi dng hai mng mt chiu ta ch phi
thm mt php gn cho mi phn t. Hn na, dng hai mng mt chiu thng trnh
c nhm ln, do nhiu ngi thng chn phng n ny.
Ton vn chng trnh vi ba phng n, quy, dng hai mng mt chiu v
dng mt mng mt chiu khi s nh sau.
(* Pascal *)
uses crt;
const mn = 51;
bl = #32; nl = #13#10;
fn = 'palin.inp';
gn = 'palin.out';
type mi1 = array[0..mn] of integer;
mi2 = array[0..mn] of mi1;
mc1 = array[0..mn] of char;
var n: integer; { Chieu dai xau }
f,g: text;
s: mc1; { xau can xu li }
d,v: mi1;
c: mi2;
procedure Doc; t vit
function Max(a,b: integer): integer; t vit
(*-----------------------------------
Phuong an de quy
------------------------------------*)
function rec(i,j: integer): integer; t vit
(*------------------------------------
Quy hoach dong voi mang 2 chieu c
-------------------------------------*)
function QHD2C: integer; t vit
(*---------------------------------
Quy hoach dong voi 2 mang
1 chieu d, v
Sng to trong Thut ton v Lp trnh Tp I

202



----------------------------------*)
function QHD2DV: integer; t vit
(*---------------------------------
Quy hoach dong voi mang 1 chieu d
----------------------------------*)
function QHD1: integer; t vit
procedure Test;
begin
Doc;
writeln(nl,'Phuong an 1: De qui: ',n-rec(1,n));
writeln(nl,'Phuong an 2: Mang 2 chieu: ',n-QHD2C);
writeln(nl,'Phuong an 3: Hai Mang 1 chieu D, V: ',n-
QHD2DV);
writeln(nl,'Phuong an 4: Mang 1 chieu D: ',n-QHD1);
end;
BEGIN
Test;
readln;
END.
// C#
using System;
using System.IO;
namespace SangTaoT1
{
/*------------------------------------
* Palindrome
* -----------------------------------*/
class Palin
{
static string fn = "palin.inp";
static string gn = "palin.out";
static string s;
static int n = 0;
static void Main()
{
Doc();
File.WriteAllText(gn,XuLi().ToString());
// Doc lai de kiem tra
Console.WriteLine("\n Input file " + fn);
Console.WriteLine(File.ReadAllText(fn));
Console.WriteLine("\n Output file " + gn);
Console.WriteLine(" So ki tu can xoa: " +
File.ReadAllText(gn));
Console.ReadLine();
}
static void Doc()
{
StreamReader f = File.OpenText(fn);
n = int.Parse((f.ReadLine()).Trim());
s = (f.ReadLine()).Trim();
Sng to trong Thut ton v Lp trnh Tp I

203



f.Close();
}
static int XuLi()
{
int[] d = new int[n + 1];
int tr = 0;
int t = 0;
for (int j = 0; j < n; ++j)
{
tr = 0;
d[j] = 1;
for (int i = j - 1; i >= 0; --i)
{
t = d[i];
d[i] = (s[i]==s[j])?(tr+2)
:Max(d[i],d[i+1]);
tr = t;
}
}
return n - d[0];
}
static int Max(int a, int b)
{
return (a > b) ? a : b;
}
} // Palin
} // SangTao1
Bi 7.3. Cm hoa
Olympic Quc t nm 1999.
Cn cm ht k b hoa khc nhau vo n l xp thng hng sao cho b hoa c s
hiu nh c t trc b hoa c s hiu ln. Vi mi b hoa i ta bit gi tr
thm m khi cm b hoa vo l j l v[i, j].
Yu cu: Xc nh mt phng n cm hoa sao cho tng gi tr thm m l ln
nht.
D liu vo ghi trong tp vn bn HOA.INP:
- Dng u tin l hai tr k v n.
- T dng th hai tr i l cc gi tr v[i, j] trong khong 0..10, vi i = 1..k
v j = 1..n; 1 s k s n s 100.
D liu ra ghi trong tp vn bn HOA.OUT: dng u tin l tng gi tr thm
m ca phng n cm hoa ti u. T dng th hai l dy k s hiu l c
chn cho mi b hoa.
Cc s liu vo v ra u l s t nhin v c ghi cch nhau bi du cch
trn mi dng.
Th d:
HOA.INP HOA.OUT
4 6
1 1 6 4 3 10
9 1 4 7 2 7
7 2 6 10 2 3
24
1 3 4 6

Sng to trong Thut ton v Lp trnh Tp I

204



Kt qu cho bit tng gi tr thm m s
t l 24 (im) nu cm hoa nh sau:
- B hoa 1 cm vo l 1;
- B hoa 2 cm vo l 3;
- B hoa 3 cm vo l 4;
- B hoa 4 cm vo l 6.


Bi gii
Trc ht ta c d liu t tp HOA.INP vo cc bin k, n v v[i, j].
(*-----------------------------------

Doc du lieu
----------------------------------*)
procedure doc;
var i,j:byte;
begin
assign(f,fn);
reset(f);
readln (f,k,n);
for i := 1 to k do
for j := 1 to n do
read(f,v[i,j]);
close(f);
end;
Cc hng v bin c khai bo nh sau:
const
fn = 'hoa.inp'; {File du lieu vao }
gn = 'hoa.out'; {File du lieu ra }
mn = 101; {So luong toi da cac lo hoa: 100 }
bl = #32; {Dau cach }
nl = #13#10; {Xuong dong }
kk = (mn+7) div 8; {So bit danh dau cac lo hoa }
type
mb1 = array[0..mn] of byte; {mang byte 1 chieu }
mb2 = array[0..mn] of mb1; {mang byte 2 chieu }
ml1 = array[0..kk] of byte;
ml2 = array[0..mn] of ml1;
mi1 = array[0..mn] of integer;
var
n,k: byte; {n - so luong lo, k - so luong bo hoa }
v: mb2;
{v[i,j] - do tham my khi cam bo hoa i vao lo j }
L: ml2;
{cac mang danh dau lo hoa
bit(i) = 1: lo hoa duoc chon
bit(i) = 0: lo hoa roi}
T: mi1; {T[i,j]: tong so do tham mi
khi cam i bo hoa vao day j lo }
f,g: text; {files input va output }
6 10 7 1 3 9

Sng to trong Thut ton v Lp trnh Tp I

205



1. Lp h thc: Gi T(i, j) l tng gi tr thm m khi gii bi ton vi i b hoa m s
1..i v j l m s 1..j, tc l thm m thu c khi cm ht i b hoa u tin vo j
l u tin, ta thy:
a) Nu s b hoa nhiu hn s l, i > j th khng c cch cm no v u bi yu
cu phi cm ht cc b hoa, mi b vo ng 1 l.
T(i, j) = 0
b) Nu s b hoa bng s l (i = j) th ch c mt cch cm l b no vo l .
c) Ta xt trng hp s b hoa t hn hn s l (i < j). C hai tnh hung: l cui
cng, tc l th j c chn cho phng n ti u v l th j khng c
chn.
- Nu l cui cng, l th j c chn cm b hoa (cui cng) i th i -1 b
hoa u tin s c phn phi vo j - 1 l u tin. Tng gi tr thm m s khi
s l T(i - 1, j - 1) + v[i, j].
- Nu l th j khng c chn cho phng n ti u th i b hoa phi c cm
vo j-1 l u tin v do tng gi tr thm m s l T(i, j-1).
Tng hp li ta c gi tr ti u khi cm i b hoa vo j l l:
T(i,j) = max {T(i-1,j-1)+v[i,j],T(i,j-1)}
2. T chc d liu v chng trnh: Nu dng mng hai chiu T th ta c th tnh nh
trong bng di y:
Ngoi ra, ta cn cn t trong mi
ca bng trn mt mng d liu bao gm
n phn t nh du l hoa no c
chn cho mi tnh hung. Gi mng d
liu l L[i, j], ta d thy l nn in
bng ln lt theo tng ct, ti mi ct ta
in bng t di ln theo lut sau:
- Nu T[i-1, j-1] + v[i, j] > T[i, j-
1] th ta phi thc hin hai thao tc:
o t li tr T[i, j]:= T[i-1, j-1] + v[i, j].
o Ghi nhn vic chn l hoa j trong phng n mi, c th ly phng n cm
hoa (i-1, j-1) ri b sung thm thng tin chn l hoa j nh sau: t L[i, j]:= L[i-
1, j-1] v nh du phn t j trong mng L[i, j].
- Nu T[i-1, j-1] + v[i, j] T[i, j-1] th ta s khng chn l j cm b hoa i v
do ch cn copy L[i, j-1] sang L[i, j], tc l ta bo lu phng n (i, j-1).
3. Lm tt. Phng n dng mng hai chiu tn km v min nh. Ta c th dng mt
mng mt chiu T[0..100] xem nh mt ct ca bng T ni trn. Ta duyt j bc. Ti
bc th j, gi tr T[i] s l tr ti u khi cm ht i b hoa vo j l. Nh vy, ti bc
th j ta c:
- Nu T[i1] ti bc j -1 + v[i, j] > T[i] ti bc j - 1 th ta phi thc hin hai thao
tc:
o t li tr T[i] ti bc j:= T[i1] ti bc j -1 + v[i, j].
o Ghi nhn vic chn l hoa j trong phng n mi, c th ly phng n cm
hoa (i-1) bc j - 1 ri b sung thm thng tin chn l hoa j nh sau: t
L[i] ti bc j:= L[i - 1] ti bc j - 1 v nh du phn t j trong mng L[i].
- Nu T[i - 1] ti bc j - 1 + v[i, j] T[i] ti bc j - 1 th ta khng phi lm g
v s bo lu phng n c.
j 1 j


i1 [i-1,j-1]
i [i,j-1] [i,j]?

T(i,j) = max {T(i-1,j-1) +
v[i,j],T(i,j-1)}
Sng to trong Thut ton v Lp trnh Tp I

206



Biu thc so snh cho bit khi cp nht mng T t bc th j - 1 qua bc th j ta phi
tnh t di ln, ngha l tnh dn theo chiu gim ca i:= j..1.
nh du cc l hoa ta dng mng L[0..MN] mi phn t L[i] li l mt dy s
byte. Nu dng mt bit cho mi l hoa th s byte cn dng nh du ti a MN l
hoa phi l:
kk = (MN+7) div 8
Vi MN = 101 ta tnh c
kk = (101+7) div 8 = 13
Khi cn nh du l hoa th j trong dy L[i] ta bt bit th j trong L[i]. Khi cn xem l
th j c c chn hay khng ta gi hm GetBit ly tr (0 hoc 1) ca bit j trong
dy bit L[i].
Ta ch ti hai biu thc sau:
- xc nh byte th my trong dy cha bit j ta tnh:
b := j div 8;
- xc nh v tr ca bit j trong byte th b ta tnh:
p := j mod 8;
(* ------------------------------------------
Cho gia tri bit thu j trong day byte L[i]
-------------------------------------------*)
function getbit(i,j: byte):byte;
var b,p: byte;
begin
b := j div 8;
p := j mod 8;
getbit := (L[i][b] shr p) and 1;
end;
(* ----------------------------------------
Gan tri 1 cho bit j trong day byte L[i]
---------------------------------------*)
procedure batbit(i,j:byte);
var b,p: byte;
begin
b := j shr 3;
p := j and 7;
L[i][b] := L[i][b] or (1 shl p);
end;
Vi j = 0, tc l khi khng c l no v khng c b hoa no ta khi tr:
fillchar(L[0],16,0);
T[0] := 0;
Vi mi j = 1..n, ta lu s b hoa phi khng ln hn s l, tc l i j. Vi i = j
ta s cm mi b vo mt l. thc hin iu ny ta lu rng phn t L[j -1] ti
bc trc cho bit j -1 l u c hoa do ta ch cn nh du l th j cho bc j:
L[j] := L[j-1];
batbit(j,j);
Nh vy ta cn chia qu trnh duyt theo cc l hoa t 1..n thnh hai giai on.
Giai on 1: Duyt t l 1 n l k, trong k chnh l s b hoa v theo u bi,
k s n.
Giai on 2: Duyt nt n - k l hoa cn li.
Sng to trong Thut ton v Lp trnh Tp I

207



Phng n quy hoch ng vi mng mt chiu khi s nh sau:
(*------------------------
Quy hoach dong
------------------------*)
procedure xuly;
var i,j: byte;
begin
{1. Khoi tri }
fillchar(L,sizeof(L),0);
{danh dau cac lo hoa duoc chon }
T[0] := 0; {do tham mi }
{Vi co k bo hoa nen xet k lo dau tien }
for j := 1 to k do
begin
L[j] := L[j-1];
batbit(j,j);
T[j] := T[j-1]+v[j,j];
for i := j-1 downto 1 do
if T[i] < T[i-1]+v[i,j] then
begin
T[i] := T[i-1]+v[i,j];
L[i] := L[i-1];
batbit(i,j);
end;
end;
{xet cac lo con lai }
for j := k+1 to n do
for i := k downto 1 do
if T[i] < T[i-1]+v[i,j] then
begin
T[i] := T[i-1]+v[i,j];
L[i] := L[i-1];
batbit(i,j);
end;
end;
(* Pascal *)
(*==================================

Hoa.pas: Quy hoach dong

===================================*)
uses crt ;
const
fn = 'hoa.inp'; {File du lieu vao }
gn = 'hoa.out'; {File du lieu ra }
mn = 101; {So luong toi da cac lo hoa: 100 }
bl = #32; {Dau cach }
nl = #13#10; {Xuong dong }
kk = (mn+7) div 8; {So bit danh dau cac lo hoa }
type
mb1 = array[0..mn] of byte; {mang byte 1 chieu }
Sng to trong Thut ton v Lp trnh Tp I

208



mb2 = array[0..mn] of mb1; {mang byte 2 chieu }
ml1 = array[0..kk] of byte;
ml2 = array[0..mn] of ml1;
mi1 = array[0..mn] of integer;
var
n,k: byte; {n - so luong lo, k - so luong bo hoa }
v: mb2;
{v[i,j] - do tham my khi cam bo hoa i vao lo j }
L: ml2;
{cac mang danh dau lo hoa
bit(i) = 1: lo hoa duoc chon
bit(i) = 0: lo hoa roi }
T: mi1;
{T[i,j] tong do tham my khi cam i bo hoa vao day j
lo }
f,g: text; {files input va output }
(*-----------------------------------
Doc du lieu
----------------------------------*)
procedure doc; t vit
(* -----------------------------------------
Cho gia tri bit thu j trong day byte L[i]
-------------------------------------------*)
function getbit(i,j: byte):byte; t vit
(* ----------------------------------------
Gan tri 1 cho bit j trong day byte L[i]
-------------------------------------------*)
procedure batbit(i,j:byte); t vit
(*------------------------
Quy hoach dong
------------------------*)
procedure xuly; t vit
(*--------------------------------
Ghi ket qua T[k] -
Tong do tham mi cac lo duoc chon
----------------------------------*)
procedure ghi; t vit
BEGIN
doc; xuly; ghi;
END.
// C#
using System;
using System.IO;

namespace SangTaoT1
{
/*------------------------------------
* Cam hoa
* -----------------------------------*/
class CamHoa
{
Sng to trong Thut ton v Lp trnh Tp I

209



const string fn = "hoa.inp";
const string gn = "hoa.out";
static int k = 0; // so hoa
static int n = 0; // so lo
// v[i,j] = do tham mi khi cam
// hoa i vao lo j
static int[,] v;
static void Main()
{
Run();
Console.WriteLine("\n Fini");
Console.ReadLine();
} // Main
static void Run()
{
Doc(); Show();
DayLo Lo = new DayLo(n + 2);
int Vmax = XuLi(Lo);
Ghi(Vmax, Lo); KiemTra();
}
// Ghi file
static void Ghi(int Vmax, DayLo d)
{
StreamWriter g = File.CreateText(gn);
g.WriteLine(Vmax);
for (int i = 1; i <= n; ++i)
if (d.Bit(i) > 0) g.Write(i + " ");
g.Close();
}
// Doc lai file gn de kiem tra
static void KiemTra() t vit
// Dynamic Programming
// T(i,j) max tham mi voi i bo hoa va j lo
// T(i,j) = max {T(i-1,j-1)+v[i,j],T(i,j-1)}
// T(0,0) = T(i,0)= T(0,j) = 0
// Tinh theo cot, duoi len
static int XuLi(DayLo d)
{
if (k > n) return 0;
int[] t = new int[k + 2];
DayLo[] Lo = new DayLo[k + 2];
for (int i = 0; i <= k + 1; ++i)
Lo[i] = new DayLo(n + 2);
Array.Clear(t,0,t.Length);
// xet k hoa va k lo
for (int j = 1; j <= k; ++j) // lo
{ // so hoa i <= so lo j
for (int i = j; i > 0; --i) // hoa
if (t[i - 1] + v[i, j] > t[i])
{
t[i] = t[i - 1] + v[i, j];
Lo[i - 1].CopyTo(Lo[i]);
Lo[i].BatBit(j);
Sng to trong Thut ton v Lp trnh Tp I

210



}
}
// xet cac lo con lai
for (int j = k + 1; j <= n; ++j)
{
for (int i = k; i > 0; --i)
if (t[i - 1] + v[i, j] > t[i])
{
t[i] = t[i - 1] + v[i, j];
Lo[i - 1].CopyTo(Lo[i]);
Lo[i].BatBit(j);
}
}
Lo[k].CopyTo(d);
return t[k];
}
static void Doc()
{
int[] a = Array.ConvertAll((File.
ReadAllText(fn)).Split(
new char[] {'\0','\n','\t','\r',' '},
StringSplitOptions.RemoveEmptyEntries),
new Converter<String, int>(int.Parse));
k = a[0]; // so hoa
n = a[1]; // so lo
v = new int[k + 2, n + 2];
int i = 2;
for (int d = 1; d <= k; ++d)
for (int c = 1; c <= n; ++c)
v[d, c] = a[i++];
// dien 0 vao cac vi tri con lai
for (int j = 0; j <= n; ++j)
v[0, j] = v[k + 1, j] = 0;
}
// Hien thi du lieu
static void Show() t vit
} // CamHoa
// The hien 1 day lo
class DayLo
{
public const int bitnum = 32;
// so bit cho 1 bien int = 32 = 2^5
public int Size;
public uint[] Data;
public DayLo(int n) // day 0/1 gom n lo hoa
{
Size = (n + bitnum - 1) / bitnum;
Data = new uint[Size];
for (int i = 0; i < Size; ++i)
Data[i] = (uint)0;
}
// Gan tri 1 cho bit i trong day lo
// i >> 5 = i / 2^5 = i / 32
Sng to trong Thut ton v Lp trnh Tp I

211



public void BatBit(int i)
{
Data[i >> 5] |= ((uint)1) <<
(i & (bitnum-1));
}
// Gan tri 0 cho bit i trong day lo
public void TatBit(int i)
{
Data[i>>5] &= ~(((uint)1)<<(i&(bitnum-1)));
}
// Lay tri cua bit i trong day lo
public int Bit(int i)
{
return (int)((Data[i>>5]>>
(i&(bitnum-1)))&((uint)1));
}
// CopyTo DayLo this sang DayLo y
public void CopyTo(DayLo y)
{
int len = (Size <= y.Size) ? Size :
y.Size;
for (int i = 0; i < len; ++i) y.Data[i]
= Data[i];
}
} // DayLo
} // SangTao1
Bi ton sau y l mt cch pht biu khc ca bi ton cm hoa:
Bi ton
Cu lc b - Hc sinh gii Tin hc, H Ni, nm 2000
Cn b tr k nhm hc sinh vo k trong s n phng hc chuyn sao cho
nhm c s hiu nh c xp vo phng c s hiu nh hn phng cha nhm c
s hiu ln. Vi mi phng c nhn hc sinh, cc gh tha phi c chuyn ra
ht, nu thiu gh th phi ly t kho vo cho mi hc sinh mt gh. Bit s hc
sinh trong mi nhm v s gh trong mi phng. Hy chn phng n b tr sao
cho tng s ln chuyn gh ra v chuyn gh vo l t nht.
Bi 7.4. Tm cc ng ngn nht
Cho mt th c hng gm n nh m s t 1..n vi cc cung (u, v) c
hng i t nh u n nh v v c chiu di th hin ng i ni t nh u
n nh v. Vit chng trnh tm mi ng i ngn nht t mt nh s cho
trc ti cc nh cn li ca th.
D liu vo c ghi trong mt tp vn bn tn DIJ.INP c cu trc nh sau:
- Dng u ghi hai s t nhin n v s cch nhau bi du cch, trong n l s
lng nh ca th, s l s hiu ca nh xut pht.
- T dng th hai ghi ln lt di ng i t nh i n cc nh 1, 2,..., n;
i = 1..n. Gi tr 0 cho bit khng c cung ni hai nh tng ng. Vi mi nh
i = 1..n, cung (i, i) c xem l khng tn ti v ghi chiu di l 0. Cc s cng
dng cch nhau qua du cch. Dng d liu cho nh vy c gi l ma trn k
ca th.
Sng to trong Thut ton v Lp trnh Tp I

212



Th d sau y cho bit th c by nh, cn tm cc ng i ngn nht t nh 2 ti
cc nh cn li ca th. Cung (2, 1) c chiu di 4,...

DIJ.INP
7 2
0 0 0 0 0 0 0
4 0 1 0 0 0 5
0 0 0 0 0 0 1
0 0 0 0 0 2 0
0 0 0 3 0 0 0
1 0 0 0 0 0 5
0 0 0 1 0 0 0

D liu ra c ghi trong tp vn bn DIJ.OUT gm n dng. Thng tin v mi
ng i ngn nht t nh s n cc nh cn li c ghi trn 1 dng. S u tin ca
dng l chiu di ng i. Nu khng tn ti ng i th ghi gi tr 0. Tip n, trong
trng hp c ng i t nh s n nh i th ghi dy nh xut hin ln lt trn
ng i, nh u tin, d nhin l s, nh cui cng l i. ng i t nh i ti chnh
nh c coi l khng tn ti, i = 1..n. Th d trn cho ta kt qu
- ng ngn nht t nh 2 n nh 1 c chiu di 4, cch
i: 2 1.
- ng ngn nht t nh 2 n nh 2: khng c (thc ra,
theo l thng l c ng chiu di 0).
- ng ngn nht t nh 2 n nh 3 c chiu di 1, cch
i: 2 3.
- ng ngn nht t nh 2 n nh 4 c chiu di 3, cch
i: 2 3 7 4.
- ng ngn nht t nh 2 n nh 5: khng c.
- ng ngn nht t nh 2 n nh 6 c chiu di 5, cch
i: 23746.
- ng ngn nht t nh 2 n nh 7 c chiu di 2, cch i: 237.
Bi gii
Thut gii quy hoch ng c trnh by di y mang tn Dijkstra, mt nh tin
hc li lc ngi H Lan. Bn cht ca thut ton l sa nh, chnh xc ra l sa trng
s ca mi nh.
Theo s gii cc bi ton quy hoch ng trc ht ta xy dng h thc cho bi
ton.
Gi p(i) l di ng ngn nht t nh s n nh i, 1 s i s n. Ta thy, hm p(i)
phi tho cc tnh cht sau:
a) p(s) = 0: ng ngn nht t nh xut pht s n chnh nh c chiu di 0.
b) Vi i = s, mun n c nh i ta phi n c mt trong cc nh st trc
nh i. Nu j l mt nh st trc nh i, theo iu kin ca u bi ta phi c
a[j,i ] > 0
trong a[j, i] chnh l chiu di cung (j i).
Trong s cc nh j st trc nh i ta cn chn nh no?
DIJ.OUT
4 2 1
0
1 2 3
3 2 3 7 4
0
5 2 3 7 4 6
2 2 3 7
2 1
6
7 3
4
5
1
5
1
3
2
1
5 1
4
Sng to trong Thut ton v Lp trnh Tp I

213



K hiu path(x, y) l ng i ngn nht qua cc nh, xut pht t nh t x v kt
thc ti nh y = x. Khi ng t s n i s c chia lm hai on, ng t s n j
v cung (j i):
path(s,i) = path(s,j)+ path(j,i)
trong path(j, i) ch gm mt cung:
path(j,i) = (j i)
Do p(i) v p(j) phi l ngn nht, tc l phi t cc tr min, ta suy ra iu kin
chn nh j st trc nh i l tng chiu di ng t s n j v chiu di cung (j i)
l ngn nht. Ta thu c h thc sau:
p(i) = min {p(j)+a[j,i ] | a[j,i ] > 0, j = 1..n }
rng iu kin a[j, i] > 0 cho bit j l nh st trc nh i.
iu ti tnh l Dijkstra cung cp thut ton tnh ng thi mi ng i ngn nht
t nh s n cc nh cn li ca th. Thut ton nh sau.
Thut ton thc hin n ln lp, mi ln lp ta chn v x l 1 nh ca th. Ti
ln lp th k ta kho st phn ca th gm k nh vi cc cung lin quan n k nh
c chn trong phn th . Ta gi phn ny l th con thu c ti bc x l
th k ca th ban u v k hiu l G(k). Vi th ny ta hon tt bi gii tm mi
ng i ngn nht t nh xut pht s n mi nh cn li ca G(k). Chiu di thu
c ta gn cho mi nh i nh mt trng s p[i]. Ngoi ra, chun b cho bc tip
theo ta nh gi li trng s cho mi nh k sau ca cc nh trong G(k).
Khi tr: Gn trng s p[i] = cho mi nh, tr nh xut pht s, gn tr p[s] = 0.
ngha ca thao tc ny l khi mi ng nh xut pht s ca th con G(0), ta
coi nh cha thm mnh no ca th nn ta cha c thng tin v ng i t s n
cc nh cn li ca th ban u. Ni cch khc ta coi nh cha c ng i t s n
cc nh khc s v do , di ng i t s n cc nh l .
Gi tr c chn trong chng trnh l:
MAXWORD = 65535.
Ti bc lp th k ta thc hin cc thao tc sau:
- Trong s cc nh cha x l, tm nh i c trng s min.
- Vi mi nh j cha x l v k sau vi nh i, ta chnh li trng s p[j] ca
nh theo tiu chun sau:
Nu p[i] + a[i, j] < p[j] th gn cho p[j] gi tr mi:
p[j]=p[i]+a[i,j]
ngha ca thao tc ny l: nu di ng i path(s, j) trong th con G(k - 1)
khng qua nh i m ln hn di ng i mi path(s, j) c qua nh i th cp nht
li theo ng mi .
- Sau khi cp nht ta cn lu li vt cp nht bng lnh gn before[i] = j vi
ngha l, ng ngn nht t nh s ti nh j cn i qua nh i.
- nh du nh i l x l.
Nh vy, ti mi bc lp ta ch x l ng mt nh i c trng s min v nh du
duy nht nh .
(*----------------------------
Thuat toan Dijkstra
------------------------------*)
procedure Dijkstra;
var i,k,j: byte;
begin
Init;
Sng to trong Thut ton v Lp trnh Tp I

214



for k := 1 to n do
begin
i := Min; { tim dinh i co trong so p[i] ->
min }
d[i] := 1; {danh dau dinh i la da xu li }
for j := 1 to n do
if d[j] = 0 then {dinh chua tham }
if a[i,j] > 0 then {co duong di i -> j }
if p[i] + a[i,j] < p[j] then
begin {sua dinh }
p[j] := p[i] + a[i,j];
before[j] := i;
end;
end;
end;
Thut ton cha hai vng for lng nhau do c phc tp l n
2
.
Sau khi hon thnh thut ton Dijkstra ta cn gi th tc Ket (kt) ghi li kt
qu theo yu cu ca u bi nh sau.
Vi mi nh i = 1..n ta cn ghi vo tp output chiu di ng i t s n i bao
gm gi tr p[i] v cc nh nm trn ng .
Ch rng nu p[i] nhn gi tr khi u tc l MAXWORD = 65535 th tc l
khng c ng i t s n i.
(*-----------------------------------------
Ket thuc thuat toan:ghi ket qua vao tep g
------------------------------------------*)
procedure Ket;
var i: byte;
begin
assign(g,gn); rewrite(g);
for i := 1 to n do
if (i=s) or (p[i] = MAXWORD) then
writeln(g,0)
else
begin
write(g,p[i],bl);
path(i);
writeln(g);
end;
close(g);
end;
V ngha, mng before cha cc con tr ngc t mi nh i n nh st trc
nh i trn ng i ngn nht, do ta phi ln ngc bng th tc quy path(i)
ghi vo tp g vt ca ng i theo trt t t s n i.
(*-------------------------------------
Giai trinh duong ngan nhat tu s den i.
Ghi vao file g
--------------------------------------*)
procedure path(i: byte);
begin
if i=0 then exit;
Sng to trong Thut ton v Lp trnh Tp I

215



path(before[i]);
write(g,i,bl);
end;
(* Pascal *)
(*----------------------------------------------
DIJ.PAS Tim cac duong ngan nhat tu mot dinh
toi cac dinh con lai trong do thi co huong
(thuat giai Dijkstra)
----------------------------------------------*)
{$B-}
uses crt;
const
MN = 100; {gioi han so dinh }
MAXWORD = 65535; {Gia tri duong vo cung }
fn = 'DIJ.INP';
gn = 'DIJ.OUT';
bl = #32; {dau cach }
nl = #13#10;{xuong dau dong moi }
type
mb1 = array[0..MN] of byte;
mb2 = array[0..MN] of mb1;
mw1 = array[0..MN] of word;
var
a: mb2; {ma tran ke}
before: mb1; {before[i] dinh sat truoc dinh i}
p: mw1; {p[i] trong so dinh i}
d: mb1; {d[i]=0: dinh i chua xu ly
d[i]=1: dinh i da xu ly}
n: byte; {so luong dinh}
s: byte; {dinh xuat phat}
f,g: text;
(*---------------------------------
Doc du lieu vao ma tran ke a
-----------------------------------*)
procedure Doc; t vit
(*----------------------------------------
Hien thi du lieu de kiem tra thu tuc doc
-----------------------------------------*)
procedure Xem; t vit
(*-------------------------------------------
Khoi tri
- trong so cac dinh: vo cung
- trong so dinh xuat phat s, p[s] = 0
- cac dinh sat truoc: 0
--------------------------------------------*)
procedure init;
var i: byte;
begin
for i := 0 to n do
begin
d[i] := 0;
Sng to trong Thut ton v Lp trnh Tp I

216



p[i] := MAXWORD;
before[i] := 0;
end;
p[s] := 0;
end;
(*---------------------------------------
Giai trinh duong ngan nhat tu s den i.
Ghi vao tep g
----------------------------------------*)
procedure path(i: byte); t vit
(*--------- ----------------------
Ket thuc thuat toan:
ghi ket qua vao file g
---------------------------------*)
procedure Ket; t vit
(*-----------------------------------
Trong so cac dinh chua xu ly,
chon dinh trong so min
-------------------------------------*)
function Min: byte;
var m, i: byte;
begin
m := 0;
for i := 1 to n do
if d[i]= 0 then {dinh i chua xu li }
if p[i] <= p[m] then m := i;
Min := m;
end;
(*----------------------------
Thuat toan Dijkstra
------------------------------*)
procedure Dijkstra; t vit
BEGIN
Doc; Xem; Dijkstra; ket;
END.
Ta minh ho tin trnh hot ng ca thut ton Dijkstra qua
th d cho.
Sau khi c d liu t tp f=DIJ.INP ta c n = 7, s = 2.
th c 7 nh, nh xut pht l 2. Ma trn k a thu c
nh sau:

Khi tr
nh d p befor
e
1 0 65535 0
2 0 0 0
3 0 65535 0
4 0 65535 0
5 0 65535 0
a
0 0 0 0 0 0 0
4 0 1 0 0 0 5
0 0 0 0 0 0 1
0 0 0 0 0 2 0
0 0 0 3 0 0 0
1 0 0 0 0 0 5
0 0 0 1 0 0 0
Sng to trong Thut ton v Lp trnh Tp I

217



6 0 65535 0
7 0 65535 0
Bc lp k = 1
i = min = O vi p[O] = 0.
Cc nh cha x l v k vi nh O s c sa trng s l 1, 3 v 7 (c du -).
V p[O] + a[O, 1] = 0 + 4 = 4 < p[1] = 65535 nn p[1] c sa thnh 4 v
before[1] c sa thnh O.
V p[O] + a[O, 3] = 0 + 1 = 1 < p[3] = 65535 nn p[3] c sa thnh 1 v
before[3] c sa thnh O.
V p[O] + a[O, 7] = 0 + 4 = 5 < p[7] = 65535 nn p[7] c sa thnh 5 v
before[7] c sa thnh O.
nh d p before
1- 0 65535/4 0/2
O 0/1 0 0
3- 0 65535/1 0/2
4 0 65535 0
5 0 65535 0
6 0 65535 0
7- 0 65535/5 0/2
Bc lp k = 2
i = min = O vi p[O] = 1.
nh cha x l v k vi nh O s c sa trng s l nh 7.
V p[O] + a[O, 7] = 1 + 1 = 2 < p[7] = 5 nn p[7] c sa thnh 2 v
before[7] c sa thnh O.
nh d p before
1 0 65535/4 0/2
C 0/1 0 0
O 0/1 65535/1 0/2
4 0 65535 0
5 0 65535 0
6 0 65535 0
7- 0 65535/5/2 0/2/3
Bc lp k = 3
i = min = 7 vi p[O] = 1
nh cha x l v k vi nh 7 s c sa trng s l nh 4.
V p[O] + a[O, 4] = 2 + 1 = 3 < p[4] = 65535 nn p[4] c sa thnh 3 v
before[4] c sa thnh O.
nh d p before
1 0 65535/4 0/2
C 0/1 0 0
C 0/1 65535/1 0/2
4- 0 65535/3 0/7
5 0 65535 0
6 0 65535 0
O 0/1 65535/5/2 0/2/3
Bc lp k = 4
Sng to trong Thut ton v Lp trnh Tp I

218



i = min = 4 vi p[O] = 3.
nh cha x l v k vi nh O s c sa trng s l nh 6.
V p[O] + a[O, 6] = 3 + 2 = 5 < p[6] = 65535 nn p[6] c sa thnh 5 v
before[6] c sa thnh O.
nh d p before
1 0 65535/4 0/2
C 0/1 0 0
C 0/1 65535/1 0/2
O 0/1 65535/3 0/7
5 0 65535 0
6- 0 65535/5 0/4
C 0/1 65535/5/2 0/2/3
Bc lp k = 5
i = min = O vi p[O] = 4.
Khng c nh cha x l no k vi nh O.
nh d p before
O 0/1 65535/4 0/2
C 0/1 0 0
C 0/1 65535/1 0/2
0/1 65535/3 0/7
5 0 65535 0
6 0 65535/5 0/4
C 0/1 65535/5/2 0/2/3
Bc lp k = 6
i = min = O vi p[O] = 5.
Khng c nh cha x l no k vi nh O. Ch rng nh 7 k vi nh O
nhng nh 7 ny x l ri.
nh d p before
0/1 65535/4 0/2
C 0/1 0 0
C 0/1 65535/1 0/2
0/1 65535/3 0/7
5 0 65535 0
O 0/1 65535/5 0/4
C 0/1 65535/5/2 0/2/3
Thut ton dng.
Lu rng nh xut pht cho bi ton ny l s = 2. Ta minh ho gii trnh kt qu
cho ba th d sau.

Sng to trong Thut ton v Lp trnh Tp I

219



ng i ngn nht t nh s = 2 n nh t = 4:
V p[4] = 3 nn di ng i l 3.
gii trnh vt ca ng i t 2 n 4 ta da
vo mng before[1..7] nh sau:
V before[4] = 7, tc l trc khi n nh 4 phi
qua nh 7 nn ta c
7 4
V before[7] = 3, tc l trc khi n nh 7 phi
qua nh 3 nn ta c
3 7 4
V before[3] = 2, tc l trc khi n nh 3 phi qua nh 2 nn ta c
2 3 7 4
Kt qu ny c ghi dng th t ca tp DIJ.OUT nh sau:
3 2 3 7 4
trong s u tin 3 cho bit chiu di ng i, dy s cn li gii trnh vt ca
ng i t nh 2 n nh 4.
ng i ngn nht t nh s = 2 n nh t = 5:
V p[5] = 32767 ng vi gi tr dng v cng khi tr lc u nn khng c
ng i t nh 2 n nh 5.
Ta ghi kt qu 0 ti dng 5 ca tp DIJ.OUT.
ng i ngn nht t nh s = 2 n nh t = 2:
V s = t nn ta coi nh khng c ng i t nh 2 n nh 2.
Ta ghi kt qu 0 ti dng 5 ca tp DIJ.OUT.
Cc dng khc ca bi ton Dijkstra
Lu rng ma trn k c th cha cc gi tr thc, tuy nhin cn gi thit rng mi
gi tr trong ma trn k phi l cc s khng m. Vi cc s m bi ton s phc tp
hn.
P1. Nu th cho l v hng ta gii nh trn, ch lu n tnh i xng khi
c d liu vo ma trn k a.
P2. Nu bi ch yu cu tm mt ng i t nh s n nh t ta thc hin cc
bc sau:
1. c d liu.
2. Gi thut ton Dijkstra.
3. Ghi kt qu p[t] v gii trnh mt ng theo thut ton path(t).
// C#
using System;
using System.IO;
using System.Collections;
namespace SangTaoT1
{
/*------------------------------------
* Thuat toan Dijkstra
* Tim moi duong ngan nhat tu mot dinh
* den moi dinh con lai
* -----------------------------------*/
class Dijkstra
nh d p before
1 1 4 2
2 1 0 0
3 1 1 2
4 1 3 7
5 0 65535 0
6 1 5 4
7 1 2 3
Sng to trong Thut ton v Lp trnh Tp I

220



{
const string fn = "Dij.inp";
const string gn = "Dij.out";
static int n = 0; // so dinh
static int s = 0; // dinh xuat phat
// c[i,j] ma tran ke cho biet
// do dai cung (i,j)
static int[,] c;
static int[] d; // danh dau dinh
static int[] t; // tro truoc
static int[] p; // trong so dinh
static void Main()
{
Run();
Console.ReadLine();
} // Main
static void Run()
{
Doc(); Show(); Dij();
Ghi(); Test();
Console.WriteLine("\n Fini");
Console.ReadLine();
}
// Kiem tra lai tep output
static void Test() t vit
static void Ghi()
{
StreamWriter g = File.CreateText(gn);
for (int i = 1; i <= n; ++i)
if (i == s || p[i] == int.MaxValue)
g.WriteLine(0);
else
{
g.Write(p[i] + " ");
int u = InvPath(i);
for (int j = u; j > 0; --j)
g.Write(d[j] + " ");
g.WriteLine();
}
g.Close();
}
// Lan nguoc duong di
// tu dinh v den dinh s
// ghi tam vao mang d
static int InvPath(int v)
{
int i = 0;
do
{
d[++i] = v;
v = t[v];
} while (v != 0);
return i;
Sng to trong Thut ton v Lp trnh Tp I

221



}
static void Dij()
{
for (int i = 0; i <= n; ++i)
{ //d: danh dau dinh, t: tro truoc
d[i] = t[i] = 0;
p[i] = int.MaxValue; // Trong so
}
p[s] = 0;// s: dinh xuat phat
for (int i = 1; i < n; ++i)
{
int u = Minp();// u: dinh trong so min
d[u] = 1; // danh dau dinh da xet
// sua lai nhan dinh
for (int v = 1; v <= n; ++v)
if (d[v] == 0) // dinh chua xet
if (c[u, v] > 0) // co cung(u,v)
if (p[u] + c[u, v] < p[v])
{ // sua lai nhan dinh v
p[v] = p[u] + c[u, v];
// chon cach di tu u -> v
t[v] = u;
}
}
}
// Tim trong so cac dinh chua
// xu li mot dinh j co p min
static int Minp()
{
int jmin = 0;
for (int i = 1; i <= n; ++i)
if (d[i] == 0) // dinh i chua xet
if (p[i] < p[jmin]) jmin = i;
return jmin;
}
static void Doc()
{
int[] a = Array.ConvertAll((File.
ReadAllText(fn)).Split(
new char[] {'\0','\n','\t','\r',' '},
StringSplitOptions.RemoveEmptyEntries),
new Converter<String, int>(int.Parse));
n = a[0]; // so dinh
s = a[1]; // dinh xuat phat
c = new int[n + 1, n + 1];
d = new int[n + 1];
t = new int[n + 1];
p = new int[n + 1];
int k = 2;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
c[i, j] = a[k++];
}
Sng to trong Thut ton v Lp trnh Tp I

222



// Hien thi du lieu
static void Show() t vit
// hien thi mang
static void Print(int[] a, int n) t vit
} // Dijkstra
} // SangTao1

Sng to trong Thut ton v Lp trnh Tp I

223



CHNG 8
SUY NGM



Chng ny gii thiu mt s bi ton thuc cc lp thut gii khc nhau bn
c t luyn tp.
Thng thng, nu ch bit mt phng php gii m gp bi ton "trng t", ngha l
bi ton vn dng chnh phng php bit th ta gn nh khng phi suy ngh g. Tuy
nhin, khi c trong tay mt s phng php th vic chn thut gii cho mi bi ton c
th s khng d dng cht no.
Luyn tp v suy ngm tm kim ng i trong cc tnh hung nh trn s
cung cp cho chng ta nhiu kinh nghim qu.
Bi 8.1. Lt nn
Ngi ta cn lt kn mt nn nh hnh vung cnh di n = 2
k
, (k l mt s t nhin
trong khong 1..6) khuyt mt phn t ti gc trn phi bng nhng vin gch mu
hnh thc th (ch L) to bi 3 vung n v nh trong hnh 2b. Hai vin gch k
cnh nhau d ch 1 n v di phi c mu khc nhau. Hy cho bit mt cch lt vi
s mu t nht.

Hnh 2
D liu vo: tp vn bn NEN.INP cha s t nhin n.
D liu ra: tp vn bn NEN.OUT. Dng u tin l hai s t nhin m biu th
s vin gch v c l s mu cn dng cho vic lt nn. Tip n l mt phng
n lt nn tm c, trong mi vin gch lt c to bi ba ch s ging
nhau th hin mu ca vin gch . Cc s trn mi dng cch nhau qua du
cch.


D B



A C


a) Nn nh b) Gch lt



Sng to trong Thut ton v Lp trnh Tp I

224



Th d, vi n = 8 ta c mt cch lt nn nh
sau:
Li gii sau y ca bn L Hong Hi, lp
10 chuyn Tin, i hc Khoa hc T nhin, i
hc Quc gia H Ni (nm 2002).
tnh s vin gch ta ly ba phn t din
tch hnh vung ph nn nh chia cho 3 l din
tch 1 vin gch thc th:
sogach:=((3*n*n) div 4) div 3;



V s mu, vi n = 2 th ch cn 1 vin gch mu 1.
Vi mi n > 2 ta s trnh by mt thut ton cn ti a ba
mu.
u tin ta gi th tc Init khi tr vi
hnh vung cnh v = 2 nm gc di tri ca
nn nh c biu din di dng mt mng hai
chiu a: ba trong hnh vung 2 2 s c
in gi tr 1, nm gc trn phi c in
gi tr 2 (phn t m, hnh 6). Gi hnh c
khi tr l A. Mi bc tip theo ta thc hin ba
thao tc bin hnh sau y:
- Tnh tin A i ln theo ng cho thu c hnh B (xem th tc
DichCheo).
- Lt A sang phi (tc l ly i xng gng qua trc tung) thu
c hnh C (xem th tc LatPhai).
- Lt A ln trn (tc l ly i xng gng qua trc honh) thu
c hnh D (xem th tc LatLen).
Ch rng khi lt ta cn thc hin thm php hon i tr 1 v 3 cho nhau.
Mi ln lp nh vy ta s thu c hnh vung c cnh tng gp i hnh trc.
Khi v = n ta gi th tc Fini ghi ba mnh D, A v C vo tp kt qu.
3 3 1 1
3 2 2 1
1 2 3 3
1 1 3 2
3 3 1 2 1 1 1 1 3 3 1 2 2 3 1 1
3 2 1 1 3 2 1 1 3 3 2 1
1 2 1 1 1 1 1 1 1 2 2 3 1 2 2 3 1 2 2 3
1 1 1 1 3 3 1 1 3 3 1 1 3 3
NEN.INP NEN.OUT
8 16 3
3 3 1 1
3 2 2 1
1 2 3 3
1 1 3 2
3 3 1 2 2 3 1 1
3 2 1 1 3 3 2 1
1 2 2 3 1 2 2 3
1 1 3 3 1 1 3 3
3 3 1 1
3 2 2 1
1 2 3 3
1 1 3 2
3 3 1 2 2 3 1 1
3 2 1 1 3 3 2 1
1 2 2 3 1 2 2 3
1 1 3 3 1 1 3 3
Hnh 3. Nn nh vi n = 8
Sng to trong Thut ton v Lp trnh Tp I

225



Hnh 6
Ta biu din nn nh hnh vung qua mt mng hai chiu a vi cc dng c m s 1..n
t trn xung v cc ct c m s t 1..n t tri qua phi. Khi vin gch gc di tri s
c to [n, 1]. Sau khi c d liu nhn gi tr n, ta gn tr ban u cho 4 vin gch gc
di tri nh sau:
a[n-1,1] := 1; a[n-1,2] := 2;
a[n,1] := 1; a[n,2] := 1;
K hiu A l hnh vung cnh di v n v nm ti gc di tri ca nn nh, tc l
phn mng v[n v + 1..n, 1..v] trong hnh 7. Khi cc th tc di chuyn hnh vung A
s c m t nh sau.




A
n v + 1 3 3 1 2
... 3 2 1 1
n 1 1 2 2 3
n 1 1 3 3
1 2 ... v
Hnh 7. Hnh vung a cnh v c chn
bin hnh



B 3 3 1 2
3 2 1 1
1 2 2 3
A 1 1 3 3
n v +
1
3 3 1 2
... 3 2 1 1
n 1 1 2 2 3
n 1 1 3 3
1 2 ... v
Hnh 8. Dch cho A thu c B
dch cho hnh vung A ta copy dn tng phn t trong cc dng, t dng n v
+ 1 n dng cui cng, dng th n n v tr mi (h. 8).

Sng to trong Thut ton v Lp trnh Tp I

226



(*---------------------------------------------
Dich hinh vuong A canh v,
a[n-v+1..n,1..v]o goc duoi trai di len theo
duong cheo chinh cua nen nha de nhan duoc manh B.
--------------------------------------------*)
procedure DichCheo(v: word);
var i,j:word;
begin
for i := n-v+1 to n do
for j := 1 to v do
a[i-v,j+v] := a[i,j];
end;




A C
n v +
1
3 3 1 2 2 3 1 1
... 3 2 1 1 3 3 2 1
n 1 1 2 2 3 1 2 2 3
n 1 1 3 3 1 1 3 3
1 2 ... v
Hnh 9. Lt A qua phi thu c C














lt phi hnh vung A ta cng chuyn dn tng phn t trong cc dng, t dng
n v + 1 n dng cui cng, dng th n n v tr mi. Tuy nhin cn lu thay i tr
mu t 1 sang mu 3 v ngc li. Thao tc ny c thc hin qua php gn 4 c,
trong c l mu ca gc. Nu c = 2 th 4 2 = 2, tc l mu 2 khng thay i (h. 9).
3 3 1 1 D
3 2 2 1
1 2 3 3
1 1 3 2
n v + 1 3 3 1 2 A
... 3 2 1 1
n 1 1 2 2 3
n 1 1 3 3
1 2 ... v
Hnh 10. Lt A ln trn thu c D

Sng to trong Thut ton v Lp trnh Tp I

227




(*--------------------------------------------
Lat hinh vuong canh v, a[n-v+1..n,1..v]
o goc duoi trai sang phai, doi mau gach
de nhan duoc manh C.
----------------------------------------------*)
procedure LatPhai(v: word);
var i,j,v2:word;
begin
v2 := 2*v;
for i := n-v+1 to n do
for j := 1 to v do
a[i,v2-j+1] := 4-a[i,j];
end;
lt hnh vung A ln trn ta cng lm tng t nh lt phi (h. 10).
(*------------------------------------------
Lat hinh vuong canh v, a[n-v+1..n,1..v]
o goc duoi len tren, doi mau gach
de nhan duoc manh D.
--------------------------------------------*)
procedure LatLen(v: word);
var i,j,v2:word;
begin
v2 := n-2*v+1;
for i := 0 to v-1 do
for j := 1 to v do
a[v2+i,j] := 4-a[n-i,j];
end;
Bnh lun
Thut gii s dng hai php bin hnh c bn trong chng trnh ph thng l php
di hnh (tnh tin) v i xng qua trc. Vic hon i tr 1 v 3 cho nhau l mt
tng thng minh. Mi trong bng c in ng mt ln do phc tp tnh
ton ca thut ton l n
2
, trong khi cc bi gii khc u phi s dng cc php d tm
xc nh mu t v gi quy nn thng tn km v min nh v thi gian hn
nhiu ln.
(* Pascal *)
(****************************
LATNEN lat nen nha
hinh vuong khuyet goc bang
cac vien gach mau hinh L
*****************************)
const
fn = 'NEN.INP'; {input file}
gn = 'NEN.OUT'; {output file}
bl = #32; {dau cach}
mn = 65; {kich thuoc toi da cua n}
var {n chieu dai canh nen nha}
f,g: text;
a: array[0..mn,0..mn] of byte; {nen nha}
Sng to trong Thut ton v Lp trnh Tp I

228



{a[i] mau vien gach lat}
n,n2: word; {n2 = n/2}
sogach: word;
{-----------------------------
Doc du lieu va khoi tri
----------------------------}
procedure Init;
begin
{Doc du lieu}
assign(f,fn); reset(f);
readln(f,n); close(f);
n2 := n div 2;
sogach := ((3*n*n) div 4) div 3;
{Dat tam 4 o vuong (2 X 2) tai goc duoi trai}
a[n-1,1] := 1; a[n-1,2] := 2;
a[n,1] := 1; a[n,2] := 1;
end;
{-------------------------------
Ket thuc, ghi tep
-------------------------------}
procedure Fini(somau:word);
var i,j: word;
begin
assign(g,gn); rewrite(g);
writeln(g,sogach,bl,somau);
{ghi goc tren trai D}
for i := 1 to n2 do
begin
for j := 1 to n2 do
write(g,a[i,j],bl);
writeln(g);
end;
{ghi nua duoi A va C}
for i := n2+1 to n do
begin
for j := 1 to n do
write(g,a[i,j],bl);
writeln(g);
end;
close(g);
end;
(*---------------------------------------------
Dich hinh vuong A canh v, a[n-v+1..n,1..v]
o goc duoi trai di len theo duong cheo
chinh cua nen nha de nhan duoc manh B.
-----------------------------------------------*)
procedure DichCheo(v: word); t vit
(*--------------------------------------------
Lat hinh vuong canh v, a[n-v+1..n,1..v]
o goc duoi trai sang phai, doi mau gach
de nhan duoc manh C.
-----------------------------------------------*)
procedure LatPhai(v: word); t vit
Sng to trong Thut ton v Lp trnh Tp I

229



(*--------------------------------------------
Lat hinh vuong canh v, a[n-v+1..n,1..v]
o goc duoi len tren, doi mau gach
de nhan duoc manh D.
-----------------------------------------------*)
procedure LatLen(v: word); t vit
procedure Run;
var v:word;
begin
Init; {khoi tri voi n = 2}
if n = 2 then
begin
Fini(1); exit;
end;
v := 1;
repeat
v := v*2;
if v < n2 then DichCheo(v);
LatPhai(v);
LatLen(v);
until v = n2;
Fini(3);
end;
BEGIN
Run;
END.
// C#
using System;
using System.IO;
namespace SangTao1
{
/*-----------------
* Lat nen
* ----------------*/
class LatNen
{
const string fn = "Nen.inp";
const string gn = "Nen.out";
static int n = 0; // canh nen nha
static int[,] c; // nen nha
static void Main()
{
Run();
Console.ReadLine();
} // Main
static void Run()
{
Doc(); Lat(); Ghi();
Test();
Console.WriteLine("\n Fini");
Console.ReadLine();
}
Sng to trong Thut ton v Lp trnh Tp I

230



// Kiem tra ket qua
static void Test() t vit
static void Ghi()
{
StreamWriter g = File.CreateText(gn);
int n2 = n / 2;
const string BL = " ";
if (n == 2)
g.WriteLine(1 + BL + 1);
else g.WriteLine(((n*n)/4)+BL+3);
for (int i = 0; i < n2; ++i)
{
for (int j = 0; j < n2; ++j)
g.Write(c[i, j] + BL);
g.WriteLine();
}
for (int i = n2; i < n; ++i)
{
for (int j = 0; j < n; ++j)
g.Write(c[i, j] + BL);
g.WriteLine();
}
g.Close();
}
static void Lat()
{
c = new int[n, n];
// Khoi tri
for (int i = n - 2; i < n; ++i)
for (int j = 0; j < 2; ++j)
c[i, j] = 1;
c[n - 2, 1] = 2;
int k = 2;
while (k < n)
{
Len(k);
Phai(k);
DichCheo(k);
k *= 2;
}
}
// Lat ma tran kXk len tren
static void Len(int k)
{
for (int i = n - k; i < n; ++i)
for (int j = 0; j < k; ++j)
c[2*(n-k)-i-1,j] = 4-c[i,j];
}
// Lat ma tran kXk sang phai
static void Phai(int k)
{
for (int i = n - k; i < n; ++i)
for (int j = 0; j < k; ++j)
Sng to trong Thut ton v Lp trnh Tp I

231



c[i,2*k-j-1] = 4-c[i,j];
}
// dich ma tran kXk theo huong Dong-Bac
static void DichCheo(int k)
{
for (int i = n - k; i < n; ++i)
for (int j = 0; j < k; ++j)
c[i - k, j + k] = c[i, j];
}
static void Doc()
{
n = int.Parse(File.ReadAllText(fn).Trim());
Console.WriteLine("\n Da doc n = " + n);
}
} // LatLen
} // SangTao1

Bi 8.2. Ch s cui khc 0
thi Tin hc Quc gia Ireland, 1994.
Tm ch s cui cng khc 0 ca n! vi n trong khong 1..100.
Th d:
- n = 7, kt qu = 4.
- n = 15, kt qu = 8.
Bi gii
Thut gii ca bn Vit Hng (H Ty, 2002) cho php m rng gii hn ca n n hng
chc vn v nu bn mun, c th tip tc m rng n hng triu.
tng chnh ca Vit Hng nm cng thc: 2 5 = 10 (hai ln nm l mi).
Tht vy, ta bit:
n! = 1.2.3...n
Cc ch s cui cng bng 0 ca n giai tha c sinh ra khi v ch khi trong khai
trin ra tha s nguyn t ca tch trn c cha cc cp tha s 2 v 5. Vy th trc ht
ta m s lng cc tha s 2, k hiu l d2 v s lng cc tha s 5, k hiu l d5.
Th d, vi n = 15 ta c dng khai trin ra tha s nguyn t ca n giai tha nh
sau:
n! = 1.2.3.(2.2).5.(2.3).7.(2.2.2).9.(2.5).11. (2.2.3).13.(2.7).(3.5)
Do d2 = 11 v d5 = 3. Vy ta c ba cp 2.5 = 10 v s m di ra ca tha s 2
so vi tha s 5 s l d2 d5 = 11 3 = 8. Khi , kt qu s l:
ch s cui cng khc 0 ca 15! = ch s cui cng ca
k.2
d2-d5

Trong k l tch ca cc tha s cn li.
D thy vi mi n, ta lun c d2 > d5 v c hai s lin tip th c mt s chn (chia
ht cho 2), cn nm s lin tip mi c mt s chia ht cho 5.
Vic cn li l ly tch k ca cc s cn li. V tch ny khng bao gi tn cng
bng 0 cho nn ta ch cn gi li mt ch s cui cng bng cch ly mod 10.
tnh ch s tn cng ca 2
m
vi m = d2 d5 > 0 ta n tnh tun hon ca
n, c th l ta ch cn tnh ch s tn cng ca 2
(m mod 4)
vi cc trng hp:
m mod 4 = 0, 1, 2 v 3.
Sng to trong Thut ton v Lp trnh Tp I

232



Theo th d trn ta c m mod 4 = 8 mod 4 = 0, do ch s cui ca 2
m
l 6 ch khng
phi l 1 v m > 0. Ta tnh c (nhng cp 2 v 5 c gch di)
15! = 1.2.3.4.5.6.7.8.9.10.11.12.13.14.15 =
= 1.2.3.(2.2).5.(2.3).7.(2.2.2).9.(2.5).11. (2.2.3).13.(2.7).(3.5)
(3.3.7.9.11.3.13.7.3). 2
8
mod 10 =
= ((k mod 10) . (2
8
mod 10)) mod 10 = (3.6) mod 10 = 8.
Ch s cui cng khc 0 ca 15! l 8.
Lu rng (a.b) mod m=((a mod m).(b mod m)) mod m cho nn ta c th ly mod
cc bc trung gian vi s ln ty .
trnh vic trn s khi s dng cc bin dung lng nh nh kiu word thay v
dng longint chng ta c th tng thm mt php ton mod na. Chng hn, khi tch
lu kt qu, thay v vit
k := (k*c) mod 10;
ta nn vit
k := (k*(c mod 10)) mod 10;
trong k l s c mt ch s, c l s c th rt ln, lm tch (k*c) vt qu gii
hn cho php. Th d, nu khai bo kiu d liu l word th khi k = 8, c = 17999 ta c
k*c = 8*17999 = 143992 > 65535 (gii hn ca word), trong khi 8 v 17999 u nm
trong gii hn cho php.
Bnh lun
rng:
14! = 87178291200, c ch s cui cng khc 0 l 2
15! = 1307674368000, c ch s cui cng khc 0 l 8.
Nu tnh 15! m bn ch ly mt ch s cui khc 0 ca cc php tnh trung gian
th sau khi tnh ch s cui ca 14! bn s nhn c 2 v cui cng l:
(2*15) mod 10 = 30 mod 10 = 3.
Kt qu ny l sai v ch s cui khc 0 ca 15! l 8.
Chng trnh sau y cha th tc find tm ch s cui cng khc 0 ca n! vi n
trong khong 1..65535.
Ta thc hin mt ci tin nh nh sau. Thay v m s lng cc tha s 2 (d2) v
tha s 5 (d5) sau lm php tr d2 d5, ta m lun mt ln hiu s ny v ghi vo
bin m. C th l vi mi gi tr i = 2..n ta m s lng cc tha s 2 trc, sau tr
i s lng cc tha s 5.
(* Pascal *)
(*---------------------------------------
Tim chu so khac khong cuoi cung cua n!
----------------------------------------*)
uses crt;
function find(n: longint): longint;
var m: longint;
{m hieu so cac thua so 2 v thua so 5}
i,k,c: longint;
begin {k ket qua trung gian}
k := 1; m := 0;
find := k;
if (n <= 1) then exit;
Sng to trong Thut ton v Lp trnh Tp I

233



d := 0;
for i := 2 to n do
begin
c := i;
while c mod 2 = 0 do
begin
m := m+1; c := c div 2;
end;
while c mod 5 = 0 do
begin
m := m-1; c := c div 5;
end;
k := (k*(c mod 10)) mod 10;
end;
case (m mod 4) of
0: c := 6;
1: c := 2;
2: c := 4;
3: c := 8;
end;
find := (k*c) mod 10;
end;
procedure run;
var n: longint;
begin
writeln('--------------------');
repeat
write(' Nap N (Muon dung chuong trinh, bam 0 ):
');
read(n);
if n = 0 then halt;
writeln(' find(',n,') = ',find(n));
until false;
end;
BEGIN
run;
END.
K thut gn trc
Bn c th thay lnh Case trong vic tnh ch s tn cng ca 2
m
bng cc thao tc
sau:
1. Khai bo v gn trc tr cho mng LuyThua
const LuyThua: array[0..3] of word = (6,2,4,8);
ngha ca dng lnh trn: khai bo mt mng kiu word vi bn phn t c ch
s bin thin t 0..3 v gn trc tr cho mng ny l:
LuyThua[0] := = 6; {= 2
4
mod 10}
LuyThua[1] = 2; {= 2
1
mod 10}
LuyThua[2] = 4; {= 2
2
mod 10}
LuyThua[3] = 8; {= 2
3
mod 10}
Sng to trong Thut ton v Lp trnh Tp I

234



Ch rng, do i hi phi khai bo trc v gn ng thi nn Turbo Pascal 7.0
quy nh t khai bo ny sau t kho const. Tuy nhin LuyThua vn l bin mng
ch khng th l hng.
2. Khi cn tm ch s cui cng c ca 2
m
bn khi phi dng lnh case, ch
cn vit:
c := LuyThua[m mod 4];
Hm Find theo phng n mi s nh sau:
const LuyThua: array[0..3] of word = (6,2,4,8);
{-------------------------------------------}
Find Tm ch s cui cng khc 0 ca n!
Phuong an dung mang LuyThua gan truoc
--------------------------------------------}
function find(n: longint): longint;
var m: longint;
{m hieu so cac thua so 2 v thua so 5}
i,k,c: longint; {k ket qua trung gian}
begin
k := 1; m := 0;
find := k;
if (n <= 1) then exit;
d := 0;
for i := 2 to n do
begin
c := i;
while c mod 2 = 0 do
begin
m := m+1; c := c div 2;
end;
while c mod 5 = 0 do
begin
m := m-1; c := c div 5;
end;
k := (k*(c mod 10)) mod 10;
end;
find := (k*LuyThua[m mod 4]) mod 10;
end;
// C#
using System;
namespace Tap1
{
/*------------------------------
* Chu so cuoi khac 0 cua n!
* -----------------------------*/
class ChuSoCuoi
{
static void Main()
{
Test(200);
} // Main
static void Test(int n)
Sng to trong Thut ton v Lp trnh Tp I

235



{
for (int i = 1; i < n; ++i)
{
Console.Write("\n Chu so cuoi khac 0 cua " +
i + "! = " + Find(i)+". ");
Console.Write("Bam exit de thoat: ");
if (Console.ReadLine() == "exit") break;
}
}
static int Find(int n)
{
if (n < 2) return 1;
int m = 0;
long k = 1;
int c = 0;
int[] mu = { 6, 2, 4, 8};
for (int i = 2; i <= n; ++i)
{
c = i;
while (c % 2 == 0)
{
++m; c /= 2;
}
while (c % 5 == 0)
{
--m; c /= 5;
}
k = (k * (c % 10)) % 10;
}
return (int)((k * mu[m % 4]) % 10);
}
} // ChuSoCuoi
} // SangTao1
Bi tp lm thm
Bi T1. Cho bit N! tn cng vi bao nhiu ch s 0. Th d, 15! tn cng vi 3 ch s
0, v 15! = 1307674368000.
Gi Nu p l mt s nguyn t v p
K
l nhn t trong dng phn tch N! ra
tha s nguyn t th k c tnh bng tng ca cc thng nguyn trong
php chia lin tip ca N cho p.
Th d, vi N = 15, p = 2 v k hiu : l php chia nguyn, ta tnh c
15 : 2 = 7; 7 : 2 = 3; 3 : 2 = 1; 1 : 2 = 0. Do k = 7+3+1+0 = 11.
Vi N=15, p = 5 ta tnh c 15 : 5 = 3; 3 : 5 = 0. Do k = 3+0 = 3.
Nh vy 15! = 2
11
.5
3
.C.
Chng minh iu ny kh d, bn ch cn vit dy 1.2N thnh cc dng, mi
dng p tha s
Vy l trong tch 1N cha K
1
tha s p. Trong tch
1K
1
s cha K
1
: p tha s p.
Bi T2. Phn tch N! ra tha s nguyn t.
Th d, 15! = 2
11
.3
6
.5
3
.7
2
.11.13.
1 p
p+1 2p

k
1
p = N!
Sng to trong Thut ton v Lp trnh Tp I

236



Gi S dng kt qu Bi 1. Trc ht bn cn vit hm Mu(n,p) cho ra s m
cao nht ca s nguyn t p trong dng phn tch n! ra tha s nguyn t.
Th d, Mu(15,2) = 11; Mu(15,5) = 3.
Bi 8.3. Hnh ch nht ti i trong ma trn 0/1.
Cho mt ma trn biu din bng mt mng hai chiu kch thc N M v ch
cha cc k t 0 v 1. Tm hnh ch nht cha ton k t 1 v c din tch ln
nht (gi l hnh ch nht ti i).
D liu vo: Tp vn bn CNMAX.INP:
- Dng u tin: s t nhin M,
3 s M s 70
- Tip n l cc dng di bng nhau th hin mt xu gm M k t l cc
ch ci 0/1 vit lin nhau.
- S dng ca tp input c th ln ti 60 nghn.
D liu ra: tp vn bn CNMAX.OUT:
- Dng u tin: Din tch ca hnh ch nht ti i ABCD cha ton k t 1
tm c.
- Dng th hai: To dng v ct ca nh A.
- Dng th ba: To dng v ct ca nh C.
C C C C C
O 1 0 0 0 0 0 0 0 0
O 1 1 1 1 1 1 1 1 0
O 0 0 1 1 1 1 1 0 0
O 0 0 1 1 1 1 1 0 0
O 0 0 0 0 0 0 0 0 0
Hnh 4
Th d, vi ma trn 5 9 cha d liu nh hnh 4 th hnh ch nht ti i, tm gi
l ABCD, c din tch l 15 v c to im A l (dng 2, ct 3) v im C l (dng
4, ct 7) nh trong hnh 4.
CNMAX.INP CNMAX.OUT

9
100000000
111111110
001111100
001111100
000000000

15
2 3
4 7

Chng ta s xy dng mt thut ton gii bi ton tng qut hn nh sau:
Bi ton 8.3.1. Sn bay v tr
Ngi ta cn xc nh mt vng hnh ch nht ABCD c din tch ln nht v bng
phng trn hnh tinh Vega xy dng sn bay v tr. Bn c cung cp mt
mnh bn hnh tinh Vega, ni cn xc nh v tr xy dng mt sn bay. Mnh
bn c dng hnh ch nht gm nhiu dng im m s t 1 tr i, mi dng c
Sng to trong Thut ton v Lp trnh Tp I

237



ng M im m s t 1 n M. Mi im c t mt mu th hin cao ca
im . Yu cu: xc nh hnh ch nht ABCD cha nhiu im ng mu nht.
D liu vo: Tp vn bn CNMAX.INP.
- Dng u tin: s t nhin M, 3 s M s 70.
- Tip n l cc dng di bng nhau th hin mt xu gm M k t l cc
ch ci a..z vit lin nhau. Mi k t biu din cho mt mu th hin cao
ca im tng ng trn mnh bn hnh tinh Vega. Hai k t khc nhau
th hin hai cao khc nhau. Hai im cng cao c biu din vi
cng mt k t.
- S dng ca tp input c th ln ti 60 nghn.
Th d:
CNMAX.INP CNMAX.OUT

20
bcccddddeabcvvvvvvvb
bbbbbccccccccccbbbbb
vvvvvcccccccccccccbb
vvcccccccccccccbbbbb
pppppccccccccccabbbb
pppppcccccccccczzzzz
ssccccccccccccczzzzz
sssssccccccccccccczz
hhhhhcccccccccczzzzz
uuuuuuuuczzzzzzzzzzz

80
2 6
9 15

D liu ra: tp vn bn CNMAX.OUT:
- Dng u tin: Din tch ca hnh ch nht ti i ABCD tm c.
- Dng th hai: To dng v ct ca nh A ( Ty-Bc).
- Dng th ba: To dng v ct ca nh C ( ng-Nam).
Tnh tng qut ca bi ton 8.3.1 th hin im sau:
- Tp khng ch cha cc k t 0/1.
Bi gii
Do khng th c ton b d liu t tp CMAX.INP vo mt mng x l nn
chng ta s c mi ln mt dng vo bin kiu xu k t (string) y. V hnh ch nht
ABCD cn tm cha cng mt loi k t cho nn cc dng ca hnh s lin thng nhau.
pht hin tnh lin thng chng ta cn dng thm mt bin kiu xu k t x lu
dng c v x l bc trc. Tm li l ta cn x l ng thi hai dng: x l dng
trc v y l dng ang xt.
Nu xt cc ct trong hnh ch nht cn tm ta thy chng phi cha cng mt loi
k t. Ta dng mt mng h vi ngha phn t h[i] ca mng cho bit tnh t v tr th i
ca dng y tr ln c bao nhiu k t ging nhau (v ging vi k t y[i]). Ta gi h[i] l
cao ca ct i v mng h khi s c gi l cao ca dng ang xt.
Th d, mng tch lu cao ca dng th 5 trong th d cho s l:
h = (1,1,1,1,1,4,4,4,4,4,4,5,4,4,4,1,2,2,4,5)
A B


Sng to trong Thut ton v Lp trnh Tp I

238






C D
Bit cao, vi hai dng x v y chng ta d dng tnh c din tch ca mi hnh
ch nht ABCD cha phn t y[i] trn cnh DC. Tht vy, gi s ta ang xt k t th i
= 8 trn dng th 5 nh ni phn trn. Ta c h[8] = h[7] = h[6] = 4; h[9] = h[10] =
h[11] = 4; h[12] = 5; h[13] = h[14] = h[15] = 4; h[16] = 1,... Vy th, khi ta i t i v hai
pha, tri v phi, nu gp cc k t ging k t y[i] cn cao th khng nh hn h[i] ta
s thu c hnh ch nht ln nht cha k t y[i].
Vi dng th 5 l y ang xt, ta c:
x = 'vvcccccccccccccbbbbb'; {dng thu 4 }
y = 'pppppccccccccccabbbb'; {dng thu 5 }

dng 1 2 3 4 5 6 7 9 10 11 12 13 14 15 16 17 18 19 20
4 x v v c c c c c c c c c c c c c b b b b b
5 y p p p p p c c c c c c c c c c a b b b b
h 1 1 1 1 1 4 4 4 4 4 4 5 4 4 4 1 2 2 4 5

trong x cha d liu ca dng th 4, y cha d liu ca dng th 5 trong tp
CNMAX.INP.
T im i = 8 dch chuyn v bn tri ta thu c im c1 = 6; dch chuyn v bn
phi ta thu c im c2 = 15. iu kin dch chuyn l:
(y[c1] = y[i]) and (h[c1] > h[i]), nu qua tri v
(y[c2] = y[i]) and (h[c2] > h[i]), nu qua phi.
Hai thao tc trn c t trong hm tnh din tch ca hnh ch nht ABCD
ln nht cha im y[i]. Hm cho ra ba gi tr:
c1: im tri nht hay l to ct ca nh D.
c2: im phi nht hay l to ct ca nh C.
Din tch ca hnh.
(*-------------------------------------------
Dien tich cua hinh chua diem y[i]
--------------------------------------------*)
function DienTich(i: byte; var c1,c2: byte): longint;
begin
{Qua trai}
c1 := i;
while (y[c1-1] = y[i]) and (h[c1-1] >= h[i])
do dec(c1);
{Qua phai}
c2 := i;
while (y[c2+1] = y[i]) and (h[c2+1] >= h[i])
do inc(c2);
DienTich := h[i]*(c2 + 1 - c1);
end;
Phn x l chnh c t trong th tc Run.
Sng to trong Thut ton v Lp trnh Tp I

239



Mng h[1..m] lc u c khi tr ton 0. Sau mi ln c dng y ta chnh li
cao h theo tiu chun sau.
Ti im i ang xt trn dng y, nu y[i] = x[i] cao h[i] c tng thm 1.
Ngc li, nu y[i] = x[i] ta t li cao h[i] = 1.
{Chinh do cao}
for i := 1 to m do
if y[i] = x[i] then inc(h[i]) else h[i] := 1;
Mt vi ch gii
1. Chng ta s dng phn t h[0] = 0 v h[m+1] = 0 chn vng lp,
c th l cc iu kin (h[c1-1] >= h[i]) v (h[c2+1] >=
h[i]) tr thnh false cui vng lp.
2. Mt con m dng d kiu longint cho bit ta ang x l dng no ca tp.
3. Dng x lc u c khi tr ton du cch l k t khng c trong vn bn th
hin tm bn .
4. Mi khi x l xong dng y ta cn sao chp gi tr ca y cho x lu gi cho
bc tip theo. Khi x s tr thnh dng trc.
5. Mi khi tm c mt hnh ch nht, ta so snh din tch ca hnh vi din tch
ln nht hin c (dtmax) lun lun m bo rng dtmax chnh l din tch
ln nht trong vng kho st.
Th tc Run c thit k theo s sau:
1. M tp d liu CNMAX.INP;
2. c gi tr chiu di mi dng vo bin m;
3. Khi tr:
Con m dng d := 0;
Dng trc x ton du cch;
Mng chiu cao h ton 0;
dtmax := 0; {din tch max}
4. Lp cho n khi ht tp CNMAX.INP:
4.1. c dng y;
4.2. Tng con m dng d;
4.3. Chnh cao h[1..m];
4.4. X l mi k t y[i] ca dng y; i = 1..m.
4.4.1. Tm din tch dt ca hnh ch nht ln nht cha phn t y[i];
cho gi tr ra l dt v hai ch s u tri c1 v u phi c2 th hin
cnh y ca hnh ch nht.
4.4.2. Nu dt > dtmax: chnh li cc gi tr
Din tch max: dtmax := dt;
To nh A(Axmax, Aymax):
Axmax := d h[i] + 1;
Aymax := c1;
To nh C(Cxmax , Cymax):
Cxmax := d;
Cymax := c2;
4.5. Sao chp dng y sang x: x := y;
Sng to trong Thut ton v Lp trnh Tp I

240



5. ng tp CNMAX.INP.
6. Thng bo kt qu.
procedure Run;
var i,c1,c2: byte;
dt: longint;
begin
assign(f,fn); reset(f); readln(f,m);
d := 0;
{Khoi tri cho dong dau tien}
x := BL;
for i := 1 to m do x := x + BL;
{Khoi tri cho chieu cao}
fillchar(h,sizeof(h),0);
while not eof(f) do
begin
readln(f,y);
inc(d);
{Chinh do cao}
for i := 1 to m do
if y[i] = x[i] then inc(h[i]) else h[i] := 1;
for i := 1 to m do
begin
dt := DienTich(i,c1,c2);
if dt > dtmax then
begin
dtmax := dt;
Axmax := d-h[i]+1; Aymax := c1;
Cxmax := d; Cymax := c2;
end;
end;
x := y;
end;
close(f);
Ket; {ghi ket qua}
end;
phc tp tnh ton
Gi s tp CNMAX.INP cha n dng, mi dng cha m k t. Khi x l mt dng,
ti mi k t th i trn dng ta dch chuyn qua tri v qua phi, tc l ta phi thc
hin ti a m php duyt. Vy, vi mi dng gm m k t ta phi thc hin m
2
php
duyt. Tng cng, vi n dng ta thc hin ti a t = n.m
2
php duyt.
(* Pascal *)
(******************************************
CNMAX Dien tich hinh chu nhat
toi dai
******************************************)
uses crt;
const
fn = 'CNMAX.INP'; {Ten tep chua du lieu vao}
gn = 'CNMAX.OUT'; {Ten tep chua du lieu ra}
MN = 80; {chieu rong van ban}
Sng to trong Thut ton v Lp trnh Tp I

241



BL = #32; {dau cach}
NL = #13#10; {xuong dong moi}
var f,g: text;
m: byte; {chieu rong tam ban do}
d: longint; {dem dong}
x,y: string; {x - dong tren}
{y dong duoi}
h: array[0..MN] of longint;
{chieu cao cua cac cot}
dtmax: longint; {Dien tich max}
Axmax, Cxmax: longint; {toa do diem A, C}
Aymax,Cymax: byte;
(*------------------------------
Ghi file ket qua
--------------------------------*)
procedure Ket;
begin
assign(g,gn); rewrite(g);
writeln(g,Dtmax);
writeln(g,Axmax,BL,Aymax);
writeln(g,Cxmax,BL,Cymax);
close(g);
end;
(*--------------------------------------------
Dien tich cua hinh chua diem y[i]
---------------------------------------------*)
function DienTich(i: byte; var c1,c2: byte): longint;
t vit
procedure Run; t vit
BEGIN
run;
END.
// C#
using System;
using System.IO;
namespace SangTao1
{
/*------------------------------
* Chu nhat toi dai
* -----------------------------*/
class ChuNhatMax
{
static string fn = "cnmax.inp"; // input file
static string gn = "cnmax.out"; // output file
static string x;// dong tren
static string y;// dong duoi
static int m = 0; // chieu dai moi dong
static int[] d; // cao do
static int dong = 0; // dem dong
static int smax = 0; // dien tich max
static int ad = 0; // toa do dong cua dinh A
static int ac = 0; // toa do cot cua dinh A
Sng to trong Thut ton v Lp trnh Tp I

242



static int cd = 0; // toa do dong cua dinh C
static int cc = 0; // toa do cot cua dinh C

static void Main()
{
Run(); Ghi(); Test();
Console.ReadLine();
} // Main
static void Ghi()
{
File.WriteAllText(gn, smax + "\n" +
ad + " "+ ac+"\n"+cd+" "+cc);
}
static void Test() t vit
static void Run()
{
StreamReader f = File.OpenText(fn);
do // Bo cac dong trong dau file
{
y = f.ReadLine().Trim();
} while (y.Length == 0);
m = int.Parse(y);
Console.WriteLine(m);
d = new int[m + 2];
x = new string('#', m + 2);
Array.Clear(d,0,d.Length);
dong = 0; smax = 0;
while (!f.EndOfStream)
{
y = f.ReadLine().Trim();
if (y.Length < m) break;
++dong; XY(); x = y;
}
f.Close(); ac++; cc++;
}
// Xu li cap dong x va y
static void XY()
{
int t = 0; // chi so trai
int p = 0; // chi so phai
int dt = 0; // dien tich
for (int i = 0; i < m; ++i)
if (y[i] == x[i]) ++d[i];
else d[i] = 1;
for (int i = 0; i < m; ++i)
{
t = Trai(i); p = Phai(i);
dt = (p - t + 1) * d[i];
if (smax < dt)
{
smax = dt;
ad = dong - d[i] + 1; ac = t;
cd = dong; cc = p;
Sng to trong Thut ton v Lp trnh Tp I

243



}
}
}
// quet tu k qua phai
static int Phai(int k)
{
for (int i = k + 1; i < m; ++i)
if (d[i] < d[k]) return i - 1;
return m - 1;
}
// quet tu k qua trai
static int Trai(int k)
{
for (int i = k - 1; i >= 0; --i)
if (d[i] < d[k]) return i + 1;
return 1;
}
} // ChuNhatMac
} // SangTao1
ng dng
Bi ton tm hnh ch nht ti i thng dng trong lnh vc ho v x l nh.
Di y lit k vi ng dng in hnh.
1. Trong khi v bn ta thng phi tm mt hnh ch nht ti i trong mt
vng, chng hn lnh th ca mt quc gia c th vit cc k t vo nh
tn quc gia, tn chu lc.
2. Trong hnh hc phn hnh (fractal) ta thng phi tm mt s hnh vung hoc
ch nht ti i tho mn mt s tiu chun cho trc lm mu.
Trong bi ny, trnh by vn c n gin chng ta thay mi im bng
mt k t.
Bi tp lm thm
Bi T1. Vi mi k t c cho trc hy tm trong tp CNMAX.INP mt hnh ch
nht ti i cha ton k t c.
Bi T2. Vi cp gi tr (k, c) cho trc hy tm hnh ch nht ti i cha cng
mt loi k t v ng thi cha im nm trn dng k, ct c ca tp
CNMAX.INP.
Bi 8.4. Ma phng
Ma phng l nhng bng s hnh vung trong mi dng, mi ct v mi
ng cho u cng tho mt s tnh cht no . Cc nh thin vn c Trung
Hoa cho rng mi tinh t trn bu tri u ng vi mt ma phng. Nhiu nh
ton hc c Ai Cp, n v sau ny cc nh ton hc phng Ty pht
hin nhng tnh cht kh l th ca cc loi ma phng. Trong bi ny ta gii
hn khi nim ma phng theo ngha sau.
Sng to trong Thut ton v Lp trnh Tp I

244



Ma phng bc n l mt bng s hnh vung, mi cnh n cha cc s t 1 n n
2
sao
cho tng cc s trn mi dng, trn mi ct v trn mi ng cho u bng nhau.
Tng ny c gi l c s ca ma phng.
4 9 2

16 2 3 13
3 5 7

5 11 10 8
8 1 6

9 7 6 12

4 14 15 1

(a) (b)
(a) ma phng bc 3, c s S
3
= 15
(b) ma phng bc 4, c s S
4
= 34

Yu cu: Vi mi tr N = 1..20 xy dng ma phng bc n.
Bi gii
Ta d dng tnh c c s ca ma phng bc n qua nhn xt: tng ca mt ct
(dng) chnh l tng ca ton b cc s nm trong bng chia cho s ct (s dng):
S
n
= (1 + 2 + ... + n
2
)/n = n(n
2
+ 1)/2.
Theo cc th d trn ta c:
c s ca ma phng bc 3: S
3
= 3(9 + 1)/2 = 15.
c s ca ma phng bc 4: S
4
= 4(16 + 1)/2 = 34.
Nh vy, trong ma phng bc 3, tng ca cc s nm trn cng hng, cng ct
hoc cng ng cho u l 15. Trong ma phng bc 4, tng ny l 34.
Tnh cht trn khng thay i nu ta in ln lt cc s hng ca mt cp s cng
vo ma phng.
Ngoi bc n = 2, vi mi s t nhin n > 1 u tn ti ma phng vi nhiu cch
b tr khc nhau. Chng ta s tm hiu hai thut ton d ci t.
Vi mi n cho trc ta xt tnh chn l ca n. Nu n l ta gi th tc MPL (ma phng
bc l), ngc li ta gi th tc MPC (ma phng bc chn).

(*-------------------------------
Ma phuong
--------------------------------*)
procedure MP(bac: word);
begin
n := bac;
if n = 2 then exit;
if Odd(n) then MPL else MPC;
Test;
end;
Trong n l bin tng th cha bc ca ma phng cn xy dng.
Sng to trong Thut ton v Lp trnh Tp I

245



Hm Odd(n) cho gi tr ng (true) khi n l mt s l, ngc li hm nhn gi tr
sai (false).
Th tc MPL(n): Ma phng bc l


k



k + 1


in theo hng ng - Nam cho ma phng bc l.
Ta dng mt mng hai chiu M cha ma phng cn xy dng theo cc bc
sau y. cho tin ta t tn cho ma phng cn xy dng l hnh vung ABCD.
Bc 1. Khi tr: in cc s 0 vo bng M[1..n, 1..n].
Bc 2. Xc nh xut pht: l gia ca dng cui, tc l
M[i, j] vi i = n, j = (n div 2) +1.
Bc 3. in s: Vi mi k bin thin t 1 n n
2
ta thc hin cc thao tc sau:
3.1. in (i, j): M[i, j]:= k;
3.2. Xc nh v tr ii, jj mi in s tip theo (k + 1).
V tr ii, jj mi c xc nh theo nguyn tc ng-Nam vi ngha l sau khi
in gi tr k, gi tr k + 1 s c vit vo nm v tr ng-Nam so vi cha k.
Nh vy, nu M[i, j] = k th v tr cha k + 1 s l ii:= i + 1, jj:= j + 1. C th s xy ra
cc tnh hung sau y:
3.2.1. (i = n) v (j = n): S k vit gc ng-Nam (gc C) ca ma phng. Khi
, nu i tip theo hng ng-Nam th s ri vo nm ngoi bng. Ta gi tnh
hung ny l tnh hung ng-Nam v x l nh sau: vit s k + 1 vo st trn cha
k, tc l chn
ii := n-1; jj := n;
Ta gi phng thc x l ny l n trn: n vo trn va vit (xem cc s 6
7 trong ma phng bc 3).
3.2.2. (i = n) v (j < n): S k vit nm cnh DC v khc C. Ta gi tnh hung
ny l tnh hung Nam v x l theo phng thc "ni bt" nh sau: Vit k + 1 vo v
tr ng-Nam tc l
i+1 = n+1,j+1.
D nhin ny nm ngoi bng, di cnh DC. By gi ta cho n ni ln ti cnh
AB. Nh vy ta s chn
ii := (i mod n) + 1;
jj := (j mod n) + 1;
(xem cc s 1 2 v 8 9 trong ma phng bc 3).
Sng to trong Thut ton v Lp trnh Tp I

246



3.2.3. (i < n) v (j = n): S k vit nm cnh BC v khc C. Ta gi tnh hung
ny l tnh hung ng v x l theo theo phng thc y tri nh sau: Vit k + 1 vo
v tr ng-Nam tc l
i+1, j+1 = n+1
ny nm ngoi bng, bn phi cnh BC. By gi ta y tri n sang ti cnh AD.
Ging nh trn, ta chn:
ii := (i mod n) + 1;
jj := (j mod n) + 1;
(xem cc s 2 3 v 7 8 trong ma phng bc 3).
3.2.4. ng : Cui cng c th (ii, jj) ri vo trong bng nhng c s
c vit trc. Ta gi tnh hung ny l tnh hung ng v x l theo phng thc
n trn nh tnh hung ng-Nam (xem bc i 3 v 4 trong ma phng bc 3).
Trng hp ny ta chn:
ii := i- 1; jj := j;
S dng php ton ng d ta c th gii quyt t ng cc tnh hung Nam v
ng theo cng thc
ii := (i mod n)+1 ; jj := (j mod n)+1;

A

B

A

B


k+1 k
k k+1
D C
ng-Nam
D C
ng


A

B

A

B

k+1 k+1
k
k *
D C
Nam
D C
ng
Cc tnh hung khi in ma phng bc l
Di y l th tc ma phng bc l.
(*---------------------------------
Ma phuong bac le
----------------------------------*)
procedure MPL;
var k,i,ii,j,jj: word;
begin
{Buoc 1: Khoi tri}
Sng to trong Thut ton v Lp trnh Tp I

247



fillchar(M, sizeof(M),0);
{Buoc 2: Xac dinh o xuat phat}
i := n;
j := n div 2 + 1;
{Buoc 3: Dien so}
for k := 1 to n*n do
begin
{3.1. Dien o (i,j)}
M[i,j] := k;
{3.2 Xac dinh vi tri ii,jj
cho so tiep theo (k+1)}
if (i=n) and (j=n) then
{3.2.1.Tinh huong Dong-Nam:Den tren}
begin
ii := n-1; jj := n;
end
else
begin {3.2.2 va 3.2.3.}
ii := i mod n + 1;
jj := j mod n + 1;
end;
if M[ii,jj]<>0 {o da dien} then
begin
{3.2.4. Dung do: Den tren}
ii := i-1; jj := j;
end;
i := ii; j := jj;
end;
end;
Th tc MPC(n): Ma phng bc chn
Bc 1. Khi tr: in cc s t 1 n n
2
vo bng theo trt t t trn xung di,
t tri sang phi. Th d, vi n = 4, M c khi tr nh sau:

1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
Khi tr cho ma phng bc 4
Bc 2. To xu mu: Ta to xu mu s phc v cho vic i ch cc s trong M.
Xu mu s c chiu di k = n div 2 v bao gm cc k t 'T', 'D', 'N' v 'B' vi cc
ngha sau:
- 'T' - thc hin php i xng tm: i ch cc cp phn t:
M[i,j] M[n-i+1,n-j+1]
Sng to trong Thut ton v Lp trnh Tp I

248



M[i,n-j+1] M[n-i+1,j]
- 'D' - thc hin php i xng theo trc dc: i ch cp phn t:
M[i,j] M[i,n-j+1]
- 'N' - thc hin php i xng theo trc ngang: i ch cp phn t:
M[i,j] M[n-i+1,j]
- 'B' - khng lm g.
Xu mu s c to nh sau:
2.1. Khi tr xu rng s[0] := #0;
2.2. Tnh k := n div 2;
2.3. Np (k div 2) k t 'T' cho s.
for i := 1 to (k div 2) do
s := s+TT;
2.4. Nu k l np thm hai k t 'DN' cho s:
if Odd(k) then s := s+DD+NN;
2.5. in thm cc k t 'B' cho k k t trong s.
for i := length(s)+1 to k do s := s+BB;
trong cc hng TT, DD, NN v BB c khai bo nh sau
const
TT = 'T'; {doi xung Tam}
DD = 'D'; {doi xung Doc}
NN = 'N'; {doi xung Ngang}
BB = 'B'; {Bo qua}
Cc th d to xu mu s:
- Vi n = 4 ta c k = n div 2 = 2 (chn), k div 2 = 1, do s='TB'
- Vi n = 6 ta c k = n div 2 = 3 (l), k div 2 = 1, do s='TDN'
- Vi n = 18 ta c k = n div 2 = 9 (l), k div 2 = 4, do s='TTTTDNBBB'
Th tc khi tr cho ma phng bc chn s nh sau:
(*-----------------------------------------
Khoi tri cho ma phuong bac chan
------------------------------------------*)
procedure InitMPC;
var i,j: word;
begin
{Buoc 1. Khoi tri}
for i := 1 to n do
for j := 1 to n do
M[i,j] := Num(i,j);
{Buoc 2: Tao xau mau}
s[0] := #0; {Khoi tri xau rong}
k := n div 2;
{Nap (k div 2) ki tu T}
for i := 1 to (k div 2) do s := s+TT;
{Nap them 2 ki tu D va N neu k le}
if Odd(k) then s := s+DD+NN;
{Bu cac ki tu B cho du k ki tu}
for i := length(s)+1 to k do s := s+BB;
end;
Sng to trong Thut ton v Lp trnh Tp I

249



Ch rng khi tr gi tr rng cho xu s ta c hai cch:
Cch 1. Vit hai du nhy n st nhau:
s := '';
Cch 2. Gn cho phn t s[0] l ni cha chiu di xu s gi tr #0 ng vi k
t c m ASCII l 0:
s[0] := #0;
Cch th nht khin bn c d nhm vi du cch, nn dng cch th hai.
Bc 3. in s theo xu mu
for i := 1 to k do
begin
XuLyDong(i);
QuayXauMau;
end;
x l dng i ta ln lt xt cc k t s[j] trong xu mu v x l tng phn t
M[i, j], j = 1..length(s).
- Nu s[j] = 'T' ta gi th tc Tam(i,j,n) thc hin i xng tm cho cc
(i, j) v (i, n j + 1).
- Nu s[j] = 'D' ta gi th tc Doc(i,j,n) thc hin i xng theo trc dc
cho (i, j).
- Nu s[j] = 'N' ta gi th tc Ngang(i, j, n) thc hin i xng theo trc
ngang cho (i, j).
- Nu s[j] = 'B' ta b qua.
procedure XuLyDong(i: word);
var j: word;
begin
for j := 1 to k do
case s[j] of
TT: Tam(i,j);
DD: Doc(i,j);
NN: Ngang(i,j);
end;
end;
rng ti bc khi tr s nm trn (i, j) s c gi tr (i 1)*n + j. Ta s s
dng hm Num(i,j,n) tnh gi tr ny.
(*------------------------------------
So nam tren hang i, cot j.
-------------------------------------*)
function Num(i,j: word):word;
begin
Num := (i-1)*n+j;
end;
Cc th tc ly i xng qua tm, dc v ngang l kh n gin.
(*-------------------------------------
Lay doi xung qua tam (2 cap so)
--------------------------------------*)
procedure Tam(i,j: word);
begin
M[i,j] := Num(n-i+1,n-j+1);
Sng to trong Thut ton v Lp trnh Tp I

250



M[n-i+1,n-j+1] := Num(i,j);
M[n-i+1,j] := Num(i,n-j+1);
M[i,n-j+1] := Num(n-i+1,j);
end;
(*--------------------------------------
Doi xung doc
--------------------------------------*)
procedure Doc(i,j: word);
begin
M[i,j] := Num(i,n-j+1);
M[i,n-j+1] := Num(i,j);
end;
(*-----------------------
Doi xung ngang
------------------------*)
procedure Ngang(i,j: word);
begin
M[i,j] := Num(n-i+1,j);
M[n-i+1,j] := Num(i,j);
end;
Mi ln x l xong mt dng ta cn quay xu mu s thm mt v tr theo chiu kim
ng h, k t cui xu c a v u xu, cc k t khc c dch qua phi mt v
tr.
Th d v quay xu mu s: Vi n = 18 ta c:
s = 'TTTTDNBBB'
sau ln quay th nht ta thu c
s = 'BTTTTDNBB'
sau ln quay th hai ta thu c
s = 'BBTTTTDNB'

quay xu s[1..k] ta ly k t cui cng s[k] ghp ln khc u s[1..k-1], tc l
t
s := s[k]+s[1..k-1]
ly on s[1..k-1] ta gi hm copy:
copy(s,1,len-1)
trong len chnh l chiu di xu s.
Lnh
copy(s,i,m)
s to ra mt xu con ca xu s vi m k t k t k t th i:
copy(s,i,m) = s[i..(i+m-1)]
(*--------------------------
Quay xau mau s 1 vi tri
---------------------------*)
procedure QuayXauMau;
var len: byte;
begin
len := length(s);
s := s[len] + copy(s,1,len-1);
end;
Sng to trong Thut ton v Lp trnh Tp I

251



Sau y l th tc to ma phng bc chn.
(*---------------------------
Ma phuong bac chan
----------------------------*)
procedure MPC;
var i,j: word;
begin
if n=2 then exit;
InitMPC;
{Dien so theo xau mau}
for i := 1 to k do
begin
XuLyDong(i);
QuayXauMau;
end;
end;
Sau khi to xong ma phng ta cn kim tra li xem ma trn M c tho cc tnh
cht c bn ca ma phng bc n cho trc hay khng.
Th tc Test s hin th ma phng trn mn hnh v ng thi kim tra xem cc
tng cc phn t trn mi dng, tng cc phn t trn mi ct, tng cc phn t trn
ng cho chnh c1 v tng cc phn t trn ng cho ph c2 c bng c s ca
ma phng hay khng.
Ta s dng hai mng dong[1..n], cot[1..n] v hai bin n c1, c2 tnh cc tng
ny bng mt ln duyt mng hai chiu M.
tnh c s ta lu kiu ca bin cha c s d l longint trong khi cc
tr ca mng M l word. Trong Turbo Pascal c nguyn tc sau:
Nguyn tc nh kiu cho biu thc
Kiu ca tr ca biu thc s s l kiu rng nht
trong s cc kiu ca cc i lng (hng v bin)
c mt trong biu thc.
Theo quy nh ny, vi khai bo n l bin kiu word th kiu ca tr ca biu thc
tnh c s ca ma phng bc n
((n*n+1)*n) div 2
cng s l word.
iu ny c th dn n trn s.
Ta khc phc bng thao tc hai bc nh sau:
d := 0;
d := d+((n*n+1)*n) div 2;
Khi , do biu thc v phi ca php gn c cha bin d thuc kiu longint
nn kt qu s c kiu longint.
Bn cng c th dng ton t chuyn sang kiu longint mt trong cc i lng
trong biu thc v phi, chng hn:
d := ((n*n+longint(1))*n) div 2
(*--------------------------------
Hien thi va kiem tra ket qua
----------------------------------*)
procedure Test;
var i,j: word;
Sng to trong Thut ton v Lp trnh Tp I

252



dong, cot: ML1;
d,c1,c2: longint;
begin {Tinh Dac so}
d := 0;
d := d+((n*n+1)*n) div 2;
writeln(NL,' Ma phuong bac ',n,', Dac so: ',d);
fillchar(dong,sizeof(dong),0);
fillchar(cot,sizeof(cot),0);
c1 := 0;
c2 := 0;
for i := 1 to n do
begin
writeln;
c1 := c1 + M[i,i];
c2 := c2 + M[i,n-i+1];
for j := 1 to n do
begin
write(M[i,j]:4);
dong[i] := dong[i] + M[i,j];
cot[j] := cot[j] + M[i,j];
end;
end;
writeln;
for i := 1 to n do
begin
if dong[i] <> d then
writeln(' Sai dong ',i,BL,dong[i]);
if cot[i] <> d then
writeln(' Sai cot ',i,BL, cot[i]);
end;
if c1 <> d then writeln(' Sai cheo chinh ',c1);
if c2 <> d then writeln(' Sai cheo phu ',c2);
end;
(* Pascal *)
Chng trnh MAPHUONG.PAS di y to b d liu kim th vi cc ma
phng t bc 1 n bc 20.
(* MAPHUONG.PAS *)
uses crt;
const
MN = 50;
TT = 'T'; {doi xung Tam}
DD = 'D'; {doi xung Doc}
NN = 'N'; {doi xung Ngang}
BB = 'B'; {Bo qua}
BL = #32; {dau cach}
NL = #13#10; {qua dong moi}
type
MW1 = array[0..MN] of word;
MW2 = array[0..MN] of MW1;
ML1 = array[0..MN] of longint;
var M: MW2;
Sng to trong Thut ton v Lp trnh Tp I

253



n,k: word;
s: string;
(*--------------------------------
Hien thi va kiem tra ket qua
----------------------------------*)
procedure Test; t vit
(*------------------------------------
So nam tren hang i, cot j
-------------------------------------*)
function Num(i,j: word):word;
begin
Num := (i-1)*n+j;
end;
(*-------------------------------------
Lay doi xung qua tam (2 so)
--------------------------------------*)
procedure Tam(i,j: word); t vit
(*--------------------------------------
Doi xung doc
--------------------------------------*)
procedure Doc(i,j: word); t vit
begin
M[i,j] := Num(i,n-j+1);
M[i,n-j+1] := Num(i,j);
end;
(*--------------------------------------
Doi xung ngang
---------------------------------------*)
procedure Ngang(i,j: word); t vit
(*--------------------------
Quay xau mau s 1 vi tri
---------------------------*)
procedure QuayXauMau; t vit
(*-----------------------------------------
Khoi tri cho ma phuong bac chan
------------------------------------------*)
procedure InitMPC; t vit
procedure XuLyDong(i: word); t vit
(*---------------------------
Ma phuong bac chan
----------------------------*)
procedure MPC; t vit
(*---------------------------------
Ma phuong bac le
----------------------------------*)
procedure MPL; t vit
(*-------------------------------
Ma phuong
--------------------------------*)
procedure MP(bac: word); t vit
(*--------------------------------
Test cac ma phuong bac 1..20
----------------------------------*)
Sng to trong Thut ton v Lp trnh Tp I

254



procedure Run;
var i: word;
begin
clrscr;
for i := 1 to 20 do MP(i);
end;
BEGIN
Run;
END.
// C#
using System;
namespace SangTao1
{
class maphuong
{
const int mn = 50;
static int[,] a = new int[mn, mn]; // Ma phuong
static char[] s = new char[mn]; // Xau mau
static void Main(string[] args)
{
for (int n = 1; n <= 20; ++n)
{ MaPhuong(n); Console.ReadLine();}
}
static void MaPhuong(int n)
{
if (n == 2)
Console.WriteLine("\n Khong ton tai "+
"Ma phuong bac 2");
else if (n % 2 == 1) MaPhuongLe(n);
else MaPhuongChan(n);
}
static void MaPhuongLe(int n)
{
Array.Clear(a,0,a.Length);
int i = n - 1;
int j = n / 2;
int nn = n * n;
a[i, j] = 1;
for (int k = 2; k <= nn; ++k)
{ Next(ref i, ref j, n); a[i, j] = k;}
Test(n); Print(n);
}
// Ma phuong le: Tim o dien tiep
static void Next(ref int i, ref int j, int n)
{
int ic = i; int jc = j;
i = (i + 1) % n; j = (j + 1) % n;
if (i + j == 0)
{ i = n - 2; j = n - 1;}
if (a[i, j] > 0)
{ i = ic - 1; j = jc;}
}
Sng to trong Thut ton v Lp trnh Tp I

255



static void MaPhuongChan(int n)
{
// Khoi tri 1, 2,..., n*n
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
a[i, j] = Num(n, i, j);
// Tao xau mau
int k = n / 2;
int k2 = k / 2;
for (int i = 0; i < k2; ++i)
s[i] = 'T';
for (int i = k2; i < k; ++i)
s[i] = 'B';
if (k%2==1) // k/2 le
{ s[k2] = 'D'; s[k2 + 1] = 'N';}
for (int i = 0; i < k; ++i)
{
for (int j = 0; j < k; ++j)
switch (s[j])
{
case 'T': Tam(n, i, j); break;
case 'D': Doc(n, i, j); break;
case 'N': Ngang(n, i, j); break;
} // switch
Quay(k);
}
Test(n); Print(n);
}
// Quay xau mau s qua phai 1 vi tri
static void Quay(int k)
{
char x = s[k - 1];
Array.Copy(s, 0, s, 1, k - 1);
s[0] = x;
}
// Doi xung qua Tam
static void Tam(int n, int i, int j)
t vit
// Doi xung qua truc doc
static void Doc(int n, int i, int j)
t vit
// Doi xung qua truc ngang
static void Ngang(int n, int i, int j)
t vit
// So nam tai ding i, cot j
static int Num(int n, int i, int j)
{ return (i * n) + j + 1;}
// Kiem tra cac ma phuong
static bool Test(int n)
{
int c1 = 0;
int c2 = 0;
// row[i] = tong dong i
Sng to trong Thut ton v Lp trnh Tp I

256



int[] row = new int[n];
// col[j] = tong cot j
int[] col = new int[n];
int dacso = (n * n + 1) * n / 2;
Console.WriteLine("\n\n Ma phuong bac "
+ n);
Console.WriteLine(" Dac so: " + dacso);
for (int i = 0; i < n; ++i)
{ row[i] = col[i] = 0;}
// tinh tong cac cot va dong
for (int i = 0; i < n; ++i)
{
c1 += a[i, i];
c2 += a[i, n - 1 - i];
for (int j = 0; j < n; ++j)
{ row[i] += a[i, j];
col[j] += a[i, j];}
}
if (c1 != dacso)
{
Console.WriteLine("Loi Duong cheo 1:"
+" Dac so " + dacso + ", " + c1);
return false;
}
if (c2 != dacso)
{
Console.WriteLine("Loi Duong cheo 2:"
+" Dac so " + dacso + ", " + c2);
return false;
}
for (int i = 0; i < n; ++i)
{
if (row[i] != dacso)
{
Console.WriteLine("Loi dong "
+(i+1)+ ": "+" Dac so "+dacso
+", "+row[i]);
return false;
}
if (col[i] != dacso)
{
Console.WriteLine("Loi cot "
+(i+1)+": "+" Dac so "+dacso
+ ", " + col[i]);
return false;
}
}
return true;
}
// Hien thi Ma phuong
static void Print(int n)
{
for (int i = 0; i < n; ++i)
Sng to trong Thut ton v Lp trnh Tp I

257



{
Console.WriteLine();
for (int j = 0; j < n; ++j)
Console.Write("{0} ", a[i, j]);
}
}
} // MaPhuong
}// SangTao1
Cc bi ton Thp H Ni
Bi 8.5. Thp H Ni c







1 2 3

Hnh 5. Bi ton thp H Ni

C ba cc cm ti ba v tr l 1, 2 v 3 nh hnh 5. Trn mt cc, gi l cc a
c mt chng gm n a bng g hnh trn to nh khc nhau c xuyn l
gia ta nh nhng ng xu v t chng ln nhau to ra mt to thp.
Ngi chi phi chuyn c to thp sang cc b = a theo cc quy tc sau:
(1) Ngi chi c s dng cc cn li t tm cc tng thp.
(2) Mi ln ch c chuyn 1 tng thp t mt cc sang mt trong hai cc cn
li.
(3) Khng bao gi c t tng thp ln ln trn tng thp nh.
Hy tm cch gii bi ton trn vi s ln chuyn t nht.
Thut ton
Chc chn l bn bit cch gii bi ton trn. Tuy nhin c th gii d dng
cc bin th ca bi ton thp H Ni chng ta th tm hiu mt cch lp lun sau.
Gi s ta quan st mt ngi chi gii, tc l ngi chuyn c n tng thp t cc
1 sang cc 2 vi s ln chuyn ti thiu. Ta dng mt chic my nh chp tng kt qu
trung gian sau mi bc chuyn ca ngi chi ny. Tng s bc nh, tr tm nh ban
u, chnh l s bc chuyn cc tng. Trong s cc bc nh chc chn phi c mt bc
nh hnh 10.
Sng to trong Thut ton v Lp trnh Tp I

258















1 2 3

Hnh 10. Mt nh phi c
Ti sao vy? Ti v chng no cha d c n - 1 tng thp pha trn ca v tr 1
chuyn sang v tr 3 th anh ta khng th chuyn c tng thp cui, tc l tng ln
nht sang v tr 2.
Gi Hn(n,a,b) l th tc chuyn n tng thp t v tr a sang v tr b = a, ta thy:
- Nu n = 0: khng phi lm g;
- Nu n > 0 ta phi thc hin ba bc sau:
Thot tin chuyn n 1 tng thp t v tr a sang v tr c = 6 a b:
Hn(n-1,a,6-a-b)
Sau chuyn tng ln nht t v tr a sang v tr b:
a b
Cui cng chuyn n 1 tng thp t c sang b:
Hn(n-1,6-a-b,b)
rng, do ta m ho cc cc l 1, 2 v 3 cho nn bit hai trong ba v tr , l x,
y chng hn, ta d dng tnh c v tr cn li z theo h thc
z = 6xy
Th tc chuyn thp n tng t cc a sang cc b c vit bng Pascal nh sau:
procedure Hn(n,a,b: byte);
begin
if n = 0 then exit;
Hn(n-1,a,6-a-b);
write(a, '->',b,' ');
Hn(n-1,6-a-b,b);
end;
Chn phng thc ghi tp hoc mn hnh
C th chn mt trong hai cch ghi kt qu vo tp vn bn hoc hin th ln mn
hnh. Bn ch cn lu rng mn hnh c nh ngha nh l mt tp vn bn. Chnh
xc hn l nh sau. Trong Turbo Pascal vng m mn hnh, tc l ni cha d liu
xut ra mn hnh, c nh ngha di dng mt tp. Nu ta m mt tp vi tn rng
nh sau:
assign(f,'');
rewrite(f);
trong f l bin kiu tp vn bn c khai bo nh sau
var f: text;
th sau mi lnh
write(f,);
s xut d liu ra mn hnh.
Ngc li, khi tn tp trong lnh m tp ni trn khc rng, th d:
Sng to trong Thut ton v Lp trnh Tp I

259



assign(f,'hanoi.out');
rewrite(f);
th sau mi lnh
write(f,);
s ghi d liu vo tp hanoi.out trn a.
Chng trnh hon chnh di y s ghi kt qu vo tp vn bn hanoi.out
c m trn a. Trc khi ghi chnh thc, bn hy chy th chng trnh vi lnh m
tp c tn rng kim tra kt qu trn mn hnh. Sau khi thy ng , bn hy vit tn
tp c th lu kt qu vo a.
Chng trnh s dng bin m d nhm m s bc chuyn.
(* Pascal *)
uses crt;
var d: longint;
f: text;
procedure Hn(n,a,b: byte);
begin
if n = 0 then exit;
Hn(n-1,a,6-a-b);
inc(d);
writeln(f,d,'. ',a,' -> ',b);
Hn(n-1,6-a-b,b);
end;
procedure runHn(n: byte);
begin
d := 0;
assign(f,'hanoi.out');
rewrite(f);
writeln('-----------------');
Hn(n,1,2);
writeln(f,'Total: ',d,' step(s)');
close(f);
readln;
end;
BEGIN
runHn(3);
END.
Khi thc hin chng trnh Hanoi.pas vi n = 3 ta thu c kt qu sau:
1. 1 -> 2
2. 1 -> 3
3. 2 -> 3
4. 1 -> 2
5. 3 -> 1
6. 3 -> 2
7. 1 -> 2
Total: 7 step(s)
// C#
using System;
namespace Tap1
Sng to trong Thut ton v Lp trnh Tp I

260



{
/*------------------------------------
* Thap Ha Noi
* -----------------------------------*/
class ThapHaNoi
{
static int d = 0; // em so lan chuyen
static void Main()
{
Console.WriteLine("\n Ha Noi ");
HaNoi(3, 1, 2);
Console.ReadLine();
} // Main
static void HaNoi(int n, int a, int b)
{
if (n == 0) return;
HaNoi(n - 1, a, 6 - a - b);
Console.WriteLine((++d) +
". " + a + " -> " + b);
HaNoi(n - 1, 6 - a - b, b);
}
} // class
} // space

Bi 8.6. Thp H Ni xui
Ni dung ging nh bi ton thp H Ni c ch sa li quy tc (2) nh sau: (2)
Mi ln ch c chuyn 1 tng thp t mt cc sang cc st n theo chiu kim
ng h.


iu kin ny quy nh ba php chuyn 1 tng thp gia cc cc nh sau:
C, hoc C C, hoc C .
Hy tm cch gii bi ton vi s ln chuyn t nht.
Bi gii
Suy ngh mt cht bn s thy ci li ca nguyn tc "Bc nh buc phi c". t
tn cc tng thp theo th t t nh n ln l 1..n. Ta m t mi tm nh nh mt b
ba (a:[A], b:[B], c:[C]) trong A, B v C l cc tng thp t ti mi v tr tng ng.
Gi a l v tr xut pht, b l v tr ch, bi ton trn c th c pht biu nh sau:
Ga thit: (a:[1..n], b:[ ], c:[ ])

Kt lun: (a:[ ], b:[1..n], c:[ ])

C C
Sng to trong Thut ton v Lp trnh Tp I

261



Vi ngha l cho bit bc nh ban u v cui cng. Hy lit k t nht cc bc
nh cn c gia ba du chm () sao cho b nh gii thch c qu trnh chuyn
thp theo cc iu kin cho trc.
Mi bc nh c gi l mt hnh trng. Ngoi hai hnh trng u tin v cui
cng, mt trong nhng hnh trng buc phi c s l (a:[n ],b:[ ],c:[1..n-1
]). Tip l hnh trng (a:[ ],b:[n ],c:[1..n-1 ])thu c sau lnh
chuyn a b
Gi Hnx(n,a,b) l th tc gii bi ton thp H Ni xui, chuyn thp n tng t
v tr a sang v tr b. Ta xt hai trng hp.
a) Trng hp v tr b ng st v tr a theo chiu kim ng h:
Theo trng hp ny ta c cc cp (a, b) sau y: (1, 2), (2, 3) v (3, 1).
c t cho iu kin ca trng hp ny l b = (a mod 3)+1
Vi ngha l, nu bit m s v tr a th v tr b st sau a xui theo chiu kim ng
h s c tnh theo cng thc trn.
Nu v tr cc cc c b tr nh sau
C C
th gia a v b c ba tnh hung, c th l
Tnh hung
C C
1 a b
2 a b
3 b a
Thp H Ni xui
c t a v b k nhau b = (a mod 3)+1
Da vo cc hnh trng buc phi c ta c th m t vic chuyn thp trong trng
hp ny ging nh trong bi ton thp H Ni c, c th l:
Hnh trng ngha Lnh
(a: [1..n], b: [ ], c: [ ]) Hnh trng ban u vi v tr b st
v tr a.
b = (a mod 3)+1
chuyn n tng t a sang b theo
chiu kim ng h ta phi...

...
(a: [n], b: [ ], c: [1..n 1]) Chuyn (tm) n 1 tng t a qua c
= 6 a b.
Hnx(n1, a, 6 a
b)
(a: [ ], b: [n], c: [1..n 1]) sau chuyn tng cn li ca a
qua b.
a b
...
(a: [ ], b: [1..n], c: [ ]) Cui cng chuyn n 1 tng t c =
6 a b qua b l hon tt.
Hnx(n 1, 6 a
b, b)

on trnh cho trng hp ny s l
if b = (a mod 3)+1 then
begin {b ke a}
Hnx(n-1,a,6-a-b);
inc(d);
writeln(f,d,'. ',a,' -> ',b);
Hnx(n-1,6-a-b,b);
Sng to trong Thut ton v Lp trnh Tp I

262



end
b) Trng hp v tr b khng ng st v tr a theo chiu kim ng h:
Cc cp (a, b) khi s l: (1, 3), (2, 1) v (3, 2). c im chung ca cc cp ny
l: nu i t a n b theo chiu kim ng h chng ta phi vt qua c l v tr nm gia
a v b.

Tnh hung C C
1 a b
2 b a
3 b a
Thp H Ni xui
c t a v b khng k nhau b = (a mod 3) + 1
Cc hnh trng buc phi c khi s l:
Hnh trng ngha Lnh
(a: [1..n], c: [ ], b: [ ]) Hnh trng ban u vi v tr b cch a
qua c theo chiu kim ng h.
b = (a mod 3) + 1
chuyn n tng t a sang b cch
qua v tr c = 6 a b ta phi...

...
(a: [n], c: [ ], b: [1..n 1] Chuyn (tm) n 1 tng t a qua b. Hnx(n 1, a, b)
(a: [ ], c: [n], b: [1..n 1]) sau chuyn (tm) tng cn li ca
a qua c = 6 a b.
a 6 a b
...
(a: [1..n 1], c: [n], b: [ ]) Ri li chuyn (tm) n 1 tng t b
qua a nhm gii phng v tr ch b...
Hnx(n 1, b, a)
(a: [1..n 1], c: [ ], b: [n]) chuyn tng ln nht n t c qua b. 6 a b b
(a: [ ], c: [ ], b: [1..n]) Cui cng chuyn n 1 tng t a qua
b l hon tt.
Hnx(n 1, a, b)

(* Pascal *)
(*******************************
Ha Noi xuoi
*******************************)
uses crt;
var d: longint;
f: text;
procedure Hnx(n,a,b: byte);
begin
if n = 0 then exit;
if b = (a mod 3)+1 then
begin {b ke a}
Hnx(n-1,a,6-a-b);
inc(d);
writeln(f,d,'. ',a,' -> ',b);
Hnx(n-1,6-a-b,b);
Sng to trong Thut ton v Lp trnh Tp I

263



end
else {b cach a qua vi tri c}
begin
Hnx(n-1,a,b);
inc(d);
writeln(f,d,'. ',a,' -> ',6-a-b);
Hnx(n-1,b,a);
inc(d);
writeln(f,d,'. ',6-a-b,' -> ',b);
Hnx(n-1,a,b);
end;
end;
procedure runHnx(n: byte);
begin
d := 0;
assign(f,'hnx.out');
rewrite(f);
writeln('-----------------');
Hnx(n,1,2);
writeln(f,'Total: ',d,' step(s)');
close(f);
readln;
end;
BEGIN
runHnx(3);
END.
Li gi runHnx(3) chuyn n tng thp t cc 1 sang cc 2 s cho ta kt qu sau:
1. 1 -> 2
2. 2 -> 3
3. 1 -> 2
4. 3 -> 1
5. 2 -> 3
6. 1 -> 2
7. 2 -> 3
8. 1 -> 2
9. 3 -> 1
10. 1 -> 2
11. 3 -> 1
12. 2 -> 3
13. 1 -> 2
14. 3 -> 1
15. 1 -> 2
Total: 15 step(s)
// C#
using System;
namespace SangTao1
{
/*------------------------------------
* Thap Ha Noi Xuoi
* -----------------------------------*/
class ThapHaNoiXuoi
{
static int d = 0;//so buoc chuyen tang thap
static void Main()
{
Console.WriteLine("\n Ha Noi Xuoi");
HaNoiXuoi(3, 1, 2);
Console.WriteLine("\n Total: "
Sng to trong Thut ton v Lp trnh Tp I

264



+ d + " steps");
Console.ReadLine();
} // Main
static void HaNoiXuoi(int n, int a, int b)
{
if (n == 0) return;
if (b == (a % 3) + 1)
{
HaNoiXuoi(n - 1, a, 6 - a - b);
Console.WriteLine((++d)+". "+a
+" -> "+b);
HaNoiXuoi(n - 1, 6 - a - b, b);
}
else // a c b, c = 6-a-b
{
HaNoiXuoi(n - 1, a, b);
Console.WriteLine((++d)+". "+a+
" -> "+(6-a-b));
HaNoiXuoi(n - 1, b, a);
Console.WriteLine((++d)+". "+
(6-a-b)+" -> "+b);
HaNoiXuoi(n - 1, a, b);
}
}
} // ThapHaNoiXuoi
} // SangTao1
Bi 8.7. Thp H Ni ngc
Ni dung ging nh bi ton thp H Ni c ch sa li quy tc (2) nh sau: (2)
Mi ln ch c chuyn 1 tng thp t mt cc sang cc st n v hng
ngc chiu kim ng h.
iu kin ny quy nh ba php chuyn 1 tng thp nh sau:
C C, hoc C, hoc C .
Hy tm cch gii bi ton vi s ln chuyn t nht.
Bi gii
Bi ny tng t nh bi H Ni xui. Ta ch cn xc nh iu kin k gia hai
cc thp v lu n chiu chuyn cc tng thp ngc chiu quay ca kim ng h.
a) Trng hp v tr b ng st v tr a ngc chiu kim ng h:
Theo trng hp ny ta c cc cp (a, b) sau y: (3, 2), (2, 1) v (1, 3).
Hon i v tr ca hai i lng a v b trong iu kin k ca bi ton H Ni xui
ta thu c iu kin k trong trng hp ny l
a = (b mod 3)+1
Tnh hung
C C
1 a b
2 b a
3 b a
Thp H Ni ngc
c t a v b k nhau a = (b mod 3) + 1
Sng to trong Thut ton v Lp trnh Tp I

265




Vi ngha l, nu bit m s v tr a th v tr b st sau a ngc chiu kim ng h
s c tnh theo cng thc trn.
Da vo cc hnh trng buc phi c ta c th m t vic chuyn thp trong trng
hp ny ging nh trong bi ton thp H Ni xui, c th l:
Hnh trng ngha Lnh
(a: [1..n], b: [ ], c: [ ]) Hnh trng ban u vi v tr b st v
tr a.
a = (b mod 3) + 1
chuyn n tng t a sang b ngc
chiu kim ng h ta phi...

...
(a: [n], b: [ ], c: [1..n 1]) Chuyn (tm) n 1 tng t a qua c =
6 a b.
Hnn(n 1, a, 6
a b)
(a: [ ], b: [n], c: [1..n 1]) sau chuyn tng cn li ca a qua
b.
a b
...
(a: [ ], b: [1..n], c: [ ]) Cui cng chuyn n 1 tng t c = 6
a b qua b l hon tt.
Hnn(n 1, 6
a b, b)


on trnh cho trng hp ny s l
if a = (b mod 3)+1 then
begin {b ke a}
hnn(n-1,a,6-a-b);
inc(d);
writeln(f,d,'. ',a,' -> ',b);
hnn(n-1,6-a-b,b);
end

b) Trng hp v tr b khng ng st v tr a theo chiu ngc kim ng h:
Cc cp (a, b) khi s l: (1, 2), (2, 3) v (3, 1). c im chung ca cc cp ny
l: nu i t a n b ngc chiu kim ng h chng ta phi vt qua c l v tr nm
gia a v b.

Tnh hung
C C
1 a b
2 a b
3 b a
Thp H Ni ngc
c t a v b khng k nhau
a = (b mod 3) + 1
Cc hnh trng buc phi c khi s rt ging vi tnh hung tng t ca bi
ton H Ni xui:
Sng to trong Thut ton v Lp trnh Tp I

266



Hnh trng ngha Lnh
(a: [1..n], c: [ ], b: [ ]) Hnh trng ban u vi v tr b cch
a qua c ngc chiu kim ng h.
a = (b mod 3) + 1
chuyn n tng t a sang b cch
qua v tr c = 6 a b ta phi...

...
(a: [n], c: [ ], b: [1..n 1] Chuyn (tm) n 1 tng t a qua b. Hnn(n 1, a, b)
(a: [ ], c: [n], b: [1..n 1]) sau chuyn (tm) tng cn li
ca a qua c = 6 a b.
a 6 a b
...
(a: [1..n-1], c: [n], b: [ ]) Ri li chuyn (tm) n 1 tng t b
qua a nhm gii phng v tr ch b...
Hnn(n 1, b, a)
(a: [1..n-1], c: [ ], b: [n]) chuyn tng ln nht n t c qua
b.
6 a b b
(a: [ ], c: [ ], b: [1..n]) Cui cng chuyn n 1 tng t a
qua b l hon tt.
Hnx(n 1, a, b)

(* Pascal *)
(**************************************
Hano.pas H Ni Ngc
Chuyn php ngc chiu kim ng h.
*************************************)
uses crt;
var d: longint;
f: text;
procedure hnn(n,a,b: byte);
begin
if n = 0 then exit;
if a = (b mod 3)+1 then
begin {b ke a}
hnn(n-1,a,6-a-b);
inc(d);
writeln(f,d,'. ',a,' -> ',b);
hnn(n-1,6-a-b,b);
end
else {b cach a qua vi tri c}
begin
hnn(n-1,a,b);
inc(d);
writeln(f,d,'. ',a,' -> ',6-a-b);
hnn(n-1,b,a);
inc(d);
writeln(f,d,'. ',6-a-b,' -> ',b);
hnn(n-1,a,b);
end;
end;
procedure runhnn(n: byte);
begin
d := 0;
Sng to trong Thut ton v Lp trnh Tp I

267



assign(f,'hnn.out');
rewrite(f);
writeln('-----------------');
hnn(n,1,2);
writeln(f,'Total: ',d,' step(s)');
close(f);
readln;
end;
BEGIN
runHnn(3);
END.

Kt qu:
1. 1 -> 3
2. 3 -> 2
3. 1 -> 3
4. 2 -> 1
5. 3 -> 2
6. 1 -> 3
7. 3 -> 2
8. 1 -> 3
9. 2 -> 1
10. 1 -> 3
11. 2 -> 1
12. 3 -> 2
13. 2 -> 1
14. 3 -> 2
15. 1 -> 3
16. 3 -> 2
17. 1 -> 3
18. 2 -> 1
19. 3 -> 2
20. 1 -> 3
21. 3 -> 2
Total: 21 step(s)
Nhn xt
Mi xem ta c cm tng rng li gi Hnn(3,1,2) v Hnx(3,1,2) chuyn thp
3 tng t cc 1 sang cc 2 phi cho cng mt s bc chuyn cc tng l 15. Tuy nhin, li gi
Hnn(3,1,2) cho ta 21 bc chuyn cc tng, trong khi li gi Hnx(3,1,2) ch cn 15
bc chuyn cc tng.
Suy ngm mt cht bn s gii thch c nghch l ny.
Hy th gi H Ni ngc chuyn thp 3 tng t cc 3 sang cc 2:
Hnn(3,3,2)
Ta s thy ch cn 15 bc!!!
Li gi H Ni xui chuyn thp 3 tng t cc 1 sang cc 3:
Hnx(3,1,3)
Ta li thy 21 bc.
Nh vy, Hnx v Hnn l i xng lch. Nu hai cc, ngun v ch k nhau th s
ln chuyn thp 3 tng s l 15. Ngc li, khi hai cc khng k nhau th s ln
chuyn thp 3 tng s l 21. Hai cc 1 v 2 l k nhau i vi thp H Ni xui nhng
khng k nhau i vi thp H Ni ngc. Tng t, hai cc 3 v 2 l k nhau i vi
thp H Ni ngc nhng khng k nhau i vi thp H Ni xui.
Ta nhn xt rng: nu ly hai s a, b khc nhau bt k trong ba s 1, 2 v 3 th gia a v
b ch xy ra mt trong hai trng hp loi tr nhau sau y:
b = (a mod 3) +1, hoc a = (b mod 3)+1
Do , quan h k nhau trong hai bi ton Thp H Ni xui v ngc l ph nh
i vi nhau.
Sng to trong Thut ton v Lp trnh Tp I

268



H Ni xui H Ni ngc
b = (a mod 3)+1 a v b k nhau a v b khng k nhau
a = (b mod 3)+1 a v b khng k nhau a v b k nhau
Quan h k nhau trong hai bi ton
thp H Ni xui v ngc
// C#
using System;
namespace SangTao1
{
/*------------------------------------
* Thap Ha Noi Nguoc
* -----------------------------------*/
class ThapHaNoiNguoc
{
static int d = 0;
static void Main()
{
Console.WriteLine("\n Ha Noi Nguoc ");
HaNoiNguoc(3, 1, 2);
Console.WriteLine("\n Total: " + d
+ " steps");
Console.ReadLine();
} // Main
static void HaNoiNguoc(int n, int a, int b)
{
if (n == 0) return;
if (a == (b % 3) + 1)
{
HaNoiNguoc(n - 1, a, 6 - a - b);
Console.WriteLine((++d) + ". " +
a + " -> " + b);
HaNoiNguoc(n - 1, 6 - a - b, b);
}
else // b c a, c = 6-a-b
{
HaNoiNguoc(n - 1, a, b);
Console.WriteLine((++d)+". "+a+
" -> "+(6-a-b));
HaNoiNguoc(n - 1, b, a);
Console.WriteLine((++d)+". "+
(6-a-b)+" -> "+b);
HaNoiNguoc(n - 1, a, b);
}
}
} // ThapHaNoiNguoc
} // SangTao1
Bi 8.8. Thp H Ni thng
Sng to trong Thut ton v Lp trnh Tp I

269



Ni dung ging nh bi ton thp H Ni c ch sa li quy tc (2) nh sau: (2)
Mi ln ch c chuyn 1 tng thp t mt cc sang cc k n, khng c
vng t 3 sang 1 hay 1 sang 3.
iu kin ny quy nh bn php chuyn 1 tng thp nh sau:
C,C , C C, C C
hoc, theo cch biu din khc:
C C
tc l ch c chuyn qua li gia hai cc k nhau. Gi thit l cc cc c
sp thnh hng nh sau:

Hy tm cch gii bi ton vi s ln chuyn t nht.
Bi gii
Ging nh phn tch trong cc bi ton H Ni trc, ta c:
- Hnh trng xut pht: (a:[1..n], b:[ ], c:[ ])
-
- Hnh trng kt thc: (a:[ ], b:[1..n], c:[ ])
- Hnh trng buc phi c: (a:[n], b:[ ], c:[1..n 1])
Ta phn bit hai trng hp:
- Hai cc a v b ng k nhau trn ng thng.
- Hai cc a v b cch nhau qua c.
Trng hp th nht Nu v tr cc cc c b tr nh sau
C C
th gia a v b c bn tnh hung, c th l:

Tnh hung
C C
1 a b
2 b a
3 a b
4 b a
Thp H Ni thng
c t a v b k nhau abs(a b) = 1
Trng hp ny c c t l

abs(a-b) = 1

Hnh trng ngha Lnh
(a: [1..n], b: [ ], c: [ ]) Hnh trng ban u vi v tr b
k v tr a trn ng thng.
abs(a b) = 1

C C
Sng to trong Thut ton v Lp trnh Tp I

270



chuyn n tng t a sang b
theo ng thng ta phi...
...
(a: [n], b: [ ], c: [1..n 1]) Chuyn (tm) n 1 tng t a
qua c = 6 a b.
Hnt(n 1, a, 6 a b);
(a: [ ], b: [n], c: [1..n 1]) sau chuyn tng cn li ca
a qua b.
a b
...
(a: [ ], b: [1..n], c: [ ]) Cui cng chuyn n 1 tng
t c = 6 a b qua b l hon
tt.
Hnt(n 1, 6 a b, b);


Trng hp th hai a v b cch nhau qua c trn ng thng. Ta c c = 2 v ch c
hai tnh hung cho a v b nh sau:


Hnh trng ngha Lnh
(a: [1..n], c: [ ], b: [ ]) Hnh trng ban u vi v tr b
khng k vi v tr a trn ng
thng.
abs(a b) = 1
Ta c c = 2.
chuyn n tng t a sang b
cch qua v tr c = 2 ta phi...

...
(a: [n], c: [ ], b: [1..n 1] Chuyn (tm) n 1 tng t a qua
b.
Hnt(n 1, a, b)
(a: [ ], c: [n], b: [1..n 1]) sau chuyn (tm) tng cui
ca a qua c = 2.
a 2
...
(a: [1..n-1], c: [n], b: [ ]) Ri li chuyn (tm) n 1 tng
t b qua a nhm gii phng v tr
ch b.
Hnt(n 1, b, a)
(a: [1..n-1], c: [ ], b: [n]) chuyn tng ln nht n t c =
2 qua b.
2 b
(a: [ ], c: [ ], b: [1..n]) Cui cng chuyn n 1 tng t a
qua b l hon tt.
Hnt(n 1, a, b)

(* Pascal *)
(****************************
HNT.PAS Ha Noi thang
Chuyen n tang thap tu coc a
sang coc b theo duong thang
1->2, 2->1 hoac 2->3, 3->2
1 2 3
****************************)
Tnh hung
C C
1 a c b
2 b c a

Sng to trong Thut ton v Lp trnh Tp I

271



uses crt;
var d: longint;
f: text;
procedure Hnt(n,a,b: byte);
begin
if n = 0 then exit;
if abs(a-b) = 1 then
begin
Hnt(n-1,a,6-a-b);
inc(d);
writeln(f,d,'. ',a,' -> ',b);
Hnt(n-1,6-a-b,b);
end
else
{-----------------------------
abs(a-b)=2 tuc la a = 1, b = 3
hoac a = 3, b = 1, do do c=2
------------------------------}
begin
Hnt(n-1,a,b);
inc(d);
writeln(f,d,'. ',a,' -> 2');
Hnt(n-1,b,a);
inc(d);
writeln(f,d,'. 2 -> ',b);
Hnt(n-1,a,b);
end;
end;
procedure runHnt(n: byte);
begin
d := 0;
assign(f,'hnt.out');
rewrite(f);
writeln('-----------------');
Hnt(n,1,2);
writeln(f,'Total: ',d,' step(s)');
close(f);
readln;
end;
BEGIN
runHnt(3);
END.
Kt qu
1. 1 -> 2
2. 2 -> 3
3. 1 -> 2
4. 3 -> 2
5. 2 -> 1
6. 2 -> 3
7. 1 -> 2
8. 2 -> 3
9. 1 -> 2
10. 3 -> 2
Sng to trong Thut ton v Lp trnh Tp I

272



11. 2 -> 1
12. 3 -> 2
13. 1 -> 2
Total: 13 step(s)
// C#
using System;
namespace SangTao1
{
/*------------------------------------
* Thap Ha Noi Thang
* -----------------------------------*/
class ThapHaNoiThang
{
static int d = 0;
static void Main()
{
Console.WriteLine("\n Ha Noi Thang");
HaNoiThang(3, 1, 2);
Console.WriteLine("\n Total: " +
d + " steps");
Console.ReadLine();
} // Main
/*------------------------------------
Ha Noi Thang
* -----------------------------------*/
static void HaNoiThang(int n, int a, int b)
{
if (n == 0) return;
if (Math.Abs(a - b) == 1)
{
HaNoiThang(n - 1, a, 6 - a - b);
Console.WriteLine((++d)+
". "+a+" -> "+b);
HaNoiThang(n - 1, 6 - a - b, b);
}
else // a c b, b c a, c = 6-a-b
{
HaNoiThang(n - 1, a, b);
Console.WriteLine((++d)+
". "+a+" -> "+(6-a-b));
HaNoiThang(n - 1, b, a);
Console.WriteLine((++d)+
". "+(6-a-b)+" -> "+b);
HaNoiThang(n - 1, a, b);
}
}
} // ThapHaNoiThang
} // SangTao1
Bi 8.9. Thp H Ni sc mu (H Ni Cu vng)
Ngi ta sn mi tng thp mt mu v quy nh lut chuyn cho mi loi tng
theo mu nh m t trong bng sau.
Sng to trong Thut ton v Lp trnh Tp I

273



K hiu Mu ngha chuyn tng Quy tc
x xanh xui chiu kim ng h
C C
n nu ngc chiu kim ng h
C C
t trng thng
C C
h hng t do (h ni kinh in)
C C
Ngoi ra, d nhin vn phi theo quy nh l tng to khng c t ln trn
tng nh.
Hy tm cch gii bi ton vi s ln chuyn t nht.
Th d, vi cc tng thp c t mu t trn (tng nh nht) xung di (tng ln
nht) l:


xanh
nu
xanh
hng
trng
H Ni sc mu 5 tng xnxht
v cn chuyn thp t cc 1 sang cc 2 th phi thc hin ti thiu 31 ln chuyn cc
tng nh sau:
1. 1 -> 2
2. 1 -> 3
3. 2 -> 3
4. 1 -> 2
5. 3 -> 1
6. 3 -> 2
7. 1 -> 2
8. 1 -> 3
9. 2 -> 3
10. 2 -> 1
11. 3 -> 1
12. 2 -> 3
13. 1 -> 2
14. 1 -> 3
15. 2 -> 3
16. 1 -> 2

17. 3 -> 1
18. 3 -> 2
19. 1 -> 2
20. 3 -> 1
21. 2 -> 3
22. 2 -> 1
23. 3 -> 1
24. 3 -> 2
25. 1 -> 2
26. 1 -> 3
27. 2 -> 3
28. 1 -> 2
29. 3 -> 1
30. 3 -> 2
31. 1 -> 2
Total: 31 step(s)

Bi gii
iu l th l th tc H Ni sc mu l kh tng qut v ta c th dng n gi
cho cc bi ton v thp H Ni xt. Bng di y cho bit cch s dng th tc
Hnm cho cc trng hp ring.
Mun gi Th gi Ch thch
Hn(n,a,b)
s := 'hhh';
Hnm(length(s),a,b);
s cha n k t 'h'
Hnx(n,a,b)
s := 'xxx';
Hnm(length(s),a,b);
s cha n k t 'x'
Sng to trong Thut ton v Lp trnh Tp I

274



Hnn(n,a,b)
s := 'nnn';
Hnm(length(s),a,b);
s cha n k t 'n'
Hnt(n,a,b)
s := 'ttt';
Hnm(length(s),a,b);
s cha n k t 't'
Ta quy c d liu ban u c m t trong bin tng th kiu xu k t s vi khai
bo nh sau:
var s: string
Trong th d trn, s s c gn tr l
s := 'xnxht';
Khi c th khai bo th tc thp H Ni sc mu nh sau:
procedure Hnm(n: byte; a,b: byte);
trong n l s tng thp, a v b l hai cc khc nhau cho trc v nhn cc gi tr 1, 2
hoc 3.
Ta vit thm th tc runHnm(Thap: string) t chc li gi thun tin cho
bi ton H Ni sc mu nh sau.
Tham bin Thap kiu string s cha m t c th cho cc tng thp. Th d, li
gi
runHnm('xnxht');
s x l thp 5 tng, tnh t trn xung, tc l t tng nh nht c m s 1 n tng y,
tng ln nht mang m s 5 nh sau:
Tng (i) Mu (Thap[i])
1 'x'
2 'n'
3 'x'
4 'h'
5 't'
Gi th tc cho bi
H Ni Sc mu
runHnm('xnxht')
Cch m s ny ngc vi quy tc gi cc tng trong i thng. Ngi ta thng
m s cc tng ca to nh t di ln l 1, 2,
Vi li gi
runHnm(Thap:string);
th gi tr ca tham tr Thap s c truyn cho mt bin tng th s:
s := Thap;
Sau l li gi c th Hnm theo s tng thp length(s), cc ngun (ni t tng
thp ban u) a = 1 v cc ch, ni cn chuyn thp n, b = 2.
Hnm(length(s),1,2);
S d phi dng mt bin tng th s lu li cu hnh thp v ta mun hn ch tn
km pht sinh trong li gi quy ca th tc Hnm.
Sng to trong Thut ton v Lp trnh Tp I

275



Nu khai bo Hnm vi bn tham bin nh sau:
procedure Hnm(Thap: string; n,a,b: byte);
th r rng l s tn km hn.
Bin tng th d c khi tr 0 s c dng m s bc chuyn cc tng thp.
procedure runHnm(Thap:string);
begin
s := Thap;
d := 0;
assign(f,'hnm.out');
rewrite(f);
writeln('-----------------');
Hnm(length(s),1,2);
writeln(f,'Total: ',d,' step(s)');
close(f);
readln;
end;
BEGIN
runHnm('txhxn');
END.
Mi khi x l mt tng thp i, ta xem
mu s[i] ca tng v la chn quyt nh
nh trong bng sau
Ta nhn xt rng, trong mi tnh
hung, tc l vi mi mu khc nhau ca
tng thp, khi hai cc a v b k nhau th ta
cn thc hin cc thao tc nh nhau,
c th l:

Vy ta ch cn c t tnh cht k
gia hai cc a v b l xong.
Ta thy, da theo lut chuyn, vi thp H Ni c, hai cc a v b khc nhau ty
c xem l k nhau. Vi thp H Ni xui, cc b phi ng st cc a theo chiu kim
ng h:
b = (a mod 3)+1
Vi thp H Ni
ngc, b phi ng st
a theo chiu quay
ngc ca kim ng
h. Ni cch khc, a
phi ng st b theo chiu kim ng h:
a = (b mod 3)+1
Vi thp H Ni thng, nh ta bit, gi tr ca a v b phi lch nhau ng 1 n
v:
Nu s[i] c mu Th x l nh th
tc
'x' hnx
'n' hnn
't' hnt
'h' hn
Phng thc x l cho bi ton
H Ni sc mu
Gi th tc ngha
Hnm(n 1, a, 6 a b) Chuyn n 1 tng trn cng t a
qua c = 6 a b
a b Chuyn tng cui cng t a sang
b
Hnm(n 1, 6 a b, b) Chuyn n 1 tng thp t c = 6
a b qua b
H Ni sc mu
Chuyn thp trong trng hp a v b k nhau
Sng to trong Thut ton v Lp trnh Tp I

276



abs(a-b) = 1
Bng di y m t cc trng hp trn.

Bi ton K hiu iu kin a k b
(a = b)
Minh ho
H Ni C h Lun ng (True)
CC
C,C,C,C
CC,CC
H Ni Xui x b = (a mod 3) + 1
C C
C, CC, C
H Ni Ngc n a = (b mod 3) + 1
C C
C, CC, C
H Ni Thng t
abs(a b) = 1 C C
C, C, CC, CC
H Ni sc mu
Cc iu kin k gia hai cc a v b
a, b = 1, 2, 3; a = b
Hm Ke (k) khi s c m t nh sau.
function Ke(n,a,b: byte): Boolean;
begin
case s[n] of
'x': ke := (b = (a mod 3)+1);
'n': ke := (a = (b mod 3)+1);
't': Ke := (abs(a-b) = 1);
'h': Ke := True;
end {case};
end;
Tng t, khi hai cc a v b khng k nhau ta cng thc hin cc thao tc nh
nhau.
Bit hm Ke, ta da vo cc thut ton ring cho mi trng hp vit phng n
cho bi ton H Ni sc mu nh sau:
(*----------------------------------------
Ha Noi sac mau
x: xanh - xuoi chieu kim dong ho
n: nau - nguoc chieu kim dong ho
t: trang - chuyen thang
h: hong - chuyen tu do
---------------------------------------*)
procedure Hnm(n: byte; a,b: byte);
begin
if n = 0 then exit;
if Ke(n,a,b) then
begin
Hnm(n-1,a,6-a-b);
inc(d);
writeln(f,d,'. ',a,' -> ',b);
Hnm(n-1,6-a-b,b);
end else
begin
Sng to trong Thut ton v Lp trnh Tp I

277



Hnm(n-1,a,b);
inc(d);
writeln(f,d,'. ',a,' -> ',6-a-b);
Hnm(n-1,b,a);
inc(d);
writeln(f,d,'. ',6-a-b,' -> ',b);
Hnm(n-1,a,b);
end;
end;
(* Pascal *)
(**************************************
HNM.PAS Thp H Ni mu
x xanh: Xui chiu kim ng h
n nu: Ngc chiu kim ng h
t Trng: thng theo hng ngang
h H Ni c: kinh in
****************************************)
uses crt;
var d: longint; {dem so buoc chuyen}
f: text; {output file}
s: string; {cau hinh thap}
{----------------------------------------
Kiem tra tinh chat ke giua 2 coc a va b
-----------------------------------------}
function Ke(n,a,b: byte): Boolean;
begin
case s[n] of
'x': ke := (b = (a mod 3)+1);
'n': ke := (a = (b mod 3)+1);
't': Ke := (abs(a-b) = 1);
'h': Ke := True;
end {case};
end;
(*----------------------------------------
Ha Noi sac mau
x: xanh - xuoi chieu kim dong ho
n: nau - nguoc chieu kim dong ho
t: trang - chuyen thang
h: hong - chuyen tu do
---------------------------------------*)
procedure Hnm(n: byte; a,b: byte); t vit
{-------------------------------
To chuc goi thu tuc Hnm
------------------------------}
procedure runHnm(Thap:string);
begin
s := Thap;
d := 0;
assign(f,'hnm.out');
rewrite(f);
writeln('-----------------');
Sng to trong Thut ton v Lp trnh Tp I

278



Hnm(length(s),1,2);
writeln(f,'Total: ',d,' step(s)');
close(f);
readln;
end;
BEGIN
runHnm('txhxn');
END.

// C#
using System;
namespace SangTao1
{
/*------------------------------------
* Thap Ha Noi
* -----------------------------------*/
class ThapHaNoi
{
static int d = 0;
static char[] s = new char[64];
static void Main()
{
Console.WriteLine("\n Ha Noi Sac Mau");
RunHaNoiSacMau("xnxht", 1, 2);
Console.WriteLine("\n Total: " +
d + " steps");
Console.ReadLine();
} // Main
static bool Ke(char KieuThap, int a, int b)
{
switch (KieuThap)
{
case 'x': return (b == (a % 3) + 1);
case 'n': return (a == (b % 3) + 1);
case 't': return (Math.Abs(a - b) == 1);
}
return true;
}
/*-------------------------------------
Ha Noi sac mau
x: xanh - xuoi chieu kim dong ho
n: nau - nguoc chieu kim dong ho
t: trang - chuyen thang
h: hong - chuyen tu do
---------------------------------------*/
void HaNoiSacMau(int n, int a, int b)
{
if (n == 0) return;
if (Ke(s[n], a, b))
{
HaNoiSacMau(n - 1, a, 6 - a - b);
Sng to trong Thut ton v Lp trnh Tp I

279



Console.WriteLine((++d)+
". ("+s[n]+") "+a+" -> "+b);
HaNoiSacMau(n - 1, 6 - a - b, b);
}
else
{
HaNoiSacMau(n - 1, a, b);
Console.WriteLine((++d)+
". ("+s[n]+") "
+a+" -> "+(6-a-b));
HaNoiSacMau(n - 1, b, a);
Console.WriteLine((++d)+
". ("+s[n]+")"
+(6-a-b) +" -> "+b);
HaNoiSacMau(n - 1, a, b);
}
}
static void RunHaNoiSacMau(string w,
int a, int b)
{
d = 0;
w.CopyTo(0, s, 1, w.Length);
HaNoiSacMau(w.Length, a, b);
}
} // ThapHaNoi
} // SangTao1

Hng dn kim th
Ta s dng k thut i snh kim th cc trng hp.
Ta chn v c nh cc gi tr n, a v b. Chng hn, n = 4, a = 1, b = 2.
Khi ta c:
RunHn(n) v RunHnm('hhhh') cho cng kt qu.
RunHnx(n) v RunHnm('xxxx') cho cng kt qu.
RunHnn(n) v RunHnm('nnnn') cho cng kt qu.
RunHnt(n) v RunHnm('tttt') cho cng kt qu.
Nu ghi cc kt qu ny vo cc tp tng ng, sau gi th tc i snh tng
cp hai tp tng ng th c th kim nh c mt s trng hp.
xy dng cc tnh hung kim th khc nhau cn li bn n cc tnh cht
thun nghch ca cc th tc khc nhau. Th d, nh phn tch phn trn, cc li
gi Hnx(3,1,2) v Hnn(3,3,1) pht sinh cng mt s ln chuyn.
Bn hy th pht hin thm s tng ng gia cc li gi Hnm vi cc tham tr
khc nhau.

Sng to trong Thut ton v Lp trnh Tp I

280




c thm
Lc s

Mt s bi ton v thp H Ni c a vo cc k thi Olympic Tin hc
ti mt s quc gia. Chng ta th tm hiu ci ngun ca cc bi ton thuc
loi ny.
Nm 1883, trn mt t bo Paris c ng bi m t mt tr chi ton hc
ca gio s Claus vi tn l Thp H Ni. Ni dung tr chi c mi ngi
say m lm th chnh l bi ton Thp H Ni c.
Thi th Paris dn chng x nhau mua chi ny v sut
ngy ngi chuyn thp. Trong lch s v cc tr chi thng minh tng c
nhng cn st nh vy. Tnh trung bnh mi th k c mt vi cn st tr chi.
Th k th XX c cn st Rubic, th k XIX l cc tr chi 15 v thp H Ni.
Bi ton ny ni ting n mc tr thnh kinh in trong cc gio trnh v thut
gii quy v c trnh by trong cc thng bo chnh thc ca cc phin
bn chun ca cc ng trnh nh ALGOL-60, ALGOL-68, Pascal, Delphy, C,
C++, Ada,... khi mun nhn mnh v kh nng quy ca cc ngn ng .
Theo nh nghin cu Henri De Parville cng b vo nm 1884 th tc gi
ca tr chi thp H Ni c tn tht l nh ton hc Eduard Lucas, ngi c
nhiu ng gp trong lnh vc s lun. Mi khi vit v ti gii tr th ng i
tn l Claus. Bn c rng Claus l mt hon v cc ch ci ca t Lucas.
De Parville cn k rng bi ton thp H Ni bt ngun t mt tch truyn
k n . Mt nhm cao tng n gio c giao trng trch chuyn dn
64 a vng gia ba cc kim cng theo cc iu kin ni bi ton Thp
H Ni c. Khi no hon tt cng vic, tc l khi chuyn xong to thp vng 64
tng t v tr ban u sang v tr kt thc th cng l thi im tn th. S vic
ny c xy ra hay khng ta s xt bi tp 8.10.
Li gii c cng b u tin cho bi ton thp H Ni l ca Allardice v
Frase, nm 1884.
Nm 1994 David G. Poole i hc Trent, Canada vit mt bi kho
cu cho t Mathematics Magazine s thng 12 nhan "V cc thp v cc
tam gic ca gio s Claus" cng vi mt ph "Pascal bit H Ni". Poole
lit k 65 cng trnh kho cu bi ton thp H Ni ng trn cc tp ch
ton-tin trong khong mi nm. Tc gi cng ch ra s lin quan gia cc
cng thc tnh s ln chuyn cc tng thp v mt phng php quen bit
dng tnh cc h s ca dng khai trin nh thc Newton (a + b)
n
. Phng
php ny c gi l Tam gic Pascal, mang tn nh ton hc kim vt l hc
Php Blaise Pascal (1623-1662), ngi ch to chic my tnh quay tay u
tin trn th gii.
Mt s nh nghin cu trong v ngoi nc c bn lun v a danh
H Ni. Theo ti vn ny vn cn ng. Hu ht cc bi vit xoay quanh
ti chuyn thp ni trn u dng thut ng bi ton thp H Ni. Khi gii thiu
v bi ton H Ni nhiu thp Dudeney t tn l bi ton ca Reve (The
Reve's Puzzle). Tuy nhin, nhiu nh nghin cu cho rng tt hn c l nn
t tn v phn loi theo tn nguyn thu ca bi ton, ngha l Thp H Ni.
Ngoi cc dng Thp H Ni lit k phn trn mt s tc gi cn
xut nhng dng kh k l, chng hn nh bi ton sau y.
Sng to trong Thut ton v Lp trnh Tp I

281



H Ni nhiu thp
Trong tr chi ny ngi ta lm thm nhng cc, chng hn thay v ba ta dng bn
cc v cng c th b tr thp ti nhiu cc. kin ny do H.E. Dudeney, mt tc gi
hng u v ton hc gii tr ngi Anh a ra vo nm 1908. c nhiu bi ng li
gii cho bi ton ny, c nhng bi mi xut hin gn y vo nhng nm 1988 v
1989. D vy cha ai chng minh c r rng s ln chuyn ca bi gii l ti thiu
nh lm vi cc dng thp H Ni khc.

Bi tp
Bn hy th lp cng thc tnh s ln chuyn cc tng ti thiu cho cc bi ton
sau:
Thp H Ni,
Thp H Ni Xui,
Thp H Ni Ngc v
Thp H Ni Thng.
Li cm n Cc t liu trn v mt s t liu khc trong bi c trch dn t cc
bi vit ca gio s vin s Nguyn Xun Vinh, Khoa K thut khng gian, i hc
Michigan, cng tc vin NASA, Hoa K. Tc gi xin chn thnh cm n gio s cho
php trch dn v ch gio v cc phng php truyn th tri thc khoa hc cho gii tr.

NXH
8/4/2008
Sa ngy 4/4/09



Sng to trong Thut ton v Lp trnh Tp I

282



Nguyn Xun Huy
sng to trong
thut ton
v lp trnh
vi C#, Pascal

tuyn cc bi ton tin nng cao
cho hc sinh v sinh vin gii

Tp mt


Li gii thiu
Sch trnh by c h thng cc ph-ng php thit
k thut ton minh ha qua cc bi ton thi hc
sinh gii v Olimpic hc sinh v sinh vin trong
n-c, khu vc v quc t. Cc bi ton u -c
phn tch y km theo thut ton v ton vn
ch-ng trnh vit trn ngn ng C# v Pascal.
Sch l ti liu b ch cho hc sinh trung hc,
gio vin cc tr-ng ph thng v cao ng v
sinh vin cc tr-ng i hc mun hon thin kin
thc tham d cc k thi Olimpic Tin hc quc
gia v quc t.
Cc ch-ng trnh song ng Pascal v C# gip cho
bn c chuyn i nhanh chng sang cc mi
tr-ng lp trnh tin tin.

You might also like