Thuật toán Loang và gắn nhãn

5 1.7K 71
Thuật toán Loang và gắn nhãn

Đang tải... (xem toàn văn)

Thông tin tài liệu

Thuật toán Loang và gắn nhãn

Kỹ thuật loang đổ mảng gán nhãn các đỉnhNguyễn Thành TrungTrong các số báo của ISM trước đây đã đề cập rất nhiều đến thuật toán tìm kiếm theo chiều rộng (BFS) có thể nói đó là một thuật toán tìm kiếm "mù", tức là quá trình tìm kiếm sẽ lập đi lập lại cho đến khi tìm được phương án. Như vậy, đòi hỏi một lượng lớn không gian lưu trữ thời gian thực hiện nhất là đối với những bài toán mà cây tìm kiếm gần như vô tận. Để khắc phục điều đó, chúng ta sẽ dùng kỹ thuật loang đổ mảng gán nhãn các đỉnh. Kỹ thuật đó giúp tránh được các trạng thái lặp cũng như các trạng thái mà chắc chắn không dẫn đến lời giải, từ đó giảm bớt không gian lưu trữ, tìm kiếm làm cho quá trình tìm kiếm "có tính dừng". Loang đổ mảng: trong quá trình loang, thường các bạn hay dùng một hàng đợi để lưu lại toàn bộ các trạng thái đã thăm chuẩn bị thăm. Nhưng ta chú ý loang là tìm kiếm theo mức, từ một mức khởi đầu sẽ sinh ra mức tiếp theo từ mức tiếp theo sẽ sinh ra mức tiếp theo nữa… Khi đó, mức đã được dùng để sinh không còn cần thiết nữa nghĩa là ta hoàn toàn có thể loại bỏ chúng ra khỏi hàng đợi để lấy "chỗ" cho các trạng thái sau. Từ ý tưởng trên, ta sẽ dùng 2 mảng khác thay thế cho 1 hàng đợi để lưu lại 2 mức liên tiếp nhau. Sau đây, chúng ta điểm qua 1 số bài toán tìm kiếm đầy thú vị: Bài 1: Chuyển biCậu bé vẽ N (N<=100) vòng tròn, đánh số từ 1 tới N tô màu các vòng tròn đó (có thể có các vòng tròn có màu giống nhau). Sau đó nối từng cặp lại bằng các cung định hướng, mỗi cung có một màu nhất định. Các màu (của cung của vòng tròn) được đánh số từ 1 đến 100. Cậu bé chọn 3 số nguyên khác nhau L, K Q nằm tong phạm vi từ 1 tới N, đặt vào trong các vòng tròn số L K mỗi vòng một hòn bi, sau đó bắt đầu di chuyển bi theo qui tắc sau: - Bi chỉ được chuyển theo cung có màu trùng với màu của vòng tròn chứa viên bi thứ 2. - Bi chỉ được chuyển theo chiều cung. - Hai viên bi không được đồng thời ở cùng một vòng tròn. - Quá trình di chuyển kết thúc, khi một trong hai viên bi tới vòng tròn Q. Hãy lập trình xác định cách di chuyển để chấm dứt quá trình sau một số ít nhất các bước chuyển. Dữ liệu: vào từ file BI.INP: - Dòng đầu: 4 số nguyên N L K Q - Dòng thứ 2: N số nguyên C1, C2, …, CN (Ci: là màu của vòng tròn i). - Dòng thứ 3: số nguyên M (0<=M<=10000). - M dòng sau: mỗi dòng 3 số nguyên Ai Bi Di xác định cung màu Di đi từ vòng tròn Ai tới vòng tròn Bi Các số trên một dòng cách nhau 1 dấu cách. Kết quả: đưa ra file BI.OUT: - Dòng đầu: YES hoặc NO cho biết quá trình có kết thúc được hay không. - Nếu dòng đầu là YES thì dòng 2 chứa số nguyên xác định số bước chuyển tối thiểu. Thật không khó để các bạn có thể giải quyết bài toán trên bằng thuật toán loang thông thường với điều kiện nghiệm phải ở một mức tìm kiếm cho phép, còn khi nghiệm ở một mức khá lớn hoặc vô nghiệm, chắc chắn chúng ta không thể biết được liệu phải cần một không gian lưu trữ lớn như thế nào liệu quá trình tìm kiếm có dừng hay không? Như vậy, nó làm mất đi tính tổng quát của một bài toán tin học. Để ý rằng, một trạng thái được ghi nhận là số thứ tự của 2 vòng tròn chứa 2 viên bi ta coi nó là một nút của cây tìm kiếm, ký hiệu (i,j). Gọi nhãn của một nút là f(i,j): f(i,j)=0 hoặc f(i,j)=1 cho biết nút đó chưa thăm hay đã thăm. Như vậy một nút sẽ được thăm nếu nó thỏa mãn mọi điều kiện của bài toán nhãn của nó có giá trị 0. Từ đó, ta suy ra rằng một mức sẽ có không quá n2 nút. Do vậy, ta sẽ dùng 2 mảng q1, q2 kích thước n*n để lưu lại các nút của 2 mức liên tiếp. Sau đây là toàn văn chương trình: const inp=’bi.inp’; out=’bi.out’; var a,q1,q2,f:array[1 100,1 100] of byte; c:array[1 100] of byte; n,v1,v2,v3:byte; m,dem:integer; stop:boolean; fi:text; procedure docf; var i,j,mau:byte; k:integer; begin assign(fi,inp); reset(fi); readln(fi,n,v1,v2,v3); for k:=1 to n do read(fi,c[k]); readln(fi); readln(fi,m); fillchar(a,sizeof(a),0); for k:=1 to m do begin readln(fi,i,j,mau); a[i,j]:=mau; end; close(fi); end; procedure initBFS; begin fillchar(f,sizeof(f),0) {khởi tạo tất cả các nút đều chưa thăm} fillchar(q1,sizeof(q1),0) {mức khởi đầu chưa có nút nào} fillchar(q2,sizeof(q2),0) { mức tiếp theo cũng chưa có nút nào} q1[v1,v2]:=1;q1[v2,v1]:=1; f[v1,v2]:=1;f[v2,v1]:=1; end; procedure inkq; begin writeln(fi,’YES’); writeln(fi,dem); close(fi); halt; end; procedure play; var i,j,k:byte; begin for i:=1 to n do for j:=1 to n do if q1[i,j]=1 then for k:=1 to n do if (k<>j) and (a[i,k]=c[j]) and (f[k,j]=0) then begin q2[k,j]:=1;q2[j,k]:=1; f[k,j]:=1;f[j,k]:=1; stop:=false; if k=v3 then inkq; end; end; procedure BFS; begin dem:=0; {bắt đầu ở mức 0} repeat inc(dem); stop:=true; play; if stop=false then begin q1:=q2; {ghi đè mức mới lên mức cũ} fillchar(q2,sizeof(q2),0); {khởi tạo mức mới chưa có nút nào} end; until stop; procedure xuly; begin assign(fi,out); rewrite(fi); initBFS; BFS; writeln(fi,’NO’); close(fi); end; begin docf; xuly; end. Qua chương trình trên, ta có thể thấy ngay rằng, quá trình tìm kiếm sẽ dừng khi tất cả các nhãn đều có giá trị 1. Đến đây, chắc các bạn đã thấy "sự lợi hại" của kỹ thuật loang đổ mảng gán nhãn các đỉnh. Bài 2: Lâu đài Splendid, vua xứ Byteotia muốn cho cô con gái xinh đẹp của mình − công chúa Ada xuất giá. Ông hỏi con gái muốn người chồng của mình phải thế nào. Công chúa trả lời là chồng tương lai phải là một người thông minh đồng thời không hoang phí cũng như không keo kiệt bủn xỉn. Nhà vua suy nghĩ khá lâu về cách kiểm tra để chọn cho công chúa người tốt nhất. Cuối cùng ông thấy hay nhất là sử dụng lâu đài của mình để tổ chức tiếp đãi mọi cư dân của Byteotia. Lâu đài có rất nhiều phòng, trong đó trưng bày các báu vật quốc gia. Theo các hành lang trong lâu đài, người ta có thể ghé vào phòng này hay phòng khác, ngắm nhìn các hiện vật độc đáo trưng bày, mang lại những kinh ngạc thích thú cho người xem. Để ghé vào mỗi phòng, người tham quan phải trả một số Bytealer (đơn vị tiền tệ của Byteotia). Cuộc tham quan bắt đầu từ phòng có cửa vào lâu đài. Nhà vua trao cho mỗi người trong điện có thể chọn làm phò mã một túi tiền, với một số lượng Bytealer như nhau. Nhà vua yêu cầu mỗi người tự chọn đường đi tham quan, bắt đầu từ phòng vào lâu đài kết thúc ở phòng công chúa ngồi. Mỗi người được yêu cầu chi hết đúng số tiền trong túi được trao. Những người hoang phí quá nhiều cho việc ghé xem các phòng trưng bày hết tiền trước khi đến được phòng công chúa. Ngược lại, những người keo kiệt tới phòng công chúa nhưng với túi vẫn còn tiền, kết quả là bị công chúa đuổi ra ngoài sau khi thu hết số tiền dư trong túi. Thật không may là vẫn chưa có chàng trai nào hoàn thành nhiệm vụ nhà vua đã trao công chúa vẫn phải trông chờ, hy vọng một khi nào đó sẽ có kết cục tốt đẹp. Tại sao bạn lại không thử vận may của mình xem sao? Bạn có thể lập trình để trợ giúp cho nàng công chúa tội nghiệp đó. Dữ liệu: vào từ file văn bản Castle.inp - Dòng đầu tiên có 5 số nguyên n,m,e,p,b (1<=n<=100; 1<=m<=4950; 1<=e,p<=n; 1<=b<=1000) trong đó n: số phòng; m: số hành lang; các phòng được đánh số từ 1 tới n; e:phòng vào lâu đài; p: phòng có công chúa; b: số Bytealer trong túi. - Dòng thứ 2 chứa n số nguyên dương c1,c2,…,cn (1<=ci<=1000) ci: tiền cần trả để vào xem phòng i. - M dòng tiếp theo: mỗi dòng chứa một cặp số nguyên dương x, y (x≠y,1<=x,y<=n) cho biết có hành lang nối 2 phòng x y Các số trên một dòng cách nhau ít nhất 1 dấu cách. Kết quả: đưa ra file văn bản Castle.out dãy số nguyên xác định các phòng cần ghé từ phòng e tới phòng p. Bài toán này cũng tương tự như bài toán trên, nó chỉ khác ở chỗ mỗi đỉnh bây giờ không phải chỉ có 1 nhãn mà là b nhãn. Ta dùng 2 mảng f,c kích thước n*b: f[i,j]: là nhãn thứ j của đỉnh i c[i,j]: lưu đỉnh trước của đỉnh i ứng với nhãn j Tuy nhiên do các nhãn của một đỉnh chỉ có giá trị 0,1 nên ta có dùng bit để tiết kiệm bộ nhớ. Phần cài đặt xin dành cho các bạn. Cần lưu ý rằng, việc loang đổ mảng sẽ không thể thực hiện được khi ta chưa xác định số lượng lớn nhất các trạng thái có trong một mức. Hy vọng với kỹ thuật trên, các bạn có thể giải được một lớp lớn các bài toán có tính chất tìm kiếm. . Kỹ thuật loang đổ mảng và gán nhãn các đỉnhNguyễn Thành TrungTrong các số báo của ISM trước đây đã đề cập rất nhiều đến thuật toán tìm kiếm. trữ và thời gian thực hiện nhất là đối với những bài toán mà cây tìm kiếm gần như vô tận. Để khắc phục điều đó, chúng ta sẽ dùng kỹ thuật loang đổ mảng và

Ngày đăng: 11/09/2012, 15:00

Từ khóa liên quan

Tài liệu cùng người dùng

Tài liệu liên quan