You are on page 1of 282

T SCH TRI THC DUY TN

NGUYN XUN HUY

SNG TO
TRONG THUT TON
V
LP TRNH
vi ngn ng Pascal v C#
Tp 1

Tuyn cc bi ton Tin nng cao


cho hc sinh v sinh vin gii

Sng to trong Thut ton v Lp trnh Tp I

MC LC

Chng I
Bi 1.1.

Li ni u

GII MT BI TON TIN


S thn thin

1
2

Bi 1.2.

S cp cng

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
Bi 2.1.

SINH D LIU VO V RA
Sinh ngu nhin theo khong

27
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
Bi 3.1.

BN PHM V MN HNH
Bng m ASCII

79
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
Bi 4.1.

T CHC D LIU
Cm

107
107

Bi 4.2.

Bi gp

112

Bi 4.3.

Chui ht

120

Sng to trong Thut ton v Lp trnh Tp I

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
Bi 5.1.

PHNG PHP THAM LAM


Bng nhc

153
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
Bi 6.1.

PHNG PHP QUAY LUI


Tm Hu

193
195

Bi 6.2.

T chun

207

Bi 6.3.

Tm ng trong m cung

216

Chng VII
Bi 7.1.
Bi 7. 2.
Bi 7.3.
Bi 7.4.

QUY HOCH NG
Chia thng
Palindrome
Cm hoa
Tm cc ng ngn nht

227
228
235
243
253

Chng VIII
Bi 8.1.
Bi 8.2.
Bi 8.3.
Bi 8.4.
Bi 8.5.
Bi 8.6.
Bi 8.7.
Bi 8.8.
Bi 8.9.

SUY NGM
Lt nn
Ch s cui khc 0
Hnh ch nht ti i trong ma trn 0/1
Ma phng
Thp H Ni c
Thp H Ni xui
Thp H Ni ngc
Thp H Ni thng
Thp H Ni sc mu (H Ni Cu vng)

267
267
276
281
291
308
311
316
321
325

Sng to trong Thut ton v Lp trnh Tp I

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

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

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

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

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

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

14

Sng to trong Thut ton v Lp trnh Tp I

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 9.
H thc 2 cho php ta tnh gii hn trn ca d:

ad 2 9
d 9/a
V d l s nguyn nn ta phi c d 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.

(*

Pascal

Cn trn d

*)

(*---------------------------Cac so tu nhien 3 chu so


lap thanh cap nhan

Sng to trong Thut ton v Lp trnh Tp I

------------------------------*)
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

15

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, a2,...,an, 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

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

20

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, a2,...,an, 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

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

22

Sng to trong Thut ton v Lp trnh Tp I

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)
{

23

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

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

25

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

(*

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);

27

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

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

30

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

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;

32

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

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");
}

35

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

(*

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)

37

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: n2.

(*

Pascal

*)

Sng to trong Thut ton v Lp trnh Tp I

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)

40

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 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 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,n1,..,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;

45

Sng to trong Thut ton v Lp trnh Tp I

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:

S
7 4 2
Tm im gy: i = 3, v s[3] < s[4]
7 4 2
Tm im vt: j = 7, v s[7] > s[3]
7 4 2
7 4 3
i ch im gy v im vt: s[3] s[7]
Lt on s[4..8]
7 4 3
Quy trnh hot ng ca hm Next
74286531 74312568

(*

Pascal

8
8
8
8
1

6
6
6
6
2

5
5
5
5
5

*)

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;

3
3
3
2
6

1
1
1
1
8

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

49

Sng to trong Thut ton v Lp trnh Tp I

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
3

Thut ton

4
7

5
1

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
using
using
using

System;
System.Collections.Generic;
System.Text;
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

52

Sng to trong Thut ton v Lp trnh Tp I

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

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;
}
1 1 1 1 0 0 1 1
static void
0 0 0 0 0 0 1 1
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

53

1
1

Sng to trong Thut ton v Lp trnh Tp I

54

Mt tp vn bn c tn fn c ghi s
1 1 0 0 0 0 0 0 0
mt vng bin hnh ch nht chiu ngang
1 1 0 0 1 1 0 0 1
250 k t, chiu dc (s dng) khng hn
5 tu
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

*)

A 0 0 0 0 0
program Ships;
{$B-}
0 1 1 1 1 1
uses crt;
0 1 1 1 1 1
const MN = 250;
boong = '1'; nuoc = '0';
D 0 0 0 0 0
Function Dem(fn: string):
integer;
Con tu ABCD
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;

Sng to trong Thut ton v Lp trnh Tp I

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)

55

56

Sng to trong Thut ton v Lp trnh Tp I

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 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

57

Sng to trong Thut ton v Lp trnh Tp I

[2+10,7*6)
[2+10,7)
(2,7+5]

[
[
(

2
2
2

+
+
BL

10
10
0

7
7
7

*
BL
+

6
0
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

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;

60

Sng to trong Thut ton v Lp trnh Tp I

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])

61

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

int
int
int
int
for
{

n = -1;
q = 0; // trang thai
i = 0; // bien tro trong s
dau, cuoi;
(; 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;

63

Sng to trong Thut ton v Lp trnh Tp I

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

64

Sng to trong Thut ton v Lp trnh Tp I

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

65

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

67

Sng to trong Thut ton v Lp trnh Tp I

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, (C) : #3, (Pch): #6, (Nhp): #5.
8

68

Sng to trong Thut ton v Lp trnh Tp I

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.

69

Sng to trong Thut ton v Lp trnh Tp I

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
DX
DY
TX

DOS
9
12
2

9
6
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',

70

Sng to trong Thut ton v Lp trnh Tp I

'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

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;

71

Sng to trong Thut ton v Lp trnh Tp I

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,

72

73

Sng to trong Thut ton v Lp trnh Tp I

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

74

Sng to trong Thut ton v Lp trnh Tp I

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;

75

Sng to trong Thut ton v Lp trnh Tp I

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

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

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

77

Sng to trong Thut ton v Lp trnh Tp I

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

78

Sng to trong Thut ton v Lp trnh Tp I

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: ');

79

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

(*

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

81

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

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:

83

84

Sng to trong Thut ton v Lp trnh Tp I

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
const int
const int
const int

scot = 20; // Toa do


sdong = 8; // Toa do
dcot = 5; // Kh cach
ddong = 2; // Khoang

cot goc
dong goc
giua 2 o tren dong
cach dong

Sng to trong Thut ton v Lp trnh Tp I

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];

85

86

Sng to trong Thut ton v Lp trnh Tp I

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

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;

87

Sng to trong Thut ton v Lp trnh Tp I

}
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
case
case
case
case
case

ConsoleKey.RightArrow: return PHAI;


ConsoleKey.LeftArrow: return TRAI;
ConsoleKey.DownArrow: return XUONG;
ConsoleKey.UpArrow: return LEN;
ConsoleKey.End: return END;
ConsoleKey.Escape: return ESC;
}

}
return 0;
}
} // Game15
} // space

88

89

Sng to trong Thut ton v Lp trnh Tp I

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

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

91

Sng to trong Thut ton v Lp trnh Tp I

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)
{

92

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: Kt qu hin th trn ngha: b bi c 10 qun m s ln lt 1,
BAIGOP.INP
2,, 10 v c 10 ngi chi. Su ln trng ti
mn hnh
chn ngu nhin cc cp s (x, y) l (2, 5),
10 6
5
(3, 3), (4, 7), (1, 5), (2, 8) v (9, 3). Cui vn
2 5
chi cn li 5 ngi c bi trn tay: {1, 2, 5, 8},
3 3
{3, 9}, {4, 7}, {6}, {10}.
4 7
1 5
2 8
9 3

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

95

Sng to trong Thut ton v Lp trnh Tp I

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)

2
(B)

3
(A)

3
(A)

2
(B)

(6)

(7)

(8)

3
(A)

(9)

(10)

(11)

2
(B)

(12)

(13)

(14)

(15)

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)
3

(8)

(9)
2

(10)

(11)

(12)

(13)

(14)

(15)

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.

97

Sng to trong Thut ton v Lp trnh Tp I

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)

10

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

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()
{

98

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:

100

Sng to trong Thut ton v Lp trnh Tp I

4
4
1
5
5
5

S mu trong chui: 5
Ct gia ht th 7 v th 8, tng s ln nht l 7.

7
4
8
8
8

8
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

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]

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 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

106

Sng to trong Thut ton v Lp trnh Tp I

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
4
4
7
1
4
5
8
5
8
5
8
8

// C#
using System;
using System.IO;
namespace SangTao1
{
class ChuoiHat
{

Kt qu d kin

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

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

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#

110

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)
{

112

Sng to trong Thut ton v Lp trnh Tp I

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;
for (j = i + 1;
if (a[j] <
{ t = a[i]; a[i] =

++i)
j < n; ++j)
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

113

Sng to trong Thut ton v Lp trnh Tp I

= 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 N 500, 1 k 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]

abdecd

[3]

[3]

bdecda

[6]

[4]

decdab

[1]

[5]

ecdabd

[4]

[6]

cdabde

[5]

Sp ch dn cc xu th cp
Thut ton QuickSort sp nhanh cc xu th cp do Hoare xut c phc tp
N.log2N 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

(*------------------------------------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;

115

Sng to trong Thut ton v Lp trnh Tp I

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}

116

Sng to trong Thut ton v Lp trnh Tp I

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";

117

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;

120

Sng to trong Thut ton v Lp trnh Tp I

}
}
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
cabxabcdab
abcd
cdaeh

STRINGS.OUT
cabxabcdab
abcd
5 4
cdaeh
7 3

Thut ton
Vi mi xu k t w ta k hiu w[i..j], i 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

121

Sng to trong Thut ton v Lp trnh Tp I

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

S[9..10]

ab

S[5..10]

abcdab

S[2..10]

abxabcdab

10

S[10..10]

S[6..10]

bcdab

S[3..10]

bxabcdab

S[1..10]

cabxabcdab

S[7..10]

cdab

S[8..10]

dab

10

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

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

124

Sng to trong Thut ton v Lp trnh Tp I

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;

125

126

Sng to trong Thut ton v Lp trnh Tp I

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
cabxabcdab
abcd
cdaeh

//

Kt qu d kin
STRINGS.OUT
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

}
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

129

130

Sng to trong Thut ton v Lp trnh Tp I

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.
BANGNHAC.INP BANGNHAC.OUT
Th d di y cho bit c N = 3 bi ht:
3
2 2
- Bi 1 pht trong thi gian 7 pht.
7 2 3
3 5
- Bi 2 pht trong thi gian 2 pht.
1 12
- Bi 3 pht trong thi gian 3 pht.
19
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

Thi gian pht

Ta xt vi tnh hung ghi bng rt ra kt lun cn thit.

Sng to trong Thut ton v Lp trnh Tp I

Trt t ghi trn bng


(x, y, z)

131

Thi gian pht


t(x) + t(y) + t(z); t(i): thi gian tm v pht bi i

( , , )

(7) + (7 + 2) + (7 + 2 + 3) = 28 pht

( , , )

(7) + (7 + 3) + (7 + 3 + 2) = 29 pht

( , , )

(2) + (2 + 7) + (2 + 7 + 3) = 23 pht

( , , )

(2) + (2 + 3) + (2 + 3 + 7) = 19 pht (phng n ti u)

( , , )

(3) + (3 + 7) + (3 + 7 + 2) = 25 pht

( , , )

(3) + (3 + 2) + (3 + 2 + 7) = 20 pht

Vy phng n ti u s l ( , , ): 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

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";

132

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

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;

136

Sng to trong Thut ton v Lp trnh Tp I

(*------------------------------------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

137

Sng to trong Thut ton v Lp trnh Tp I

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

138

Sng to trong Thut ton v Lp trnh Tp I

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;

139

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
BALO.OUT
C N = 5 vt v sc cha ti a ca ba l l
M = 30 (kg).
5 30
8
8 5
- Vt th nht c trng lng 8, n gi 5
3
tr/kg,
5 4
0
- Vt th hai c trng lng 5, n gi 4,
4 2
3

141

Sng to trong Thut ton v Lp trnh Tp I

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.

16
172

(tr. - triu ng)


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:

145

Sng to trong Thut ton v Lp trnh Tp I

(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

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()
{

148

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];

150

Sng to trong Thut ton v Lp trnh Tp I

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 di, 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
5
4
10, 5, 4, 4, 3. Cn thc hin 4 ln trn, mi ln 2 tp.
10
5 3 6
Ln th nht: trn tp 5 vi tp 3 ghi vo tp 6.
5
4 2 7
Ln th hai: trn tp 4 vi tp 2 ghi vo tp 7.
4
6 7 8
Ln th ba: trn tp 6 vi tp 7 ghi vo tp 8.
4
1 8 9
Ln th t: trn tp 1 vi tp 8 ghi vo tp 9.
3
58
Tng s ln ghi l 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 ( ) nh sau:
Bc 1: Trn tp vi tp 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 ghi vo tp . S thao tc ghi s l 6 + 2 = 8 v tp
c 8 phn t.
Kt qu thu c tp . 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.

156

Sng to trong Thut ton v Lp trnh Tp I

Phng n

Quy trnh thc hin

Tng s thao tc ghi tp

( )

2(5 + 1) + 2 = 2.6 + 2 = 14

( )

2(5 + 2) + 1 = 2.7 + 1 = 15

( )

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

(:10,:5,:4,:4,:3)

:3 , :4

(:10,:5,:4,:7)

:5 , :4

(:10,:7, : 9)

:7 , :9

16

(:10,: 16)

:10 , :16

26

Kt
qu

(: 26)

58

Minh ho thut ton Huffman vi d liu vo


(:10,:5,:4,:4,: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.

157

Sng to trong Thut ton v Lp trnh Tp I

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:

16

26

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

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

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
* --------------------------*/

160

Sng to trong Thut ton v Lp trnh Tp I

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;

161

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.

163

Sng to trong Thut ton v Lp trnh Tp I

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)
Khi tr v: v tho P;
repeat
if (v tho Q) then
begin
Ghi nhn nghim;
exit;

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;

Sng to trong Thut ton v Lp trnh Tp I

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;

164
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)
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;

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 (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

169

Sng to trong Thut ton v Lp trnh Tp I

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

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 }

170

Sng to trong Thut ton v Lp trnh Tp I

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

171

Sng to trong Thut ton v Lp trnh Tp I

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];

172

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 N 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

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

177

Sng to trong Thut ton v Lp trnh Tp I

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);

178

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;

182

Sng to trong Thut ton v Lp trnh Tp I

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:
9
1
1
0
0
0
0
0
1

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

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:

MECUNG.OUT
5
6 4 2 3 7

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

183

Sng to trong Thut ton v Lp trnh Tp I

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.

8
7

41

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.

Sng to trong Thut ton v Lp trnh Tp I

(*

Pascal

184

*)

(*---------------------------------------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

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

189

Sng to trong Thut ton v Lp trnh Tp I

{
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

190

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.

2.

3.

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.
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.
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 m, n 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:

192

Sng to trong Thut ton v Lp trnh Tp I

Phng n

10

11

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

193

Sng to trong Thut ton v Lp trnh Tp I

i<j

Chia(i, j) = Chia(i, i)

ij

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(ij,j);
end;

Phng n ny chy chm v pht sinh ra qu


nhiu
ln gi hm trng lp. Bng di y lit k s
9 1 1 0
0
ln gi hm Chia khi gii bi ton chia thng vi by
9 2 1 0
9
phn thng (m = 7) v 4 hc sinh (n = 4). Th d, hm
6 1 0 0
6
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
5 2 1 1
5
tn km.
3 1 1 0
3
Lm tt ln 1: Phng n 1 kh d trin khai nhng
2 1 0 0
2
chng trnh s chy rt lu, bn hy th gi
Chia(66,32) tri nghim c iu trn. Din t
1 0 0 0
1
quy thng trong sng, nhn tn, nhng khi thc hin s
1 1 1 1
1
sinh ra hin tng gi lp li nhng hm quy. Ci tin
S ln gi hm Chia cc b
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
khi tnh hm Chia(,)
vo khc nhau v in vo mt mng hai chiu cc.
Mng cc c m t nh sau:

j-1
i-j
...

j
[i-j,j]
...

Sng to trong Thut ton v Lp trnh Tp I

194

const
[i,j-1]
[i,j]
i
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:

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 = ...

197

Sng to trong Thut ton v Lp trnh Tp I

// 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:
PALIN.INP
PALIN.OUT
Dng u tin l gi tr n, 1 n 1000.
9
4
Dng th hai l n k t ca dy vit lin
baeadbadb
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

198

Sng to trong Thut ton v Lp trnh Tp I

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 n2 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 nrec(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));

199

Sng to trong Thut ton v Lp trnh Tp I

end;
j-1

b a e

i
i+1

b 1 1 1

a 0 1 1

[i,j-1]

[i,j]

e 0 0 1

[i+1,j-1]

[i+1,j]

a 0 0 0

d 0 0 0

b 0 0 0

a 0 0 0

d 0 0 0

b 0 0 0

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: ',nQHD2DV);
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 k n 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
1
9
7

6
1
1
2

6 4
4 7
6 10

3 10
2 7
2 3

24
1 3 4 6

204

Sng to trong Thut ton v Lp trnh Tp I

6 10

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 }

205

Sng to trong Thut ton v Lp trnh Tp I

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:

j 1

i1

[i-1,j-1]

[i,j-1]

[i,j]?

T(i,j) = max {T(i-1,j-1) +


v[i,j],T(i,j-1)}
o
o

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, j1] th ta phi thc hin hai thao tc:

t li tr T[i, j]:= T[i-1, j-1] + v[i, j].


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[i1, 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.

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 n.
Giai on 2: Duyt nt n - k l hoa cn li.

Sng to trong Thut ton v Lp trnh Tp I

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 }

207

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.

212

Sng to trong Thut ton v Lp trnh Tp I

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
0
4
0
0
0
1
0

2
0
0
0
0
0
0
0

0
1
0
0
0
0
0

0
0
0
0
3
0
1

0
0
0
0
0
0
0

0
0
0
2
0
0
0

4
0
5
1
0
0
5
0

1
6

5
3

7
1

3
2

1
4

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
DIJ.OUT
i: 2 1.
4 2 1
- ng ngn nht t nh 2 n nh 2: khng c (thc ra,
0
theo l thng l c ng chiu di 0).
1 2 3
- ng ngn nht t nh 2 n nh 3 c chiu di 1, cch
3 2 3 7 4
i: 2 3.
- ng ngn nht t nh 2 n nh 4 c chiu di 3, cch
0
i: 2 3 7 4.
5 2 3 7 4 6
- ng ngn nht t nh 2 n nh 5: khng c.
2 2 3 7
- 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 i 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?

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 n2.
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;

216

Sng to trong Thut ton v Lp trnh Tp I

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

befor
e

65535

65535

65535

65535

a
0
4
0
0
0
1
0

0
0
0
0
0
0
0

0
1
0
0
0
0
0

0
0
0
0
3
0
1

0
0
0
0
0
0
0

0
0
0
2
0
0
0

0
5
1
0
0
5
0

217

Sng to trong Thut ton v Lp trnh Tp I

65535

65535

Bc lp k = 1
i = min = vi p[] = 0.
Cc nh cha x l v k vi nh s c sa trng s l 1, 3 v 7 (c du ).
V p[] + a[, 1] = 0 + 4 = 4 < p[1] = 65535 nn p[1] c sa thnh 4 v
before[1] c sa thnh .
V p[] + a[, 3] = 0 + 1 = 1 < p[3] = 65535 nn p[3] c sa thnh 1 v
before[3] c sa thnh .
V p[] + a[, 7] = 0 + 4 = 5 < p[7] = 65535 nn p[7] c sa thnh 5 v
before[7] c sa thnh .
nh
d
p
before
0
65535/4 0/2
1

0/1 0
0
0
65535/1 0/2
3
4
0
65535
0
5
0
65535
0
6
0
65535
0
0
65535/5 0/2
7
Bc lp k = 2
i = min = vi p[] = 1.
nh cha x l v k vi nh s c sa trng s l nh 7.
V p[] + a[, 7] = 1 + 1 = 2 < p[7] = 5 nn p[7] c sa thnh 2 v
before[7] c sa thnh .
nh
1

4
5
6
7

d
0
0/1
0/1
0
0
0
0

p
65535/4
0
65535/1
65535
65535
65535
65535/5/2

before
0/2
0
0/2
0
0
0
0/2/3

Bc lp k = 3
i = min = 7 vi p[] = 1
nh cha x l v k vi nh 7 s c sa trng s l nh 4.
V p[] + a[, 4] = 2 + 1 = 3 < p[4] = 65535 nn p[4] c sa thnh 3 v
before[4] c sa thnh .
nh
d
p
before
1
0
65535/4
0/2

0/1 0
0

0/1 65535/1
0/2
0
65535/3
0/7
4
5
0
65535
0
6
0
65535
0

0/1 65535/5/2 0/2/3


Bc lp k = 4

218

Sng to trong Thut ton v Lp trnh Tp I

i = min = 4 vi p[] = 3.
nh cha x l v k vi nh s c sa trng s l nh 6.
V p[] + a[, 6] = 3 + 2 = 5 < p[6] = 65535 nn p[6] c sa thnh 5 v
before[6] c sa thnh .
nh

before

65535/4

0/2

0/1

0/1

65535/1

0/2

0/1

65535/3

0/7

65535

65535/5

0/4

0/1

65535/5/2

0/2/3

Bc lp k = 5
i = min = vi p[] = 4.
Khng c nh cha x l no k vi nh .
nh

before

0/1

65535/4

0/2

0/1

0/1

65535/1

0/2

0/1

65535/3

0/7

65535

65535/5

0/4

0/1

65535/5/2

0/2/3

Bc lp k = 6
i = min = vi p[] = 5.
Khng c nh cha x l no k vi nh . Ch rng nh 7 k vi nh
nhng nh 7 ny x l ri.
nh

before

0/1

65535/4

0/2

0/1

0/1

65535/1

0/2

0/1

65535/3

0/7

65535

0/1

65535/5

0/4

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:
nh d
p
before
V p[4] = 3 nn di ng i l 3.
1
1 4
2
gii trnh vt ca ng i t 2 n 4 ta da
2
1 0
0
vo mng before[1..7] nh sau:
1 1
2
V before[4] = 7, tc l trc khi n nh 4 phi 3
qua nh 7 nn ta c
4
1 3
7
74
5
0 65535 0
V before[7] = 3, tc l trc khi n nh 7 phi
6
1 5
4
qua nh 3 nn ta c
7
1 2
3
374
V before[3] = 2, tc l trc khi n nh 3 phi qua nh 2 nn ta c
2374
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

Sng to trong Thut ton v Lp trnh Tp I

{
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;

220

Sng to trong Thut ton v Lp trnh Tp I

}
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++];
}

221

Sng to trong Thut ton v Lp trnh Tp I

// Hien thi
static void
// hien thi
static void
} // Dijkstra
} // SangTao1

du lieu
Show() t vit
mang
Print(int[] a, int n) t vit

222

223

Sng to trong Thut ton v Lp trnh Tp I

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 = 2k, (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.

a) Nn nh

b) Gch lt

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.

224

Sng to trong Thut ton v Lp trnh Tp I

Th d, vi n = 8 ta c mt cch lt nn nh
sau:

NEN.INP

NEN.OUT

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;

16 3
3 3 1
3 2 2
1 2 3
1 1 3
3 3 1
3 2 1
1 2 2
1 1 3

1 1

2 1

3 3

1
1
3
2
2
1
3
3

2
3
1
1

3
3
2
1

1
2
2
3

1
1
3
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
3 1 2 2 3 1 1
nn nh c biu din di dng mt mng hai
2 1 1 3 3 2 1
chiu a: ba trong hnh vung 2 2 s c
2 2 3 1 2 2 3
in gi tr 1, nm gc trn phi c in
gi tr 2 (phn t m, hnh 6). Gi hnh c
1 3 3 1 1 3 3
khi tr l A. Mi bc tip theo ta thc hin ba
Hnh 3. Nn nh vi n = 8
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).

3
3
1
1

3 2

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.

225

Sng to trong Thut ton v Lp trnh Tp I

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]

a[n,1]

:=

1; a[n,2]

:=
:=

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
nv+1

...

n1

...

Hnh 7. Hnh vung a cnh v c chn


bin hnh
B

A
nv+
1
...

n1

...

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).

226

Sng to trong Thut ton v Lp trnh Tp I

(*--------------------------------------------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;

nv+
1
...

n1

...

Hnh 9. Lt A qua phi thu c C


3

nv+1

...

n1

1 2 ... v
Hnh 10. Lt A ln trn thu c D
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).

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 n2, 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

{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

228

Sng to trong Thut ton v Lp trnh Tp I

(*-------------------------------------------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();
}

229

Sng to trong Thut ton v Lp trnh Tp I

// 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)

230

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.2d2-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 2m 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 2m 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). 28mod 10 =
= ((k mod 10) . (28 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 2m 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; {= 24 mod 10}
LuyThua[1] = 2; {= 21 mod 10}
LuyThua[2] = 4; {= 22 mod 10}
LuyThua[3] = 8; {= 23 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 pK 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! = 211.53.C.
Chng minh iu ny kh d, bn ch cn vit dy 1.2N thnh cc dng, mi
dng p tha s
1

p+1

2p

k1p = N!

Vy l trong tch 1N cha K1 tha s p. Trong tch


1K1 s cha K1 : p tha s p.
Bi T2. Phn tch N! ra tha s nguyn t.
Th d, 15! = 211.36.53.72.11.13.

236

Sng to trong Thut ton v Lp trnh Tp I

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 M 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.

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

237

Sng to trong Thut ton v Lp trnh Tp I

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 M 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
20
bcccddddeabcvvvvvvvb
bbbbbccccccccccbbbbb
vvvvvcccccccccccccbb
vvcccccccccccccbbbbb
pppppccccccccccabbbb
pppppcccccccccczzzzz
ssccccccccccccczzzzz
sssssccccccccccccczz
hhhhhcccccccccczzzzz
uuuuuuuuczzzzzzzzzzz

CNMAX.OUT
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

238

Sng to trong Thut ton v Lp trnh Tp I

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 }
1

10

11

12

13

14

15

16

17

18

19

20

4 x

5 y

dng

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.

239

Sng to trong Thut ton v Lp trnh Tp I

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.

2.
3.
4.
5.

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.
Mt con m dng d kiu longint cho bit ta ang x l dng no ca tp.
Dng x lc u c khi tr ton du cch l k t khng c trong vn bn th
hin tm bn .
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.
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 m2 php
duyt. Tng cng, vi n dng ta thc hin ti a t = n.m2 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.

244

Sng to trong Thut ton v Lp trnh Tp I

Ma phng bc n l mt bng s hnh vung, mi cnh n cha cc s t 1 n n2 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

16

13

11

10

12

14

15

(a)

(b)

(a) ma phng bc 3, c s S3 = 15
(b) ma phng bc 4, c s S4 = 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):
Sn = (1 + 2 + ... + n2)/n = n(n2 + 1)/2.
Theo cc th d trn ta c:
c s ca ma phng bc 3: S3 = 3(9 + 1)/2 = 15.
c s ca ma phng bc 4: S4 = 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.

245

Sng to trong Thut ton v Lp trnh Tp I

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+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 n2 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).

246

Sng to trong Thut ton v Lp trnh Tp I

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

k+1

k+1

ng-Nam

C
ng

B
k+1

k+1
k

C
Nam

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}

247

Sng to trong Thut ton v Lp trnh Tp I

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 n2 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

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

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
----------------------------------*)

253

Sng to trong Thut ton v Lp trnh Tp I

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;}
}

254

Sng to trong Thut ton v Lp trnh Tp I

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

255

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)

257

Sng to trong Thut ton v Lp trnh Tp I

{
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

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.

258

Sng to trong Thut ton v Lp trnh Tp I

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

260

Sng to trong Thut ton v Lp trnh Tp I

{
/*-----------------------------------*
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:


, hoc , hoc .
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:[ ])

261

Sng to trong Thut ton v Lp trnh Tp I

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

th gia a v b c ba tnh hung, c th l


Tnh hung

2
3

a
b

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
(a: [1..n], b: [ ], c: [ ])

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

ngha

Lnh

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...
Chuyn (tm) n 1 tng t a qua c
= 6 a b.
sau chuyn tng cn li ca a
qua b.

Hnx(n1, a, 6 a
b)
ab

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);

262

Sng to trong Thut ton v Lp trnh Tp I

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

a
b

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

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: [1..n], c: [ ], b: [ ])

...
(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.

a6ab

(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.

6abb

(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);

263

Sng to trong Thut ton v Lp trnh Tp I

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.
2.
3.
4.
5.
6.
7.
8.

1
2
1
3
2
1
2
1

->
->
->
->
->
->
->
->

2
3
2
1
3
2
3
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: "

264

Sng to trong Thut ton v Lp trnh Tp I

+ 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:
, hoc , hoc .
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
1

a
b

Thp H Ni ngc
c t a v b k nhau a = (b mod 3) + 1

265

Sng to trong Thut ton v Lp trnh Tp I

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
(a: [1..n], b: [ ], c: [ ])

ngha

Lnh

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.

ab

Cui cng chuyn n 1 tng t c = 6


a b qua b l hon tt.

Hnn(n 1, 6
a b, b)

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

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
1

2
3

a
b

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:

266

Sng to trong Thut ton v Lp trnh Tp I

Hnh trng

ngha

Lnh

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: [1..n], c: [ ], b: [ ])

...
(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.

a6ab

(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.

6abb

(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;

267

Sng to trong Thut ton v Lp trnh Tp I

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.

268

Sng to trong Thut ton v Lp trnh Tp I

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

269

Sng to trong Thut ton v Lp trnh Tp I

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:
, , ,
hoc, theo cch biu din khc:

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

th gia a v b c bn tnh hung, c th l:


Tnh hung

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
(a: [1..n], b: [ ], c: [ ])

ngha
Hnh trng ban u vi v tr b
k v tr a trn ng thng.
abs(a b) = 1

Lnh

270

Sng to trong Thut ton v Lp trnh Tp I

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.

ab

Cui cng chuyn n 1 tng


t c = 6 a b qua b l hon
tt.

Hnt(n 1, 6 a b, b);

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

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

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

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


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

Pascal

Lnh

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: [1..n], c: [ ], b: [ ])

(*

Tnh hung

Chuyn (tm) n 1 tng t a qua


b.
sau chuyn (tm) tng cui
ca a qua c = 2.

Hnt(n 1, a, b)

Ri li chuyn (tm) n 1 tng


t b qua a nhm gii phng v tr
ch b.
chuyn tng ln nht n t c =
2 qua b.
Cui cng chuyn n 1 tng t a
qua b l hon tt.

Hnt(n 1, b, a)

*)

(****************************
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
****************************)

a2

2b
Hnt(n 1, a, b)

Sng to trong Thut ton v Lp trnh Tp I

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

271

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.

273

Sng to trong Thut ton v Lp trnh Tp I

K hiu
x
n
t
h

Mu
xanh
nu
trng
hng

ngha chuyn tng


xui chiu kim ng h
ngc chiu kim ng h
thng
t do (h ni kinh in)

Quy tc

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
Hn(n,a,b)
Hnx(n,a,b)

Th gi

Ch thch

s := 'hhh';
Hnm(length(s),a,b);

s cha n k t 'h'

s := 'xxx';
Hnm(length(s),a,b);

s cha n k t 'x'

274

Sng to trong Thut ton v Lp trnh Tp I

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.

275

Sng to trong Thut ton v Lp trnh Tp I

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:

Nu s[i] c mu
'x'

Th x l nh th
tc
hnx

'n'

hnn

't'

hnt

'h'

hn

Phng thc x l cho bi ton


H Ni sc mu

Vy ta ch cn c t tnh cht k
gia Gi
hai cc
v b l xong.
th atc
ngha
Ta thy, da theo lut chuyn, vi thp H Ni c, hai cc a v b khc nhau ty
Hnm(n 1, a, 6 a b)
Chuyn n 1 tng trn cng t a
c xem l k nhau. Vi qua
thpcH
Ni xui, cc b phi ng st cc a theo chiu kim
=6ab
ng h:
ab

Chuyn tng cui cng t a sang

b
Hnm(n 1, 6 a b, b)

b = (a mod 3)+1

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

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:

276

Sng to trong Thut ton v Lp trnh Tp I

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

K hiu

H Ni C

iu kin a k b
(a b)
Lun ng (True)

H Ni Xui

b = (a mod 3) + 1

H Ni Ngc

a = (b mod 3) + 1

H Ni Thng

abs(a b) = 1

Minh ho

,,,
,

, ,

, ,

, , ,

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

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('-----------------');

277

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
n
dng tnh cc h s ca dng khai trin nh thc Newton (a + b) . 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.

281

Sng to trong Thut ton v Lp trnh Tp I

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

282

Sng to trong Thut ton v Lp trnh Tp I

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