Nh− vËy biÕt kÕt hîp víi nghiÖm tèi −u cña c¸c nghiÖm tr−íc ®ã th× viÖc t×m kiÕm nghiÖm tiÕp theo ®−îc nhanh chãng h¬n... (Mét sè bµi tËp tèi − u hµm môc tiªu cña nghiÖm..[r]
(1)Chuyên đề ph−ơng pháp duyệt
I / ý nghÜa :
Trong nhiều tr−ờng hợp , nghiệm tốn d∙y có thứ tự tập hợp phần tử đ−ợc xác định khơng theo luật tính tốn định, muốn tìm nghiệm phải thực b−ớc ,tìm kiếm dần phần tử nghiệm Để tìm phần tử (còn gọi đề cử) phải kiểm tra điều kiện chấp nhận phần tử
Những ý duyệt:
ã Nu phn tử xét bị loại bỏ chuyển sang chọn phần tử khác (ch−a đ−ợc chọn ) Chú ý: chọn phần tử thơng th−ờng trạng thái tốn thay đổi tr−ớc chuyển sang chọn phần tử khác, phải trả lại trạng thái nh− tr−ớc chọn phần tử vừa bị loại bỏ (gọi quay lui lại trạng thái cũ )
• Nếu phần tử đ−ợc chọn ch−a phần tử cuối tìm phần tử • Nếu phần tử cuối nghiệm và:
a) Nếu toán yêu cầu nghiệm Hiện nghiệm hẳn khỏi thủ tục đệ qui b) Nếu tốn u cầu tìm tất nghiệm Hiện nghiệm
c) Nếu toán yêu cầu tìm nghiệm tốt So tối −u Nghĩa tìm đ−ợc nghiệm, ta so sánh với nghiệm tốt đ∙ tìm đ−ợc tr−ớc nghiệm (gọi nghiệm tối −u tạm thời) Nếu nghiệm vừa tìm đ−ợc tốt nghiệm tối −u tạm thời gán lại nghiệm tối −u tạm thời nghiệm vừa tìm đ−ợc Quá trình tiếp diễn duyệt hết nghiệm toán ta đ−ợc nghiệm tối −u (cuối cùng) tốn
• Trong xem xét chọn phần tử nghiệm biết tìm điều kiện để nhanh chóng loại bỏ đ−ợc phần tử duyệt nhanh chóng Việc chọn thử phần tử nghiệm giống nh− ng−ời đ−ờng, đến ng∙ N-đ−ờng , lần l−ợt chọn đ−ờng thích hợp đ−ờng ng∙ N-đ−ờng đó, biết chắn đ−ờng đ−ờng ng∙ N-đ−ờng đ−ờng “cụt” tới đích ng−ời đ−ờng loại đ−ờng đó; ng−ợc lại nhìn thấy tr−ớc điều kiện cho phép cần theo số đ−ờng định N đ−ờng mà tới đích nhanh chóng ng−ời đ−ờng dùng điều kiện nh− “la bàn “ ph−ơng h−ớng Tất nhiên khẳng định điều “đúng” ,điều “sai” phải thận trọng.Nếu khẳng định” chắn” điều “ngộ nhận” bỏ sót số đ−ờng tới đích, chệch h−ớng khơng thể tới đích Một đánh giá vừa “táo bạo” vừa “chắc chắn” th−ờng đến với học sinh giỏi
II Hai kĩ thuật duyệt duyệt không biến đổi quan hệ đối t−ợng Duyệt theo chiều rộng - Breadth first search
(2)Khởi trị đỉnh ch−a thăm: d[i] := ∀i
procedure BFS_visit(i : integer); (* Bắt đầu thăm từ đỉnh i *) var x,y : integer;
begin
dau := 0; cuoi := 1;
inc(cuoi); (* Nạp phần tử i vào đầu hàng đợi q *) q[cuoi] := i;
while dau<cuoi (* Trong hàng đợi phần tử ch−a đ−ợc xem xét *) begin
inc(dau);
x := q[dau]; (* Lấy phần tử đầu hàng đợi để xem xét *) for y:=1 to n do (* Duỵệt chọn đỉnh ch−a xét y kề với đỉnh x*) if (a[x,y]=1) and (not d[y]) then
begin
d[y] := true; (* Đánh dấu đ∙ xét đỉnh y *)
t[y] := x; (* Ghi nhận tr−ớc đỉnh y đỉnh x*) inc(cuoi); (* Nạp đỉnh y vào cuối hàng đợi*)
q[cuoi] := y; end;
end; end;
procedure BFS; var x : integer; begin
for x:=1 to n
if not d[x] then BFS_visit(x); end;
(3)var y : integer; begin
d[x] := true; for y:=1 to n
if (not d[y]) and (a[x,y]=1) then DFS_visit(y); end;
procedure DFS; var x : integer; begin
for x:=1 to n
if not d[x] then DFS_visit(x); end;
III Ba dạng duyệt thờng gặp tập Dạng : Tìm nghiệm
Procedure Tim(k : Integer); Begin
Vòng lặp xét đề cử b−ớc thứ k trình tìm kiếm nghiệm Begin
+ Thử chọn đề cử cho b−ớc k + Nếu đề cử chấp nhận đ−ợc Begin
* L−u trạng thái tr−ớc chọn đề cử * Ghi nhận giá trị đề cử;
* Ghi nhận trạng thái toán sau đề cử; * Nếu ch−a phải b−ớc cuối Tim(K+1)
Else {là bớc cuối cùng}
Hiện Nghiệm+Tăng số nghiệm; * Trả lại trạng thái toán tr−ớc đề cử;
End; End;
End;
(4)Cịng cã thĨ viÕt d−íi d¹ng sau : Procedure Tim(k : Integer); Begin
Nếu b−ớc k b−ớc sau b−ớc cuối Hiện nghiệm+Tăng số nghiệm ; Vòng lặp xét đề cử b−ớc thứ k trình tìm kiếm nghiệm
Begin
+ Thử chọn đề cử cho b−ớc k + Nếu đề cử chấp nhận đ−ợc Begin
* L−u trạng thái tr−ớc chọn đề cử * Ghi nhận giá trị đề cử;
* L−u trạng thái toán sau đề cử;
* Tim(k+1);
* Trả lại trạng thái toán tr−ớc đề cử; End;
End; End;
NÕu số nghiệm kết luận vô nghiệm
Thí dụ : Bài toán m tuần ( Hiện tất nghiệm) Program Madequy;
Uses Crt;
Const Max = 6;
Fi = 'madq.inp';
D : Array [1 8] of -2 = (-2,-2,-1,1,2,2,1,-1); C : Array [1 8] of -2 = (-1,1,2,2,1,-1,-2,-2); Var
F : Text;
T1,T2 : longint;
A : Array[1 Max,1 Max] of Integer; x,y,k,dem,n,nsq : Integer;
Procedure DocFi; Begin
Assign(F,Fi);
{$I-} Reset(F); {$I+} If Ioresult<>0 then
(5)Nsq := N*N; Readln(F,x,y); Close(F); End;
Procedure Hien; Var i,j : Integer; Begin
Inc(dem); Assign(F,Fi);
Append(F); {Ghi nghiÖm ci File d÷ liƯu Input } Writeln(F,'Nghiem thu ',dem);
For i:=1 to N Begin
For j:=1 to N Write(F,A[i,j]:3); Writeln(F); End;
Close(F); End;
Procedure Try(k:Integer;x,y: Integer); Var i,j,u,v : Integer;
Begin
If k > nsq then Hien Else For i:=1 to
Begin
u:=x+D[i]; v:=y+C[i];
If (u in [1 n]) and (v in [1 n]) and (A[u,v]=0) then Begin
A[u,v]:=k; try(k+1,u,v); A[u,v]:=0; End;
End; End;
BEGIN Clrscr;
Fillchar(A,Sizeof(A),0); dem:=0;
(6)D¹ng : T×m mét nghiƯm : Procedure Tim(k : Integer); Begin
NÕu Stop th× Exit;
Vòng lặp xét đề cử b−ớc thứ k trình tìm kiếm nghiệm Begin
+ Thử chọn đề cử cho b−ớc k + Nếu đề cử chấp nhận đ−ợc Begin
* L−u trạng thái tr−ớc chọn đề cử * Ghi nhận giá trị đề cử;
* Ghi nhận trạng thái toán sau đề cử; * Nếu ch−a phải b−ớc cuối Tim(K+1) Else {là b−ớc cuối cùng}
Begin
HiÖn nghiÖm ;
Stop := true; (đ đợc nghiÖm) Exit;
End;
* Trả lại trạng thái toán tr−ớc đề cử; End;
End; End;
Nếu not stop kết luận vô nghiệm Cịng cã thĨ viÕt d−íi d¹ng sau :
Stop:= False;
Procedure Tim(k : Integer); Begin
NÕu Stop th× Exit;
NÕu b−íc k lµ b−íc sau b−íc ci cïng th× Begin
(7)Stop := true; (xác nhận đ đợc nghiÖm) Exit;
End;
Vòng lặp xét đề cử b−ớc thứ k trình tìm kiếm nghiệm Begin
+ Thử chọn đề cử cho b−ớc k + Nếu đề cử chấp nhận đ−ợc Begin
* L−u trạng thái tr−ớc chọn đề cử * Ghi nhận giá trị đề cử;
* L−u trạng thái toán sau đề cử;
* Tim(k+1);
* Trả lại trạng thái toán tr−ớc đề cử; End;
End; End;
Nếu not stop kết luận vô nghiệm Dạng : Tìm nghiệm tối u
Có c¸ch th−êng dïng : C¸ch :
Procedure Tim(k : Integer); Begin
NÕu b−íc k bớc sau bớc cuối Begin
Nếu tìm đ−ợc nghiệm So sánh nghiệm với nghiệm tối −u tr−ớc để chọn lại nghiệm tối −u
End;
Vòng lặp xét đề cử b−ớc thứ k trình tìm kiếm nghiệm
( Chú ý nên so sánh với nghiệm l−u tối −u đ∙ có để thu hẹp diện đề cử )
Begin
+ Thử chọn đề cử cho b−ớc k + Nếu đề cử thoả m∙n tốn Begin
(8)* L−u trạng thái toán sau đề cử; * Tim(k+1);
* Trả lại trạng thái toán tr−ớc đề cử; End;
End; End;
NÕu sè nghiƯm b»ng th× kÕt luận vô nghiệm Cách :
Procedure Tim(k : Integer); Begin
Vòng lặp xét đề cử b−ớc thứ k trình tìm kiếm nghiệm ( Chú ý nên kết hợp với nghiệm l−u tối −u đ∙ có để thu hẹp diện đề cử ) Begin
+ Thử chọn đề cử cho b−ớc k + Nếu đề cử chấp nhận đ−ợc Begin
*L−u trạng thái toán tr−ớc ghi nhận đề cử * Ghi nhận giá trị đề cử;
* L−u trạng thái toán sau đề cử; * Nếu ch−a phải b−ớc cuối Tim(K+1) Else {là b−ớc cuối cùng}
Begin
So sánh nghiệm với nghiệm tối −u tr−ớcđể chọn lại nghiệm tối −u
End;
* Trả lại trạng thái toán tr−ớc đề cử End;
End; End;
NÕu sè nghiƯm b»ng th× kÕt ln v« nghiƯm
Thí dụ tốn du lịch : Tìm đ−ờng qua N thành phố , thành phố qua lần , cho tốn chi phí vận chuyển Mỗi nghiệm tốn véc tơ N thành phần d∙y tên có thứ tự chọn N thành phố Giả sử đ∙ tìm đ−ợc số nghiệm , nghiệm tốt có chí phí t−ơng ứng CPMax đồng , tìm tiếp nghiệm cịn lại Đặt tình ta xây dựng tới thành phần thứ i (i<N) nghiệm ,gọi CP2 tổng chi phí tối thiểu N-i thành phố lại , CP1 tổng chi phí qua i thành phố đ∙ chọn
Nếu đề cử b−ớc i mà CP1+CP2 > CPMax đề cử bị loại
(9)Bài toán ngời du lịch: Cho N thành phố , giá cớc phí vận chuyển từ thành phố i tới thành phố j Cij Yêu cầu :
File liệu vào DULICH.INP nh sau
Dòng đầu N , XP , Dich ( N số thành phố , XP : th/ phố xuất phát , Dich : th/phố đích ) N dịng tiếp theo: Số đầu dòng i , cặp số j Cij ma trận C(N,N)
File liệu ra DULICH.OUT
Dòng đầu: Liệt kê hành trình tốn chi phí qua đợc nhiều thành phố N thành phố ( Mỗi thành phố lần ) Hành trình XP kết thúc Dich
Dòng tiÕp theo: Tæng chi phÝ TEST :
DULICH.INP 10
10 6 10
10 2
8 7 10 1 3 10 2
10 DULICH.OUT
1
Bài chữa : Bài toán du lịch Uses Crt;
Const MN = 100; TF1 = 'DULICH.INP'; TF2 = 'DULICH.OUT'; Var F : Text;
C : Array[1 MN,1 MN] of Integer; KQ,LKQ : Array[1 MN] of Byte; D : Array[1 MN] of Boolean; N,Lcs,cs,xp,Dich : Byte;
Tong,LTong : LongInt; Procedure Batdau;
Begin
(10)FillChar(KQ,Sizeof(KQ),0); FillChar(LKQ,Sizeof(LKQ),0); End;
Procedure TaoF;
Var F : Text;
i,j,k : Byte; Begin
Write('Nhap so : ');Readln(N); Write('Nhap xuat phat : ');Readln(xp); Write('Nhap se toi : ');Readln(Dich); Assign(F,TF1);
ReWrite(F);
Writeln(F,N,' ',Xp,' ',Dich); Randomize;
For i:=1 to N Begin
Write(F,i:4); For j:=1 to N
Begin
k := Random(2); If i=j then k:=0;
If k=1 then Write(F,j:4,(Random(8)+1):2); End;
Writeln(F); End;
Close(F); End;
Procedure DocF;
Var i,j : Byte;
F : Text; Begin
Assign(F,TF1); Reset(F);
Readln(F,N,XP,Dich); While Not SeekEof(F) Begin
Read(F,i);
While Not Eoln(F) Begin
(11)End; End; Close(F);
Tong := 0; LTong:= MaxInt div 2; cs := 1; KQ[cs] := xp;
D[xp] := True; End;
Procedure Hien; Var i,j : Byte; Begin
For i:=1 to n Begin
For j:=1 to N
If C[i,j]>0 then Write(C[i,j]:2) Else Write('*':2);
Writeln; End;
End;
Procedure Tim (i: Byte;Tong : LongInt); Var j : Byte;
Begin
For j:=1 to N
If (Not D[j]) and (i<>j) then
If (C[i,j]>0) and (Ltong-Tong>=C[i,j]) then Begin
Inc(cs); KQ[cs] := j; D[j] := True;
Tong := Tong + C[i,j]; If (j<>dich) then Tim(j,Tong) Else {Nếu Tới đích}
If (Tong<Ltong) or ((Tong=Ltong) and (cs>Lcs)) then Begin
Ltong := Tong; LKQ := KQ; Lcs := cs; End;
Dec(cs);
(12)Tong := Tong - C[i,j]; End;
End;
Procedure HienKQ; Var i : Byte; Begin
For i:=1 to Lcs Write(LKQ[i]:4); Writeln;
Writeln('Tong chi phi la : ',LTong); End;
BEGIN
Clrscr; {TaoF;} Batdau;
DocF; Nhonhat := Min; If XP= Dich then
Begin Writeln(Xp); Writeln(‘Khong di chuyen ‘);Readln;Halt;End; Tim(xp,Tong); {Hien;Chi goi N<=10}
Writeln; HienKq; Readln; END
(Một số tập tối −u hàm mục tiêu nghiệm Th−ờng đặt cận trên cận d−ới hàm mục tiêu Mỗi lần xây dựng đ−ợc nghiệm lại thu hẹp dần cận giúp q trình duyệt nhanh chóng hơn.) Ví dụ: Bài tốn tơ màu
procedure try(i:byte); var j :byte;
begin
if sm>=lsm then exit; for j:=1 to sm
if check(i,j) then {NÕu mµu j thâa mn tô màu} begin
mau[i]:=j;
(13)end;
if sm<lsm-1 then { Dïng mµu míi } begin
inc(sm); mau[i]:=sm;
if i<N then try(i+1) else toiuu; dec(sm);
end; end;
Bµi to¸n c¸i tói
Tìm cách chọn đồ vật N đồ vật (mỗi loại đồ vật chọn 1), xếp vào va li cho tổng giá trị đồ vật va ly lớn nh−ng tổng trọng l−ợng chúng không v−ợt giới hạn qui định LimW Giả sử N, Wi , Vi nguyên d−ơng ( Wi : trọng l−ợng vật i , Vi : giá trị vật i )
Dữ liệu vào : cho File VALY.INP tổ chức nh sau Dòng đầu : số N LimW
N dòng : Mỗi dòng số Wi Vi Dữ liệu : File VALY.OUT
Dòng ®Çu : sè LimW
Các dịng : Mỗi dòng số : i Wi Vi số hiệu, trọng l−ợng, giá trị đồ vật đ−ợc chọn vào va ly
uses crt;
const mn = 30; tf = 'valy.inp'; tf2 = 'valy.out'; type index = mn; dovat = record
w,v : integer; { w luong ,v gia tri } end;
var i,n : index;
a : array[index] of dovat; kq,lkq : set of index;
limw,can_d,can_t : integer; procedure docf;
(14)f : text; begin
assign(f,tf); reset(f);
readln(f,n,limw); for i:=1 to n with a[i] begin
readln(f,w,v);
can_t := can_t+v; { X©y dùng cËn trªn } end;
close(f); end;
procedure try(i : index;tw, v : integer); var v1 : integer;
begin
if tw + a[i].w <= limw then {điều kiện cần trọng lợng} begin
kq := kq+[i];
if i<n then try(i+1,tw+ a[i].w,v) else { đ∙ xét hết N đồ vật }
if v > can_d then {cận > cận dới nâng cận d−íi lªn} begin
can_d := v; lkq := kq; end;
kq := kq-[i]; end;
v1:= v - a[i].v; {kh«ng chän vËt i}
if v1>can_d then {nếu cận lớn cận dới} begin
if i<n then try(i+1,tw,v1) {đệ qui tiếp với cận v1} else
(15)can_d := v1; {n©ng cËn d−íi} lkq := kq;
end; end; end;
procedure ghif;
var i : index; f : text; begin
assign(f,tf2); rewrite(f);
writeln(f,can_d); for i:=1 to n if i in lkq then with a[i]
writeln(f,i:4,w:5,v:6); close(f);
end; begin docf;
can_d := 0; { Khëi t¹o cËn d−íi } try(1,0,can_t);
ghif;
writeln('da xong '); readln;
end
IV Duyệt theo chiều sâu có giới hạn độ sâu:
(16)VÝ dơ: T×m mét đờng dẫn từ trạng thái xuất phát tới trạng thái kết thúc:
Khởi trị đỉnh ch−a thăm: d[i] := ∀i procedure DFS_limit_depth_visit(x: integer); var y : integer;
begin
if dosau[x]>maxdosau then exit; d[x] := true;
for y:=1 to n
if (not d[y]) and (a[x,y]=1) then begin
dosau[y] := dosau[x] + 1; if (y=đỉnh đích) then begin
OK := true; exit;
end
else DFS_ limit_depth_visit(y); End;
end;
procedure DFS_limit_depth(dosaumax: integer); var x : integer;
begin
for x:=1 to n
if (x đỉnh xuất phát) then
if not d[x] then DFS_limit_depth_visit(x); end;
procedure solution; var x : integer; begin
maxdosau := -1; repeat
ok := false;
inc(maxdosau);
(17)until OK; end;
V Duyệt theo chiều rộng (hoặc chiều sâu) có kết hợp chọn mức độ −u tiên
Tinh thần chủ đạo kiểu duyệt là: Trong danh sách đề cử đỉnh i ta chọn số ứng sử viên có lực Muốn cần tăng giảm danh sách theo khố thích hợp Sau ta chọn số định phần tử đầu danh sách đ−ợc đóng vai trị đỉnh i
Nhận xét: Duyệt theo chiều sâu có giới hạn độ sâu định tìm đ−ợc nghiệm có nghiệm thời gian cho phép phần góp phần bảo đảm thời gian thực ch−ơng trình tốt duyệt theo chiều sâu bình th−ờng (vì khơng phải duyệt q sâu vào nhánh khơng có nghiệm)
Duyệt theo chiều rộng (hoặc chiều sâu) với mức độ −u tiên ph−ơng pháp heuristic, thời gian chạy nhanh nh−ng bỏ sót nghiệm khơng nghiệm tối −u số đề cử bị bỏ sót
VI Mét sè bµi tËp vỊ dut 1 Gard
2 Subtract 3 Bdbang 4 Danhca 5 Frame 6 Onion 7 Rebuss 8 WBR
9 Tháp Hà Nội 10.SqMagic