Quét Graham và hệ điều hành Jarvis
Bao lồi với thuật toán Quét Graham và Diễu hành Jarvis (Bọc gói)Nguyễn Thế AnhI. Bài toánBao lồi của 1 tập hợp Q gồm các điểm của đa giác lồi nhỏ nhất P mà mỗi điểm của Q nằm trên biên của P hoặc trong phần trong của nó. Hay có thể phát biểu thành bài toán như sau:Cho n điểm A1(x1,y1), A2(x2,y2), ., An(xn,yn). Hãy tìm đa giác lồi có diện tích nhỏ nhất chứa tất cả các điểm trên. Đa giác như vậy gọi là bao lồi của n điểm đã cho.Rõ ràng bao lồi cần tìm có các đỉnh thuộc các điểm đã cho.II. Các phương pháp giảiA. Thuật toán quét Graham1. Phát biểu thuật toán+ Trong các điểm có tung độ nhỏ nhất, tìm điểm có hoành độ lớn nhất, gọi điểm này là B1. Điểm này chắc chắn thuộc bao, đổi vị trí điểm này với A1.+ Kết nạp thêm các điểm A2,A3 vào bao+ Với mỗi điểm Ai(i=1 n) tính các góc giữa véctơ A1Ai với đường thẳng nằm ngang. Sắp xếp lại các điểm theo thứ tự tăng dần của các góc này+ Với mỗi điểm Ai.(i=1 n) kiểm tra thuộc bao trước đó có cònthuộc bao hay không, nếu không thì loại bỏ. Kết nạp điểm Ai vào bao.Tiếp tục quá trình cho đến hết.2. Đoạn chương trìnhprogram baoloigrama;uses crt;type p=recordx,y:longint;end;varm,n:byte;A,B:array[byte] of p;procedure input;var i:byte; f:text; s:string;beginclrscr; write('Ten file du lieu vao : ');readln(s); assign(f,s); {$I-} reset(f); {$I+} readln(f,n);for i:=1 to n do readln(f,A[i].x,A[i].y); close(f);End;function goc(m1,m2:p):real;var dx,dy:longint; t:real;begindx:=m2.x-m1.x; dy:=m2.y-m1.y;if (dx=0) and (dy=0) then t:=0else t:=dy/(abs(dx)+abs(dy));if dx<0 then t:=2-t elseif dy<0 then t:=4+t; goc:=t*90;end;functiondirect(m1,m2,m3:P):integer;var dx1,dx2,dy1,dy2:longint;begindx1:=m2.x-m1.x;dy1:=m2.y-m1.y;dx2:=m3.x-m1.x;dy2:=m3.y-m1.y;if dy2*dx1-dy1*dx2>0 thendirect:=1;if dy2*dx1-dy1*dx2<0 thendirect:=-1;if dy2*dx1-dy1*dx2=0 thenbeginif (dx1*dx2<0) or (dy1*dy2<0) then direct:=1elseif (dx1*dx1+dy1*dy1)>= (dx2*dx2+dy2*dy2) then direct:=0else direct:=1;end;end;procedure Swap;var i,j:byte; t:real; q:p;g:array[byte]of real;beginfor i:=2 to n do g[i]:=goc(a[1],a[i]);for i:=2 to n-1 dofor j:=i+1 to n doif g[i]>g[j] thenbegint:=g[i]; g[i]:=g[j];g[j]:=t;q:=a[i]; a[i]:=a[j];a[j]:=q;end;end;procedure graham;var i,min:byte; q:p; t:real;beginmin:=1;for i:=2 to n doif a[i].yfor i:=1 to n doif a[i].y=a[min].y thenif a[i].x>a[min].x then min:=1;q:=a[1]; a[1]:=a[min]; a[min]:=q; soft;b[0]:=a[n]; m:=3;for i:=1 to 3 do b[i]:=a[i];for i:=4 to n dobeginwhile direct(b[m-1],b[m],a[i])<=0 do m:=m-1;m:=m+1; b[m]:=a[i];end;end;end;BEGIN input;graham;END.B.Thuật toán 'Diễu hành Jarvis'(Bọc gói)1. Phát biểu thuật toán+ Chọn điểm thứ nhất là điểm có tung độ bé nhất, gọi là điểm B1. Điểm này chắc chắn thuộc bao lồi. Đặt Bn+1 = B1.+ Dùng 1 tia quan điểm B1 quét ngược chiều kim đồng hồ cho đến khi gặp 1 điểm khác. Gọi điểm này là B2+ Dùng 1 tia quan điểm B2quét ngược chiều kim đồng hồ cho đến khi gặp 1 điểm khác. Gọi điểm này là B3+ Lặp lại quá trình trên cho đến khi điểm chọn trùng lại điểm Bn+1Ta có thể nhận thấy không cần quét tất cả các góc có thể. Góc cần quét chắc chắn lớn hơn hay bằng góc đã quét được trước đó. Đồng thời các điểm được chọn cần đánh đấu để không được chọn lại lần sau.2. Đoạn chương trìnhVề chương trình thì chỉ cần thay thủ tục javis sau vào thủ tục Graham ở chương trình trên procedure Javis;var i,j:byte;min,g:real;C:array[byte]of boolean;beginfor j:=1 to n do c[j]:=true; i:=1;for j:=2 to n do ifa[j].yrepeatm:=m+1; B[m]:=A[i];C[i]:=false;i:=n+1; g:=min;min:=360;for j:=1 to n+1 doif c[j] thenif ( goc(b[m], a[j])>g) and (goc(b[m], a[j])begin i:=j;min:=goc(b[m],a[i]);end;until i=n+1;writeln('So ding thuoc bao la : ',m); readln;end; Ngoài ra, nếu bạn muốn vẽbao lồi ra màn hình thì chỉ cần thêm thủ tục vẽ sau vao chương trìnhprocedure ve;var gd, gm:integer;i:byte;s:string[3];begingd:=0;initgraph(gd,gm,'C:tp7bgí);b[m+1]:=b[1];for i:=1 to n dobeginputpixel(a[i].x,a[i].y,white);str(i,s); outtextxy(a[i].x,a[i].y+5,s);end;for i:=1 to m do line(b[i].x,b[i].y,b[i+1].x,b[i+1].y);readln;closegraph;end;ở chương trình chính bạn gọi các thủ tục như sau : BEGINnhap;graham;{hoặc Javis}VE;END.III. Các bài toán Sau khi tham khảo hai thuật toán trên, mời bạn thử sức với các bài toán sau :1. Cho n điểm , hãy tìmtrong n điểm này ba điểm tạo thành 1 tam giác mà số lượng điểm nằm trong đó (kể cả biên) là lớn nhất.2.Rào câyNgười ta muốn rào các cây ở một khu vườn để bảo vệ. Hàng rào được tạo bởi một đường gấp khúc đơn khép kín có đỉnh là một số cây làm cột mốc, sao cho các cây khác phải nằm trong hàng rào (một số cây có thể nằm trên biên).Hãy xác định một phương án rào cây sao cho số cây phải làm cột mốc là ít nhất.Dữ liệu vào : - Tệp văn bản Cay.inp, dòng đầu là số cây, các dòng tiếp là toạ độ của các cây. Các cây được đánh số từ 1 theo thứ tự trong file.Dữ liệu ra : - Ghi ra file văn bản Cay.out, dòng đầu là số cây làm cột mốc, dòng sau là số hiệu các cây này theo đúng thứ tự tạo hàng rào.Giới hạn: Số cây ≤255Vdụ : . Bao lồi với thuật toán Quét Graham và Diễu hành Jarvis (Bọc gói)Nguyễn Thế AnhI. Bài toánBao lồi của 1 tập hợp. direct(b[m-1],b[m],a[i])<=0 do m:=m-1;m:=m+1; b[m]:=a[i];end;end;end;BEGIN input ;graham; END.B.Thuật toán 'Diễu hành Jarvis& apos;(Bọc gói)1. Phát biểu thuật toán+ Chọn điểm