Tải bản đầy đủ (.docx) (33 trang)

Chu de 16 2015

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (178.04 KB, 33 trang )

<span class='text_page_counter'>(1)</span>LUYỆN THI HỌC SINH GIỎI MÔN TIN HỌC Thời gian làm bài: 150 phút. CHỦ ĐỀ 16 BÀI TOÁN HÌNH HỌC. Tổng quan TT 1 2 3. Tên bài Đường thẳng chứa 3 điểm Điểm trong đa giác Diện tích phủ sóng. Tệp chương trình. Tệp dữ liệu. Tệp kết quả. Thời Gian. DT3D.PAS. DT3D.INP. DT3D.OUT. 1s/test. DTDG.PAS PSONG.PAS. DTDG.INP PSONG.INP. DTDG.OUT PSONG.OUT. 1s/test 1s/test. Bài 1. (6 điểm) ĐƯỜNG THẲNG CHỨA 3 ĐIỂM Cho một dãy gồm N điểm khác nhau (N <= 200). Yêu cầu: Tìm xem có bao nhiêu đường thẳng khác nhau, mỗi đường thẳng đó chứa ít nhất 3 điểm trong N điểm nói trên. Dữ liệu: Đọc vào từ tệp DT3D.INP, gồm nhiều phương án, mỗi phương án trên một dòng, trên dòng đó ghi N cặp số X, Y là tọa độ của N điểm. Kết quả: Ghi ra màn hình và ghi ra tệp DT3D.OUT, mỗi phương án trên một dòng, trên dòng đó ghi số lượng (SL) các đường thẳng tìm được (nếu không tìm được đường thẳng nào thỏa mãn thì đặt SL = 0), tiếp đó, nếu SL > 0 thì ghi ra SL bộ số để trong cặp ngoặc vuông, mỗi bộ số đó là chỉ số của các điểm nằm trên đường thẳng tương ứng. Ví dụ: DT3D.INP DT3D.OUT 000102111222 3 [1 2 3] [1 4 6] [3 5 6] 00011112202526 1 [5 6 7] Bài 2. (7 điểm) ĐIỂM TRONG ĐA GIÁC Cho đa giác không tự cắt có N đỉnh và một điểm P =(px, py). Yêu cầu: Txác định vị trí của điểm P đối với đa giác đã cho. Dữ liệu: Đọc từ tệp DTDG.INP, gồm nhiều phương án, mỗi phương án trên một dòng, trên dòng đó ghi cặp số px, py, tiếp đó ghi N cặp số, mỗi cặp là tọa độ của 1 đỉnh của đa giác. Kết quả: Ghi ra màn hình và ghi ra tệp DTDG.OUT, mỗi phương án trên một dòng, trên dòng đó ghi vị trí VTP của điểm P đối với đa giác với quy định sau: VTP = 1: P nằm trong đa giác, VTP = -1: P nằm ngoài đa giác, VTP = 0: P là 1 đỉnh của đa giác hoặc P nằm trên cạnh của đa giác. Ví dụ: DTDG.INP DTDG.OUT -2 0 -1 -1 -1 1 1 1 0 0 1 -1 -1 0 0 -1 -1 -1 1 1 1 0 0 1 -1 0 Bài 3. (7 điểm) DIỆN TÍCH PHỦ SÓNG Một công ty kinh doanh dịch vụ điện thoại di động, lắp đặt N ăng ten thu phát sóng trên mặt đất. Ăng ten thứ i lắt đặt tại vị trí (X[i], Y[i]), có công suất là R[i] và có diện tích phủ sóng là hình vuông với tâm là (X[i], Y[i]) và diện tích là 4R[i]2. Yêu cầu: Tính tổng diện tích phủ sóng của N ăng ten đó. Dữ liệu: Đọc từ tệp văn bản PSONG.INP, gồm nhiều phương án, mỗi phương án ghi trên một dòng, trên dòng đó ghi N bộ ba số X[i], Y[i], R[i], tương ứng với vị trí và công suất của các ăng ten. Các số đều là số thực. Kết quả: Ghi ra màn hình và ghi ra tệp văn bản PSONG.OUT, mỗi phương án trên 1 dòng, trên dòng đó ghi tổng diện tích phủ sóng tìm được, với 2 chữ số thập phân.. Ví dụ:. PSONG.INP 3.0 3.0 3.0 1.5 1.5 1.0 3.0 2.0 4.0 1.5 2.5 3.0. PSONG.OUT 36.00 67.00 TÓM TẮT LÝ THUYẾT.

<span class='text_page_counter'>(2)</span> 1. Điểm, đường thẳng, đoạn thẳng, đa giác Điểm là đối tượng hình học cơ sở, được biểu diễn bằng một cặp số (x, y). Trong Pascal, có thể khai báo điểm là cặp số thông thường, cũng có thể dùng bản ghi để khai báo các điểm: Type Point = record x,y: integer End; var P, Q, M: Point; Qua hai điểm khác nhau luôn có một và chỉ một đường thẳng. Phương trình của đường thẳng đi qua hai điểm P(px,py) và Q(qx,qy) là: dy*(x-px) = dx*(y-py) trong đó dx = qx – px, dy = qy – py. (Tỷ số dy/dx chính là tang của góc tạo bởi đường thẳng PQ và trục hoành). Trong Pascal, có thể khai báo đường thẳng cặp điểm thông thường, cũng có thể dùng bản ghi để khai báo các đường thẳng: Type Line = record P1, P2: Point End; var L1, L2: Line; Đoạn thẳng được biểu diễn bởi một cặp điểm (P,Q), là phần của đường thẳng đi qua hai điểm đó, và chỉ gồm các điểm M nằm giữa hai điểm đó. Điều kiện cần và đủ để điểm M là một điểm thuộc đoạn PQ là tồn tại số thực α với 0 <= α <=1 để cho Mx = (1- α) * Px + α * Qx và My = (1- α) * Py + α * Qy. Trong Pascal, không có cách khai báo đoạn thẳng nào khác với cách khai báo đường thẳng nói trên. Đa giác được biểu diễn bởi một danh sách N điểm, trong đó hai điểm kế tiếp được nối với nhau bởi một đoạn thẳng (điểm cuối có điểm kế tiếp là điểm đầu). Trong Pascal, có thể khai báo đa giác theo nhiều cách khác nhau: a) Sử dụng hai mảng X, Y riêng biệt: var X, Y: array[1..NMax] of integer; {các mảng chứa NMax tọa độ} Cách này thường dùng khi cần xử lý các tọa độ riêng biệt. b) Sử dụng một mảng hai chiều: var P: array[1..Nmax, 1..2] of integer; {mảng chứa NMax điểm} Theo cách này điểm thứ I sẽ có tọa độ là Px = P[i,1] và Py = P[I,2]. c) Sử dụng một mảng các bản ghi: Type Diem = record x,y: integer End; var P: array[1..Nmax] of Diem; {mảng chứa NMax điểm} Theo cách này điểm thứ i sẽ có tọa độ là Px = P[i].x và Py = P[i].y. 2. Giao của các đoạn thẳng Để xác định xem hai đoạn thẳng có giao nhau (có điểm chung) hay không, người ta thường sử dụng hàm CCW sau đây để xác định hướng đi từ điểm (x1,y1) đến điểm (x2,y2) rồi đến điểm (x3,y3): function CCW(x1,y1,x2,y2,x3,y3: integer): integer; Var dx1, dy1, dx2, dy2: integer; BEGIN dx1 := x2 – x1; dy1 := y2 – y1; dx2 := x3 – x1; dy1 := y3 – y1; if dx1*dy2 > dy1*dx2 then ccw := 1; {ngược chiều kim đồng hồ} if dx1*dy2 < dy1*dx2 then ccw := -1; {thuận chiều kim đồng hồ} if dx1*dy2 = dy1*dx2 then ccw := 0; {ba điểm thẳng hàng} END; Từ đó, sự giao nhau của hai đoạn thẳng (x1,y1)-(x2,y2) và (x3,y3)-(x4,y4) được xác định bởi hàm GiaoNhau như sau: function GiaoNhau(x1,y1,x2,y2,x3,y3,x4,y4: integer): boolean; var c1, c2, c3, c4: integer; BEGIN c1 := CCW( x1,y1,x2,y2,x3,y3); {1 – 2 - 3} c2 := CCW( x1,y1,x2,y2,x4,y4); {1 – 2 - 4} c3 := CCW( x3,y3,x4,y4,x1,y1); {3 – 4 - 1} c4 := CCW( x3,y3,x4,y4,x2,y2); {3 – 4 - 2} GiaoNhau := (c1*c2 <= 0) and (c3*c4 <=0); END;.

<span class='text_page_counter'>(3)</span> 3. Điểm nằm trong đa giác. Để xác định vị trí của điểm P đối với đa giác GD ta có thể làm như sau: 1) Nếu P là đỉnh hoặc P nằm trên cạnh của đa giác thì đặt vtP = 0. 2) Trái lại, tìm điểm M nằm ngoài đa giác sao cho đường thẳng MP không chứa đỉnh của đa giác. Tìm số điểm sc mà đoạn thẳng MP cắt các cạnh của đa giác (sử dụng hàm CCW nói trên). Nếu sc lẻ vtP = 1 (P nằm trong đa giác), trái lại đặt vtP = -1 (P nằm ngoài đa giác).. GIỢI Ý CÁCH GIẢI Bài 1. - Thủ tục TimSL để tìm số đường thẳng: Đặt SL = 0, n1 = N – 1, n2 = N - 2 Khởi tạo mảng CD bằng 0 (0: chưa dùng, 1: đã dùng) Duyệt với i từ 1 đến n2 {Điem thu 1}.

<span class='text_page_counter'>(4)</span> Đặt i1 = i + 1 Duyệt với j = i1 đến n1 Nếu CD[j] = 0 thì {Diem thu 2} Đặt j1 = j + 1 Duyệt với k từ j1 đến n Nếu TH(i,j,k) thì {Diem thu 3} Tăng sl Đặt DT[sl,1] = i, DT[sl,2] = j Đặt CD[j] = 1, CD[k] = 1 {Dánh dấu đã dùng} - Hàm TH(ii ,jj, kk: byte): boolean xác định 3 điểm ii, jj, kk thẳng hàng Đặt dx = D[jj,1] - D[ii,1], dy = D[jj,2] - D[ii,2] if dx*(D[kk,2] - D[ii,2]) = dy*(D[kk,1] - D[ii,1]) thì TH = true trái lại TH = false Bài 2. - Thủ tục TimVTP để tìm vị trí của điểm P đối với đa giác. Đặt X[N+1] = X[1], Y[N+1] = Y[1], vtp = 0 Nếu TrungDinh hoặc ThuocCanh) thì Thóat ra Trái lại TimM Đặt sdc = 0 Duyệt với i từ 1 đến N Nếu Cat(i) thì tăng sdc Nếu sdc mod 2 = 1 thì vtp = 1 trái lại vtp = -1 - Hàm TrungDinh: xác định P trùng với đỉnh của da giác Duyệt với i từ 1 đến N Nếu (px = X[i]) và (py = Y[i]) thì Đặt TrungDinh = true Thoát ra TrungDinh = false - Hàm ThuocCanh: xác định P thuộc cạnh của đa giác Duyệt với i từ 1 đến N Nếu (px-X[i])*(Y[i+1] - Y[i]) = (py-Y[i])*(X[i+1] - X[i]) thì Nếu ((px - X[i])*(px-X[i+1])<=0) và ((py - Y[i])*(py-Y[i+1])<=0) thì Đặt ThuocCanh = true Thoát ra Đặt ThuocCanh = false - Thủ tục TimM: tìm điểm M nằm ngoài đa giác Đặt mx = -maxint, my = -maxint Duyệt với i từ 1 đến N Nếu mx < X[i] thì mx = X[i] Nếu my < Y[i] thì my = Y[i] Tăng mx {Tránh trường hợp M trùng với đỉnh của đa giác} Lặp lại cc = false Duyệt với i từ 1 đến N Nếu (my-py)*(X[i] - px) = (mx-px)*(Y[i] - py) thì Tăng mx Đặt cc = true Thoát khỏi vòng lặp theo i; Cho đến khi cc = false - Hàm Cat(ii): xác định đoạn MP cắt cạnh ii của đa giác Đặt x1 = X[ii], y1 = Y[ii], x2 = X[ii+1], y2 = Y[ii+1] Đặt cc1 = ccw(x1,y1,x2,y2,px,py) {1 2 P} Đặt cc2 = ccw(x1,y1,x2,y2,mx,my) {1 2 M} Đặt cc3 = ccw(px,py,mx,my,x1,y1) {P M 1} Đặt cc4 = ccw(px,py,mx,my,x2,y2) {P M 2} Trả về Cat = (cc1*cc2 < 0) và (cc3*cc4 < 0).

<span class='text_page_counter'>(5)</span> - Hàm ccw(x1,y1,x2,y2,x3,y3): xác định hướng đi từ 1-2-3 Đặt dx1 = x2 - x1, dx2 = x3 - x2, dy1 = y2 - y1, dy2 = y3 - y2 Nếu dx1*dy2 > dy1*dx2 thì ccw = 1 {ngược chiều kim đồng hồ} Nếu dx1*dy2 < dy1*dx2 thì ccw := -1 {thuận chiều kim đồng hồ} Nếu dx1*dy2 = dy1*dx2 thì ccw:=0; {thẳng hàng} Bài 3. - Thủ tục TinhDT: tính tổng diện tích phủ sóng SXTang(X, XX) SXTang(Y, YY) Đăt dt = 0, n21 = 2*N-1 Duyệt với i từ 1 đến n21 Duyệt với j từ 1 đến n21 Duyệt với k từ 1 đến N Đặt x1 = XX[i], y1 = YY[j], x2 = XX[i+1], y2 = YY[j+1]; Đặt x3 = X[k]-r[k], y3 = Y[k]-r[k], x4 = X[k]+r[k], y4 = Y[k]+r[k] Nếu NT(x3, y3, x4, y4, x1, y1, x2, y2) thì dt = dt + abs((x1-x2)*(y1-y2)) thoát khỏi vòng lặp theo k - Thủ tục SXTang(mm, xt): tạo và sắp xếp tăng dần mảng xt từ màng mm Duyệt với i từ 1 đến N xt[2*i-1] = mm[i] - R[i], xt[2*i] = mm[i] + R[i]; n2 = 2*N, n21 = n2 -1 Duyệt với i từ 1 đến n21 i1 = i+1; Duyệt với j từ i1 đến n2 Nếu (xt[i]>xt[j]) thì DoiCho(xt,i,j) - Thủ tục DoiCho(mm, ii,jj): đổi chỗ các phần tử ii, jj của mảng mm t = mm[ii], mm[ii] = mm[jj], mm[jj] = t - Hàm NT(x1,y1,x2,y2,x3,y3,x4,y4): Xác định hcn 3-4 nằm trong hcn 1-2 Nếu (x1<=x3) và (x4<=x2) và (y1<=y3) và (y4<=y2) thì NT = true trái lại NT = false. DỮ LIỆU ĐỂ KIỂM TRA BÀI 1 Tệp DT3D.INP 0 0 0 1 0 2 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 1 0 2 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1. 1 1 1 1 1 1 1 1. 1 2 2 2 1 2 2 2. 1 2 2 2 1 2 2 2. 2 0 0 0 2 0 0 0. 2 2 2 2 2 2 2 2. 2 5 5 5 2 5 5 5. 2 3 3 3 3 3 3. Tệp DT3D.OUT 3 [1 2 3] [1 4 6] [3 5 6]. 6 3 3 3 4 3 3. 4 4 4 4 4 4. 4 4 4 5 4 4. 3 5 5 4 3. 4 5 6 5 4. 6 6 4 4. 6 7 7 8 6 4 7 7 8 5 5 7 7 9 8 9.

<span class='text_page_counter'>(6)</span> 1 1 2 5 3 3 4. [5 [1 [1 [1 [2 [1 [1. 6 3 3 2 4 3 3. 7] 7 8] 7 8] [2 4 9] 3] [1 4 6 7 8 9 10] [1 7 8 9 10] [1 9 10] [3 5 6] 7 8 9 10 11] [2 8 9 10 11] [2 10 11] 7 8] [2 4 9 12] [8 10 11] 7 8] [2 4 9 10 13] [2 10 13] [6 11 13]. DỮ LIỆU ĐỂ KIỂM TRA BÀI 2 Tệp DTDG.INP -2 0 -1 -1 -1 1 1 1 0 0 1 -1 0 0 -1 -1 -1 1 1 1 0 0 1 -1 -1 0 -2 -1 -1 1 1 1 0 0 1 -1 -5 0 -1 -1 -1 1 1 1 0 0 1 -1 0 2 -1 -2 -1 2 1 2 2 4 1 -1 0 -2 -2 -1 -1 3 3 1 4 0 1 -1 -1 -1 -2 -2 -1 0 1 1 0 0 1 -1 1 0 -5 -1 -1 5 1 1 0 0 1 -1 -1 -3 -5 0 -4 2 4 2 5 0 0 -1 0 -5 Tệp DTDG.OUT -1 0 1 -1 0 -1 1 -1 1. DỮ LIỆU ĐỂ KIỂM TRA BÀI 3 Tệp PSONG.INP (Chú ý: dữ liệu kéo dài đến dòng thục vào tiếp theo) 3.0 3.0 3.0 1.5 1.5 1.0 3.0 2.0 4.0 1.5 2.5 3.0 4.0 4.0 3.0 5.0 6.0 3.0 5.5 4.5 1.0 4.0 4.0 2.5 6.0 5.0 3.5 4.5 5.5 1.5 4.0 4.0 3.5 5.0 6.0 3.0 5.5 4.5 1.5 6.5 5.5 2.5 4.0 4.0 3.0 6.0 5.0 3.5 4.5 5.5 2.0 5.5 6.5 2.5 4.0 4.0 4.0 5.0 6.0 4.0 5.5 4.5 3.0 6.5 5.5 5.0 5.5 6.5 7.0 4.0 4.0 3.0 6.0 5.0 4.0 4.5 5.5 2.0 5.5 6.5 3.0 6.5 5.5 5.0 4.0 4.0 3.0 6.0 5.0 3.0 4.5 5.5 1.0 5.5 6.5 2.0 6.5 5.5 2.0 3.5 5.5 2.0 Tệp PSONG.OUT 36.00 67.00 52.00 54.00 65.25.

<span class='text_page_counter'>(7)</span> 62.75 196.00 103.00 54.75. MÃ NGUỒN BÀI 1 (Tệp DT3D.PAS). {Phan khai bao chung} uses crt; Const tentep = 'DT3D'; {Ten tep} Nmax = 255; DTmax = 100; Var D: array[1..Nmax, 1..2] of integer; {Dau vao} sl: integer; {Dau ra} DT: array[1..Nmax, 1..2] of byte; {Dau ra} N: integer; {Bien phu} CD: array[1..nmax] of 0..1; {Mang phu} pa, sopa: byte; {QL phuong an}. f: text;. {Bien tep}. {Dem so phuong an} procedure DemSoPA; BEGIN assign(f,tentep+'.INP'); reset(f); sopa:=0; while (not eof(f)) do begin readln(f); inc(sopa); end; close(f);.

<span class='text_page_counter'>(8)</span> END; {Doc du lieu cua phuong an pa} procedure DocPA; var i:integer; BEGIN assign(f,tentep+'.INP'); reset(f); i:=1; while (i<pa) do begin readln(f); inc(i); end; N := 0; while (not eoln(f)) do begin inc(N); read(f,D[N,1],D[N,2]); end; close(f); END; {Xet 3 diem, true: thang hang, false: khong thang hang} function TH(ii ,jj, kk: byte): boolean; var dx, dy: integer; BEGIN dx := D[jj,1] - D[ii,1]; dy := D[jj,2] - D[ii,2]; if dx*(D[kk,2] - D[ii,2]) = dy*(D[kk,1] - D[ii,1]) then TH := true else TH := false; END; {Tim so duong thang qua it nhat 3 diem} Procedure TimSL; var n1, n2, i, i1, j, j1, k: integer; BEGIN SL := 0; n1 := N - 1; n2 := N - 2; fillchar(CD, sizeof(CD),0); for i := 1 to n2 do {Diem thu 1} begin i1 := i + 1; for j := i1 to n1 do if CD[j] = 0 then {Diem thu 2} begin j1 := j + 1; for k := j1 to n do if TH(i,j,k) then {Diem thu 3} begin inc(sl);. DT[sl,1] := i; DT[sl,2] := j; CD[j] := 1; CD[k] := 1; break; end; end; end; END; {Ghi ket qua ra man hinh va tep tin} procedure GhiKQ; var i, id, j: integer; BEGIN assign(f,tentep+'.OUT'); if pa=1 then rewrite(f) else append(f); write(SL); write(f,SL); if SL > 0 then for i := 1 to SL do begin write(' [',DT[i,1],' ',DT[i,2]); write(f,' [',DT[i,1],' ',DT[i,2]); id := DT[i,2] + 1; for j := id to N do if TH(DT[i,1], DT[i,2],j) then begin write(' ',j); write(f,' ',j); end; write(']'); write(f,']'); end; writeln; writeln(f); close(f); END; {Chuong trinh chinh} BEGIN clrscr; DemSoPA; for pa:=1 to sopa do begin DocPA; TimSL; GhiKQ; end; writeln; write('Da xong. Nhan ENTER de thoat'); Readln; END..

<span class='text_page_counter'>(9)</span> GIẢI THÍCH MÃ NGUỒN BÀI 1 1. Chương trình chính. Sau khi gọi lệnh DemSoPA, vòng lặp For gọi các lệnh DocPA, TimSL, và GhiKQ. 2. Lệnh DemSoPA: đếm số phương án có trong tệp dữ liệu. 3. Lệnh DocPA: đọc dữ liệu của phương án thứ pa. 4. Lệnh GhiKQ: ghi kết quả ra màn hình và tệp tin. 5. Lệnh TimSL: Tìm số lượng đường thẳng theo yêu cầu, thuật giải đã nêu ở phần Hướng dẫn cách giải.. MÃ NGUỒN BÀI 2 (Tệp DTDG.PAS) {Phan khai bao chung} uses crt; const tentep = 'DTDG';. {Ten tep}. var px, py: integer; {Dau vao} X,Y: Array[1..2000] of integer; {Dau vao} vtp: -1..1; {Dau ra} N, mx, my: integer; {Bien phu} sopa, pa: integer; f:text;.

<span class='text_page_counter'>(10)</span>

<span class='text_page_counter'>(11)</span>

<span class='text_page_counter'>(12)</span>

<span class='text_page_counter'>(13)</span>

<span class='text_page_counter'>(14)</span>

<span class='text_page_counter'>(15)</span>

<span class='text_page_counter'>(16)</span>

<span class='text_page_counter'>(17)</span>

<span class='text_page_counter'>(18)</span>

<span class='text_page_counter'>(19)</span>

<span class='text_page_counter'>(20)</span>

<span class='text_page_counter'>(21)</span>

<span class='text_page_counter'>(22)</span>

<span class='text_page_counter'>(23)</span> var i: integer; BEGIN for i := 1 to N do if (px = X[i]) and (py = Y[i]) then begin TrungDinh := true; Exit; end; TrungDinh := false; END; {P thuoc 1 canh cua da giac} function ThuocCanh: boolean; var i: integer; BEGIN for i := 1 to N do if (px-X[i])*(Y[i+1] - Y[i]) = (py-Y[i])*(X[i+1] X[i]) then {P, i, i+1 thang hang} if ((px - X[i])*(px-X[i+1])<=0) and ((py Y[i])*(py-Y[i+1])<=0) then {P thuoc canh i} begin ThuocCanh := true; Exit; end; ThuocCanh := false; END; {Tim diem M ngoai da giac va PM khong chua dinh cua da giac} procedure TimM; var i: integer; cc: boolean; {con chinh mx} BEGIN mx := -maxint; my := -maxint; for i := 1 to N do begin if mx < X[i] then mx := X[i]; if my < Y[i] then my := Y[i]; end; inc(mx); repeat cc := false; for i:=1 to N do if (my-py)*(X[i] - px) = (mx-px)*(Y[i] - py) then begin {P, M, i thang hang} inc(mx); cc := true; break; end; until (not cc); END;.

<span class='text_page_counter'>(24)</span> {huong giua 3 diem: 1: nguoc, -1: thuan, 0: thang hang} function ccw(x1,y1,x2,y2,x3,y3: integer): integer; var dx1, dx2, dy1, dy2: integer; BEGIN dx1 := x2 - x1; dx2 := x3 - x2; dy1 := y2 - y1; dy2 := y3 - y2; if dx1*dy2 > dy1*dx2 then ccw := 1; {nguoc} if dx1*dy2 < dy1*dx2 then ccw := -1; {thuan} if dx1*dy2 = dy1*dx2 then ccw:=0; {thang hang} END; {Doan thang MP cat canh thu ii} function Cat(ii: integer): boolean; var x1, y1, x2, y2, cc1, cc2, cc3, cc4: integer; BEGIN x1 := X[ii]; y1 := Y[ii]; x2 := X[ii+1]; y2 := Y[ii+1]; cc1 := ccw(x1,y1,x2,y2,px,py); {1 2 P} cc2 := ccw(x1,y1,x2,y2,mx,my); {1 2 M} cc3 := ccw(px,py,mx,my,x1,y1); {P M 1} cc4 := ccw(px,py,mx,my,x2,y2); {P M 2} Cat := (cc1*cc2 < 0) and (cc3*cc4 < 0); END; {vi tri cua diem P: 1: trong, -1: ngoai, 0: thuoc canh} procedure TimVTP; var i, sdc: integer; BEGIN X[N+1] := X[1];. Y[N+1] := Y[1]; vtp := 0; if (TrungDinh or ThuocCanh) then Exit else begin TimM; sdc := 0; for i := 1 to N do if Cat(i) then inc(sdc); if sdc mod 2 = 1 then vtp := 1 else vtp := -1; end; END; {Ghi ket qua ra man hinh va tep tin} procedure GhiKQ; BEGIN Assign(f, tentep+'.OUT'); if (pa = 1) then Rewrite(f) else Append(f); writeln(vtp); writeln(f,vtp); Close(f); END; {Chuong trinh chinh} BEGIN clrscr; DemSoPA; for pa:=1 to soPA do begin DocPA; TimVTP; GhiKQ; end; writeln; write('Da xong. Nhan ENTER de thoat.'); readln; END.. GIẢI THÍCH MÃ NGUỒN BÀI 2 1. Chương trình chính. Sau khi gọi lệnh DemSoPA, vòng lặp For gọi các lệnh DocPA, TimVTP, và GhiKQ. 2. Lệnh DemSoPA: đếm số phương án có trong tệp dữ liệu. 3. Lệnh DocPA: đọc dữ liệu của phương án thứ pa. 4. Lệnh GhiKQ: ghi kết quả ra màn hình và tệp tin. 5. Lệnh TimVTP: Tìm vị trí của điểm P theo yêu cầu, thuật giải đã nêu ở phần Hướng dẫn cách giải..

<span class='text_page_counter'>(25)</span> MÃ NGUỒN BÀI 3 (Tệp PSONG.PAS) {Phan khai bao chung} uses crt; const tentep = 'PSONG'; Nmax = 1000;. {Ten tep}. type MangST = array[1..Nmax] of real; var X, Y, R: MangST; dt: real;. {Dau vao} {Dau ra}.

<span class='text_page_counter'>(26)</span>

<span class='text_page_counter'>(27)</span>

<span class='text_page_counter'>(28)</span>

<span class='text_page_counter'>(29)</span>

<span class='text_page_counter'>(30)</span>

<span class='text_page_counter'>(31)</span>

<span class='text_page_counter'>(32)</span> {hcn 1-2 chua hcn 3-4} function NT(x1,y1,x2,y2,x3,y3,x4,y4: real): boolean; BEGIN if (x1<=x3) and (x4<=x2) and (y1<=y3) and (y4<=y2) then NT := true else NT := false; END; {doi cho cac phan tu ii va jj cua mang mm} procedure DoiCho(var mm: MangST; ii,jj: integer); var t: real; BEGIN t := mm[ii]; mm[ii] := mm[jj]; mm[jj] := t; END; {tao va sap xep mang xx tang dan} procedure SXTang(mm: MangST; var xt: MangST); var i, i1, j: integer; BEGIN for i := 1 to N do begin xt[2*i-1] := mm[i] - R[i]; xt[2*i] := mm[i] + R[i]; end; n2 := 2*N; n21 := n2 -1; for i:= 1 to n21 do begin i1 := i+1; for j := i1 to n2 do if (xt[i]>xt[j]) then DoiCho(xt,i,j); end; END; {Tinh dien tich phu song} Procedure TinhDT; var i, j, k: integer; x1, y1, x2, y2, x3, y3, x4, y4: real; BEGIN SXTang(X, XX); SXTang(Y, YY); dt :=0; n21 := 2*N-1; for i := 1 to n21 do for j := 1 to n21 do for k := 1 to N do begin x1 := XX[i]; y1 := YY[j]; x2 := XX[i+1];.

<span class='text_page_counter'>(33)</span> y2 := YY[j+1]; x3 := X[k]-r[k]; y3 := Y[k]-r[k]; x4 := X[k]+r[k]; y4 := Y[k]+r[k]; if NT(x3, y3, x4, y4, x1, y1, x2, y2) then begin dt := dt + abs((x1-x2)*(y1-y2)); break; end; end; END; {Ghi ket qua ra man hinh va tep tin} procedure GhiKQ; BEGIN assign(f, tentep+'.OUT'); if pa = 1 then rewrite(f) else append(f); writeln(dt:0:2);. writeln(f,dt:0:2); close(f); END; {Chuong trinh chinh} BEGIN clrscr; DemSoPA; for pa:=1 to SoPA do begin DocPA; TinhDT; GhiKQ; end; writeln; write('Da xong. Nhan ENTER de thoat.'); readln; END.. GIẢI THÍCH MÃ NGUỒN BÀI 3 1. Chương trình chính. Sau khi gọi lệnh DemSoPA, vòng lặp For gọi các lệnh DocPA, TinhDT, và GhiKQ. 2. Lệnh DemSoPA: đếm số phương án có trong tệp dữ liệu. 3. Lệnh DocPA: đọc dữ liệu của phương án thứ pa. 4. Lệnh GhiKQ: ghi kết quả ra màn hình và tệp tin. 5. Lệnh TinhDT: CTính tổng diện tích phủ sóng theo yêu cầu, thuật giải đã nêu ở phần Hướng dẫn cách giải..

<span class='text_page_counter'>(34)</span>

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×