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 (214.87 KB, 12 trang )
<span class='text_page_counter'>(1)</span>Bài File bài làm File dữ liệu File kết quả Bài 1: Dãy con lồi DAYLOI.PAS DAYLOI.INP DAYLOI.OUT Bài 2: Dây chuyền thông báo THONGBAO.PAS THONGBAO.INP THONGBAO.OUT Bài 3: Bày tranh PICTURE.PAS PICTURE.INP PICTURE.OUT Bài 1 - Dãy con lồi Dãy giá trị nguyên A=(A1, A2, …, AN) được gọi là lồi, nếu nó giảm dần từ A1 đến một Ai nào đó, rồi tăng dần tới AN. Ví dụ dãy lồi: 10 5 4 2 −1 4 6 8 12 Yêu cầu: Lập trình nhập vào một dãy số nguyên, bằng cách xóa bớt một số phần tử của dãy và giữ nguyên trình tự các phần tử còn lại, ta nhận được dãy con lồi dài nhất. Dữ liệu: Dayloi.inp có dạng - Dòng đầu là N (N≤2000) - Dòng tiếp theo là N số nguyên của dãy số (các số kiểu integer) Kết quả: Dayloi.out gồm: - Dòng đầu tiên ghi số phần tử lớn nhất của dãy con tìm được - Dòng tiếp theo ghi các số thuộc dãy con (không thay đổi trật tự các phần tử trong dãy ban đầu) Ví dụ. Bài 2 - Dây chuyền thông báo Các học sinh trong một lớp học quyết định lập một dây chuyền thông báo như sau. Mỗi học sinh chọn một học sinh duy nhất khác làm người kế tiếp để truyền trực tiếp thông báo. Khi mỗi học sinh nhận được thông báo, anh ta sẽ truyền ngay cho người kế tiếp của mình. Dây chuyền thông báo được gọi là tốt nếu nó thoả mãn điều kiện: Khi một học sinh A 1 bất kỳ gửi thông báo cho người kế tiếp A2, A2 lại gửi cho người kế tiếp A 3,..., cứ như vậy thì cuối cùng thông báo sẽ đến mọi người trong lớp kể cả người ban đầu (A1) đã phát ra thông báo. Không nhất thiết mọi dây chuyền thông báo là tốt. Bài toán đặt ra là: Cho trước một dây chuyền thông báo, hãy tìm số ít nhất việc thay đổi người kế tiếp để có thể nhận được một dây chuyền thông báo tốt. Dữ liệu: file văn bản THONGBAO.INP trong đó dòng thứ nhất ghi số N < 10000 là số hcjc sinh trong lớp, các họcc sinh này có tên từ 1 đến N. Trong dòng tiếp theo ghi N số, số thứ i là tên người kế tiếp của học sinh i. Kết quả: file THONGBAO.OUT như sau: dòng thứ nhất ghi số K là số thay đổi cần tiến hành (nếu dây chuyền thông báo đã cho là tốt thì K=0). Nếu K>0, trong K dòng tiếp theo, mỗi dòng ghi hai tên học sinh, người sau là người kế tiếp mới được thay đổi của người trước.. Ví dụ: THONGBAO.INP 10 6 9 2 7 3 1 10 3 6 9. THONGBAO.OUT 3 14 10 8 85. Bài 3 - Bày tranh Cho n bức tranh mã số từ 1..n (n≤50). Người ta cần chọn ra một bức để đặt ở cửa phòng tranh, số còn lại được treo thẳng hàng trong phòng trên m vị trí định sẵn có mã số 1..m từ trái qua phải. Các bức tranh phải được treo theo trật tự nghiêm ngặt sau đây: tranh có số hiệu nhỏ phải treo ở trên tranh có số hiệu lớn. Biết các thông tin sau về mỗi bức tranh: - Tranh thứ i treo tại cửa sẽ đạt trị thẩm mỹ c[i]; - Tranh thứ i treo tại vị trí j sẽ đạt trị thẩm mỹ v[i,j]. - m+1≥n. - Các giá trị thẩm mỹ là những số tự nhiên không vượt quá 50. Yêu cầu: Hãy xác định một phương án treo tranh để có tổng trị thẩm mỹ là lớn nhất. Dữ liệu: Picture.INP - Dòng thứ nhất ghi n, m (cách nhau 1 dấu cách) - Dòng tiếp theo là n giá trị c. - Tiếp đến là n dòng, dòng i gồm m vị trí v[i,1], v[i,2],..v[i,m]. Kết quả: Picture.OUT - Dòng thứ nhất ghi giá trị thẩm mỹ lớn nhất tìm được - Dòng thứ hai: ghi mã số hiệu bức tranh treo ở cửa phòng tranh. - Dòng thứ 3 ghi n-1 số tự nhiên sắp tăng chặt cho biết mã số các vị trí được chọn để treo tranh Ví dụ:.
<span class='text_page_counter'>(2)</span> Tư tưởng thuật toán: Bài 1 - Dãy con lồi Phân tích bài toán: Theo định nghĩa của đề bài: "Dãy giá trị nguyên A =(A 1, A2, A3,.., AN) được gọi là lồi, nếu nó giảm dần từ A1 đến một Ai nào đó, rồi tăng dần tới AN" ta thấy rằng phần tử đặc biệt trong một dãy lồi là điểm gãy Ai, dãy đơn điệu tăng về hai phía của điểm gãy. Do không được định nghĩa rõ nên ở đây chúng ta tự ngầm định: 1<i< N (nếu trùng với 1 hoặc N thì dãy trở thành đơn điệu tăng hoặc giảm. Từ nhận xét trên, ta giải quyết bài toán như sau: - Xây dựng mảng U thoả mãn: U[i] số phần tử của dãy giảm dài nhất là dãy con của dãy X 1, X2, .. , Xi, với Xi là phần tử nhỏ nhất của dãy con.. - Xây dựng mảng D thoả mãn: D[i] số phần tử của dãy tăng dài nhất là dãy con của dãy X i, Xi+1, .., Xn, với Xi là phần tử nhỏ nhất của dãy con.. - Điểm gãy được chọn là điểm vt thoả mãn:. (D[i]>1 và D[j]>1 để đảm bảo điểm gãy không nằm ở đầu mút) Độ dài của dãy lồi dài nhất là: U[vt]+D[vt]-1. Lưu ý: Do đề bài nên một số bài cho kết quả là những dãy đơn điệu, còn một số trả lời là không có dãy lồi, cả hai kết quả trên đều được chấp nhận. Bài giải sẽ cho kết quả là 0 với những dãy chỉ có điểm gãy trùng với một trong hai điểm đầu mút. Bài 2 - Dây chuyền thông báo Thực chất đây là một bài toán đồ thị, nếu ta coi mỗi học sinh là một đỉnh, thì đỉnh i nối với đỉnh j khi học sinh j là người kế tiếp của học sinh i. Ta thấy một học sinh j có thể là người kế tiếp của rất nhiều học sinh khác, hoặc sẽ không là người kế tiếp của bất kì học sinh nào (tức là sẽ không có đỉnh i nào nối tới j). Gả sử ta có một học sinh jo như vậy, jo sẽ chọn cho mình một nguời kế tiếp j 1, sau đó j1 lại chọn cho mình người kế tiếp j 2,… quá trình này cứ tiếp diễn cho đến khi nguời kế tiếp mà j n chọn trùng với người kế tiếp của ji nào đó. Ta có thể hình dung jo… jn đã tạo nên một cây với gốc là jo (cây không phân nhánh có gốc là jo ngọn là jn). Như vậy mỗi học sinh j không được ai chọn là người kế tiếp đều tạo ra một cây, giả sử có a cây như thế. Những học sinh không tham gia ở bất kì một cây nào sẽ tạo ra những chu trình (vì mỗi học sinh của nhóm này đều được một học sinh của nhóm chọn là người kế tiếp). Giả sử có b chu trình, bây giờ ta sẽ tìm cách ghép a cây và b chu trình (ta coi chu trình là một cây khép kín, đỉnh i bất kì của nó là ngọn, đỉnh i+1 là gốc) để tạo ra một chu trình duy nhất. Rất đơn giản ta chỉ việc lấy ngọn của cây này ghép với gốc của cây kia như vậy ta cần ít nhất a+b cách thay đổi để nhận được một dây chuyền thông báo tốt. Bài 3 - Bày tranh Đây là một biến thể của bài toán quy hoạch động. Đầu tiên ta sẽ thử treo bức tranh k ở cửa (k = 1..n), sau đó ứng với k ta sẽ tìm cách treo n −1 bức còn lại vào trong phòng, sau đó ta tìm giá trị thẩm mĩ lớn nhất ứng với k. Nếu nó lớn hơn các giá trị thẩm mỹ ứng với k khác thì ta ghi nhận, cuối cùng ta sẽ có được giá trị lớn nhất Như vậy bài toán trên thực ra là bài toán tìm giá trị thẩm mỹ lớn nhất khi treo n −1 bức tranh vào m vị trí. Để giải bài toán trên chúng ta có nhận xét sau: vì các bức tranh phải xếp theo thứ tự số hiệu nên với mỗi bức tranh i thì chúng ta chỉ có thể đặt tại sl = m − (n−1)+1 vị trí mà thôi, cụ thể với bức tranh i có thể đặt tại vị trí start đến finish trong đó start = i, finish = i+sl−1 nếu i <k (k là bức tranh treo ở cửa) start =i-1; finish=i+sl-2 nếu i>k gọi s[i,j] là độ thẩm mỹ lớn nhất nếu treo bức tranh i ở vị trí j (như vậy j=start..finish). Với mỗi vị trí có thể đặt được của bức tranh i ta sẽ so sánh với bức tranh tri (tri là bức tranh treo trước bức tranh i; tri = i-1 nếu i<>k+1 và tri=i-2 nếu i=k+1), để tìm max s[i,j], khi i được treo ở j thì tri chỉ có thể được treo ở start −1 tới j −1, vì vậy hàm quy hoạch động của ta sẽ là: s[i,j]:=max(s[i,j], s[tri,u]+v[i,j]); trong đó u= start −1 tới j −1 Để tìm lại kết quả chúng ta dùng mảng Tr (tr[i,j] tức là vị trí treo bức tranh tri) Cách làm trên sẽ được trình bày ở bài giải (ở đây giải quyết với maxM=150, vì đề bài không nói rõ MaxM, chúng ta hoàn toàn có thể tăng maxM bằng việc sử dụng thêm mảng động)..
<span class='text_page_counter'>(3)</span> Ngoài cách xử lý trên chúng ta có thể viết chương trình quy hoạch động dễ dàng bằng cách, ứng với mỗi bức tranh k được treo ở cửa thì ta sẽ loại bức tranh đó ra khỏi mảng v, tức là trong mảng v chỉ còn n −1 hàng. Việc làm này được thực hiện đơn giản bằng mảng cs[i] i=1… n−1 trong đó cs[i] là chỉ số của bức tranh sẽ được bố trí ở trong phòng, như vậy trong mảng cs sẽ không có giá trị cs[i] = k. Bài 1 - Dãy con lồi. const fin=’DAYLOI.INP’; fou=’DAYLOI.OUT’; nmax=2000; type arr= Array[0..nmax+1] of integer; var A: arr; U,Tru,D,TrD: arr; {Up, Down} n, KyLuc, Vitri: integer; f: text;. begin assign(f,fou); rewrite(f); writeln(f,KyLuc); if KyLuc >0 then begin GhiLen(ViTri); GhiXuong(TrD[ViTri]); end; close(f); end; procedure ChuanBi; var i: integer; begin for i:=1 to n do begin U[i]:=1; D[i]:=1; TrU[i]:=0; TrD[i]:=0; end; end; procedure Up; var i,j: integer; begin for i:=1 to n do for j:=1 to i-1 do if (A[i]then begin U[i]:=U[j]+1; TrU[i]:=j; end; end;. Procedure Down; var i,j :integer; begin for i:=n downto 1 do for j:=n downto i+1 do if (A[i] begin D[i]:=D[j]+1; TrD[i]:=j; end; end;. Bài 2 - Dây chuyền thông báo uses crt; const max=10001; fi=’thongbao.inp’; fo=’thongbao.out’; fu=’thongbao.luu’; var next:array[1..max] of integer; tt,ok:array[1..max] of byte; count,n:integer; f,g:text;. read(f,next[i]); tt[next[i]]:=1; end; close(f); assign(f,fu); rewrite(f); count:=0; end;. end; writeln(f,k,’ ’,finish); end;. procedure init; var i,j:integer; begin assign(f,fi); reset(f); fillchar(tt,sizeof(tt),0); readln(f,n); for i:=1 to n do begin. procedure get_tree(k:integer); var i,finish:integer; begin inc(count); i:=k; while ok[i]=0 do begin ok[i]:=1; finish:=i; i:=next[i];. procedure Nhap; var i: integer; begin assign(f,fin); reset(f); readln(f,n); for i:=1 to n do read(f,A[i]); close(f); end; procedure GhiLen(i: integer); begin if TrU[i]<>0 then GhiLen(TrU[i]); Write(f,A[i],’ ’); end; procedure GhiXuong(i: integer); begin Write(f,A[i],’ ’); if TrD[i]<>0 then GhiXuong(TrD[i]); end; procedure Xuat; var i: integer;. procedure TimDiemGay; var i: integer; begin KyLuc:=0; for i:=1 to n do if (U[i]>1) and (D[i]>1) and (U[i] +D[i]-1>KyLuc) then begin KyLuc:=U[i]+D[i]-1; Vitri:=i; end; end; BEGIN Nhap; ChuanBi; Up; Down; TimDiemGay; Xuat; END. procedure main; var i,j:integer; begin fillchar(ok,sizeof(ok),0); for i:=1 to n do if tt[i]=0 then get_tree(i); {cay} for i:=1 to n do if ok[i]=0 then get_tree(i);{chu trinh} close(f); end; procedure show; var start,finish,store_start,i:integer; begin.
<span class='text_page_counter'>(4)</span> assign(f,fu); reset(f); assign(g,fo); rewrite(g); writeln(g,count); read(f,store_start); for i:=1 to count-1 do begin. readln(f,finish); read(f,start); writeln(g,finish,’ ’,start); end; readln(f,finish); writeln(g,finish,’ ’,store_start); close(f); close(g);. end;. Bài 3 - Bày tranh const MaxN = 51; MaxM = 150; fi=’picture.inp’; fo=’picture.out’; type mang =array[0..MaxN,0..maxM] of byte; mang1 =array[0..MaxN,0..maxM] of integer; var f:text; n,m,lvtr,luumax,lk,ln:longint; c:array[0..maxN] of byte; v,tr,ltr:mang; s,ls:mang1; procedure int; var i,j:integer; begin assign(f,fi); reset(f); readln(f,n,m); for i:=1 to n do read(f,c[i]); for i:=1 to n do for j:=1 to m do read(f,v[i,j]); close(f); assign(f,fo); rewrite(f); luumax:=0; end; {*--------------------*} procedure check_result(k:byte); var j,max,vtr,so:longint; begin max:=0; so:=n; if n=k then dec(so); for j:=1 to m do. if s[so,j] > max then begin max:=s[so,j]; vtr:=j;end; if max+c[k] > LuuMax then begin LuuMax:=max+c[k]; ls:=s; ltr:=tr; lvtr:=vtr; lk:=k; ln:=so; end; end; {*--------------------*} procedure process; var i,j,sl,k,u,start,finish,tri:integer; begin sl:=m-n+2; {so luong} for k:=1 to n do begin fillchar(s,sizeof(s),0); for i:=1 to n do if i<>k then begin start:=i; finish:=i+sl-1; if i>k then begin dec(start); dec(finish); end; for j:=start to finish do for u:=start-1 to j-1 do begin tri:=i-1; if i = k+1 then dec(tri); if s[i,j]. begin s[i,j]:=s[tri,u]+v[i,j]; tr[i,j]:=u; end; end; end; check_result(k); end; end; {*--------------------*} procedure inkq(n,m:byte); var trn:byte; begin if n > 0 then begin trn:=n-1; if n = lk+1 then dec(trn); inkq(trn,ltr[n,m]); write(f,m,’ ’); end; end; {*--------------------*} procedure print; var i,j:integer; begin writeln(f,luumax); writeln(f,lk); inkq(ln,lvtr); close(f); end; {*--------------------*} BEGIN int; process; print; END. begin init; main; show; end.. Bài 1: Thẻ tín dụng Vào năm 21xx, tiền mặt trở thành một món đồ cổ. Người ta giao dịch hầu hết qua các thẻ tín dụng. Hôm nay bạn được tham quan một nhà máy sản xuất thẻ. Những chiếc thẻ được sản xuất theo một quy trình đặc biệt. Nhà máy có 3 máy tự động in thẻ, mỗi máy nhận đọc một tấm thẻ có ghi hai số nguyên dương và đưa ra một tấm thẻ mới theo nguyên tắc sau: Sau khi đọc thẻ có ghi cặp số (a, b), máy thứ nhất (1) in ra thẻ có cặp số (a-b, b), máy thứ hai (2) in ra thẻ có cặp số (a+b, b) và máy thứ ba (3) in ra thẻ có cặp số (b, a). Do có lỗi trong khâu lập trình, toàn bộ các thẻ sản xuất ra trong ngày trước đều bị ghi sai số. Người ta phải tái chế lại các thẻ đó, rủi thay lập trình viên của nhà máy đang nghỉ phép, bạn hãy lập trình giúp nhà máy. Yêu cầu: Với một tấm thẻ (a, b) hãy tìm cách đổi tấm thẻ thành (c, d) bằng cách sử dụng một loạt các thao tác trên các máy (1), (2) hoặc (3) hoặc thông báo tấm thẻ đó bị hỏng do không thể dùng các máy trên đổi được. Input: File The.Inp gồm một dòng duy nhất ghi 4 số a b c d (1 ≤ a, b, c, d ≤ 2.10 9) Ouput: Ghi ra file The.Out nếu thẻ bị hỏng thì ghi ra số -1, ngược lại ghi ra quy trình đổi thẻ mỗi dòng ghi ra số hiệu máy xử lý thẻ 1, 2 hoặc 3 tương ứng..
<span class='text_page_counter'>(5)</span> Ví dụ: The.Inp 3 4 11 15. The.Out 2 2 3 2 3. Bài 2: Quan hệ Có N người mang tên tương ứng là 1, 2, ..., N và tình trạng quen biết của N người này được cho bởi mảng đối xứng A[1..N,1..N] trong đó A[i,j] = A[j,i] = 1 nếu i quen j và bằng 0 nếu i không quen j. Hãy xét xem liệu có thể chia N người đó thành 2 nhóm mà trong mỗi nhóm hai người bất kì đều không quen nhau? Dữ liệu vào được cho bởi file QHE.INP trong đó dòng thứ nhất ghi số nguyên dương N <= 100, trong N dòng tiếp theo, dòng thứ i ghi N số A[i,1], ..., A[i,N]. Kết quả ghi ra file QHE.OUT như sau: oNếu không có thể , ghi -1 oNếu có thể, ghi ra hai dòng, dòng thứ nhất tên những người thuộc nhóm 1, dòng thứ hai tên những người thuộc nhóm 2. Ví dụ: QHE.INP. QHE.OUT. 11 01001100000 10100000000 01000000000 00001100100 10010000000 10010010000 00000100010 00000000110 00010001000 00000010001 00000000010. 1 3 4 7 8 11 2 5 6 9 10. Bài 3: GRAY CODE Một hình tròn được chia thành 2n hình quạt đồng tâm. Hãy xếp tất cả các xâu nhị phân độ dài n vào các hình quạt, mỗi xâu vào một hình quạt sao cho bất kì hai xâu nào ở hai hình quạt cạnh nhau đều chỉ khác nhau đúng 1 bit. Ưùng với mỗi n xuất ra 2 khả năng khác nhau. Vd n=2 (hình 1). Hình 1. input Output (gcode.out) N=2 00 10 11 01 ********** 00 01 11 10 Hình 2. Yeâu caàu ◦ Input : nhập từ bàn phím một số n (1<n<=11) ◦ Output : Gcode.out Mỗi xâu ghi trên một dòng. Giữa 2 khả năng cách nhau bởi chuỗi ‘*************’ Câu 1: TÍNH TỔNG Trên một màn hình lớn, người ta lần lượt cho hiện ra các số của một dãy gồm N số nguyên không âm a 1, a2, …, aN và cứ lặp đi lặp lại như thế. Mỗi người theo dõi màn hình được đề nghị tính tổng của K số nguyên liên tiếp xuất hiện trên màn hình bắt đầu từ số nguyên thứ B. Viết chương trình giúp cho những người theo dõi màn hình tính được tổng như đề nghị..
<span class='text_page_counter'>(6)</span> Dữ liệu vào: chứa trong tệp văn bản SUM.INP gồm hai dòng + Dòng đầu tiên ghi ba số nguyên N, K và B, 1 N 100, 1 K 100, 1 B 109. + Dòng thứ hai chứa dãy số nguyên không âm a1, a2, …, aN. Dữ liệu ra: ghi vào tệp văn bản SUM.OUT gồm một dòng chứa tổng cần tính. Ví dụ: SUM.INP SUM.OUT 5 7 154 24 1 2 3 4 5 Chương trình tham khảo: PROGRAM Tinh_Tong; CONST fi=’SUM.INP’; fo=’SUM.OUT’; VAR N, K, B, i : longint; S : longint; a : array[0..100] of longint; f: text; PROCEDURE DocFile; Var f: text; i: integer; Begin Assign(f, fi); Reset(f); Readln(f, N, K, B);. For i:=0 to N do Read(f, a[i]); Close(f) End; BEGIN Assign(f, fo); Rewrite(f); DocFile; S := 0; For i := B to B+K-1 do S := S + a[(i-1) mod N]; Write(f, S); Close(f); END.. Câu 2: ĐẲNG THỨC Cho một đẳng thức sai có dạng A=S (với A, S là hai số nguyên không âm). Viết chương trình tìm cách thêm vào giữa các chữ số của số nguyên A một số phép cộng để nhận được một đẳng thức đúng, sao cho số phép cộng thêm vào là ít nhất có thể được. Dữ liệu vào: chứa trong tệp văn bản EQ.INP gồm một dòng là đẳng thức sai A = S. Dữ liệu ra: ghi vào tệp văn bản EQ.OUT gồm một dòng chứa đẳng thức đúng sau khi đã thêm vào các phép cộng. Ví dụ: EQ.INP EQ.INP 143175=120 5025=30 EQ.OUT EQ.OUT 14+31+75=120 5+025=30 PROGRAM Dang_Thuc; CONST fi=’EQ.INP’; fo=’EQ.OUT’; inf = 1000000000; VAR n, S : longint; i, j : longint; ch : char; KQ: String; A : array[1..1000] of longint; B : array[1..1000] of longint; memo : array[1..1000,0..5000] of longint; PROCEDURE KhoiTao; Var f: text; Begin Assign(f, fi); Reset(f); n:=0; Read(f, ch); Repeat Inc(n); A[n]:= Ord(ch) – 48; Read(f, ch); Until ch=’=’; Readln(f, S); Close(f); B[n] := n;. For i := n-1 downto 1 do if A[i] = 0 then B[i] := B[i+1] else B[i] := i; For i := 1 to n do For j := 0 to S do memo[i,j] := -1; KQ:=’’; End; PROCEDURE GhiFile; Var f: text; Begin Assign(f, fo); Rewrite(f); Write(f, KQ); Close(f); End; FUNCTION Opt( i, sum : longint ) : longint; Var j, broj : longint; Begin if i > n then begin if sum = 0 then opt := 0 else opt := inf; end else begin if memo[i,sum] = -1 then begin memo[i,sum] := inf; broj := 0;.
<span class='text_page_counter'>(7)</span> for j := B[i] to n do begin broj := broj * 10 + A[j]; if broj > sum then break; if 1 + opt( j+1, sum-broj ) < memo[i,sum] then memo[i,sum] := 1 + opt( j+1, sum-broj ); end; end; Opt := memo[i,sum];. if i > 1 then KQ:=KQ + '+'; broj := 0; for j := i to n do begin KQ:=KQ + Chr(A[j]+48 ); broj := broj * 10 + A[j]; if opt( i, sum ) = 1 + opt( j+1, sum-broj ) then begin Xuly( j+1, sum-broj ); break; end; end; end; End; BEGIN KhoiTao; Xuly(1, S ); GhiFile; END.. end; End; PROCEDURE Xuly( i, sum : longint ); Var f: text; j, broj : longint; Begin if i > n then begin KQ:=KQ + '=’+ Str(S ); end else begin Câu 3: TRẠM CANH Tại một vùng đất nọ, người ta bố trí các trạm canh để cảnh báo nguy cơ cho toàn vùng. Mỗi trạm canh gồm có một đài lửa và một cung thủ được trang bị một số lượng tên nhất định. Khi có nguy cơ xuất hiện, một trạm được chỉ định làm trạm xuất phát sẽ tự đốt lửa báo hiệu, sau đó người cung thủ của trạm sẽ bắn tên để thắp lửa cho các trạm khác theo những chỉ thị cho sẵn. Đến lượt mình, mỗi trạm sau khi được thắp lửa, người cung thủ của trạm lại bắn tên để thắp lửa cho các trạm khác, cũng theo những chỉ thị cho sẵn. Việc bắn tên của mỗi cung thủ chỉ kết thúc khi đã sử dụng hết số tên được cấp hoặc khi tất cả các trạm đã được thắp lửa báo hiệu. Xem vùng đất như một mặt phẳng toạ độ và mỗi trạm canh được đặt tại một toạ độ nhất định. Viết chương trình xác định thời điểm mà mỗi trạm được thắp lửa báo hiệu. Giả sử thời gian để một cung thủ bắn tên thắp lửa cho trạm kế tiếp bằng khoảng cách giữa hai trạm (thời gian giữa các loạt bắn là không đáng kể) và trạm số 1 được chỉ định là trạm xuất phát. Ngoài ra, ta cũng giả sử mỗi cung thủ luôn bắn trúng đích. Dữ liệu vào: chứa trong tệp văn bản SPARK.INP có dạng như sau: + Dòng đầu chứa số nguyên dương N (1 N 100) cho biết số trạm canh. + N dòng tiếp theo mỗi dòng chứa N+2 số nguyên theo thứ tự cho biết các thông tin sau: Hai số nguyên X, Y (1 X,Y 1000) cho biết toạ độ của trạm. Số nguyên S (1 N 100) cho biết lượng cung tên được cấp cho trạm. N-1 số nguyên cho biết thứ tự các trạm được chỉ định cho người cung thủ phải bắn tên để thắp lửa tiếp theo. Dữ liệu ra: ghi vào tệp văn bản SPARK.OUT gồm N dòng, mỗi dòng ghi thời điểm mà trạm tương ứng được thắp lửa báo hiệu. Các thời điểm ghi dưới dạng số thập phân với độ chính xác đến 0.001 Ví dụ: SPARK.INP SPARK.OUT 4 0.000000 1 1 1 2 3 4 1.000000 1 2 1 4 1 3 3.000000 2 1 1 2 1 4 2.000000 2 2 1 3 2 1 Chương trình tham khảo: PROGRAM Tram_Canh; CONST fi=’SPARK.INP’; fo=’SPARK.OUT’; VAR n : longint; x, y, S : array[1..100] of longint; A : array[1..100,1..99] of longint; thoidiem : array[1..100] of real; daxet : array[1..100] of boolean; d : array[1..100,1..100] of real; PROCEDURE KhoiTao; Var f: text; i, j: integer; Begin Assign(f, fi); Reset(f);. Readln(f, n); For i := 1 to n do begin read(f, x[i], y[i], S[i]); for j := 1 to n-1 do read(f, A[i,j]); thoidiem[i] := 1000000000; daxet[i] := false; end; Close(f); For i := 1 to n do for j := 1 to n do d[i,j] := sqrt( (x[i]-x[j])*(x[i]x[j]) + (y[i]-y[j])*(y[i]-y[j]) );.
<span class='text_page_counter'>(8)</span> thoidiem[1] := 0; End; PROCEDURE Xuly; Var i, j: integer; truoc_i, tiep : longint; Begin For i := 1 to n do begin truoc_i := 0; for j := 1 to n do begin if daxet[j] then continue; if truoc_i = 0 then truoc_i := j; if thoidiem[j] < thoidiem[truoc_i] then truoc_i := j; end; daxet[truoc_i] := true; for j := 1 to n-1 do begin tiep := A[truoc_i,j]; if daxet[tiep] then continue; if thoidiem[truoc_i] + d[truoc_i,tiep] < thoidiem[tiep] then. thoidiem[tiep] := thoidiem[truoc_i] + d[truoc_i,tiep]; S[truoc_i] := S[truoc_i] - 1; if S[truoc_i] = 0 then break; end; end; End; PROCEDURE GhiFile; Var f: text; i: integer; Begin Assign(f, fo); Rewrite(f); For i:=1 to n do Writeln(f, thoidiem[i]:10:10); Close(f); End; BEGIN KhoiTao; Xuly; GhiFile; END.. Câu 1 (6 điểm) - Cặp số song sinh Hai số a, b được gọi là cặp số song sinh nếu như ở dạng biểu diễn nhị phân thì hai số này không được sai khác nhau quá 1 bit. Yêu cầu: Cho trước hai số nguyên dương a và b (a, b đều nhỏ hơn 1.000.000.000). Hãy kiểm tra hai số a, b có phải là cặp số song sinh hay không. Input: File văn bản s3.inp cấu trúc như sau: - Gồm một số dòng (nhỏ hơn 1.000.000); - Mỗi dòng chứa 2 số cần kiểm tra; - Mỗi số trên dòng cách nhau ít nhất một khoảng trắng. Output: File văn bản s3.out cấu trúc như sau: - Gồm 1 dòng, là những con số 0 hoặc 1 đứng liền nhau tạo thành một dãy số nhị phân. - Tính từ trái sang phải, kí tự thứ i là 1 nếu tại dòng thứ i của file input chứa cặp số song sinh; Ngược lại kí tự tại vị trí thứ i là 0 Ví dụ S3.inp 7 3 8 9. S3.out 11. Câu 2 (7 điểm) - Điền khuyết xâu kí tự Cho trước 2 xâu ký tự a, b (chiều dài của mỗi xâu không quá 100). Yêu cầu: Viết chương trình bổ sung một số ký tự vào a và một số ký tự vào b để hai xâu a và b trở nên giống nhau (phân biệt chữ hoa, thường). Tổng số kí tự bổ sung vào là ít nhất. Input: File văn bản fs.inp cấu trúc như sau: - Bao gồm một số dòng (là số chẵn, có thể lên đến 10.000 dòng). - Mỗi dòng là một xâu kí tự (không quá 100 kí tự). Output: File văn bản fs.out cấu trúc như sau: - Gồm một số dòng (là số dòng của file input chia 2) - Dòng thứ i chứa xâu kí tự là kết quả của việc bổ sung 2 xâu tại dòng thứ i*2-1 và i*2 trên file input. Ví dụ: Fs.inp Abcde Abcdef Abdf Câu 3 (7 điểm) - Dãy đặc biệt Dãy số an cho trước được gọi là dãy đặc biệt nếu thỏa 2 điều kiện : - n là số chính phương; - Các phần tử trong an đôi một khác nhau;.
<span class='text_page_counter'>(9)</span> Các phần tử trong an có thể lần lượt sắp xếp vào ma trận vuông A √ n để A √ n tạo thành một ma phương. Chú ý: Ma phương là một ma trận vuông có tính chất sau: tổng các phần tử trên từng dòng bằng tổng các phần tử trên từng cột và cũng bằng tổng các phần tử trên 2 đường chéo. Yêu cầu: Cho dãy an (với -10.000 < ai < 10.000; n là số nguyên dương nhỏ hơn 3000). Viết chương trình kiểm tra xem dãy an có phải là dãy đặc biệt hay không. Nếu phải thì hãy xuất ma phương ra còn không phải thì xuất ra dòng chữ “khong phai day dac biet”. Input: file văn bản ddb.inp. Dòng đầu tiên chứa số n. Dòng tiếp theo chứa n số lần lượt là các phần tử trong dãy. Mỗi số cách nhau ít nhất một khoảng trắng. Output: file văn bản ddb.out. Dòng đầu tiên chứa số m là cấp của ma phương hoặc là chứa dòng chữ “khong phai day dac biet”. Nếu dòng đầu tiên chứa số m thì m dòng tiếp theo mỗi dòng chứa m số là lượt là các phần tử của ma phương (mỗi số cách nhau 1 khoảng trắng). Ví dụ: ddb.inp ddb.out 5 khong phai day dac biet 24356 (Vì n không phải là số chính phương) -. Bài 2: Var a:array[0..100,0..100] of byte; If (s1[i] = s2[j]) and (a[i,j] = a[i-1,j-1]+ 1) then s1,s2,s3,s4:string; Begin i,j:byte; s3:=s1[i]+s3; Begin dec(j); dec(i); s1:='121212qqw12121212'; End else s2:='121wer21212121212'; If a[i,j] = a[i-1,j] then dec(i) else dec(j); s3:=''; End; For i:=0 to length(s1) do Until (i*j=0); a[0,i]:=0; s4:=''; For i:=1 to length(s2) do For i:=1 to length(s3) do a[i,0]:=0; Begin For i:=1 to length(s1) do s4:=s4+ copy(s1,1,pos(s3[i],s1)-1); For j:=1 to length(s2) do delete(s1,1,pos(s3[i],s1)); Begin s4:=s4+ copy(s2,1,pos(s3[i],s2)-1); If s1[i]=s2[j] then a[i,j]:= a[i-1,j-1]+1 else delete(s2,1,pos(s3[i],s2)); If a[i-1,j]>a[i,j-1] then a[i,j]:= a[i-1,j] s4:=s4+s3[i]; Else a[i,j]:= a[i,j-1]; End; End; s4:=s4+s1+s2; i:= length(s1); Write(s4); j:= length(s2); Readln; Repeat end. Begin Bài 1: LSFIGHT (10đ)Trong kỳ thi năm nay các thí sinh phải tham gia một môn thi đấu đối kháng giữa 2 người. Sau vòng loại, ban tổ chức sẽ chọn ra N thí sinh có số điểm cao nhất và đánh số từ 1 đến N. Các thí sinh này phải xếp lần lượt theo thứ tự thành 1 vòng tròn (người thứ N đứng cạnh người thứ 1). Sau đó sẽ chọn ra 2 thí sinh bất kì đang đứng cạnh nhau trong vòng tròn để thi đấu, thí sinh nào thua sẽ bị loại và buộc phải đi ra vòng tròn, trở về hàng ghế khán giả. Cuộc đấu cứ tiếp tục như thế đến khi chỉ còn một người ở lại và cũng chính là người thắng cuộc. Yêu cầu: Ban tổ chức muốn biết trước xem có bao nhiêu người có khả năng thắng cuộc và đó là những người nào. Biết trước ai sẽ thắng trong mỗi trận đấu, bạn hãy giúp ban tổ chức. Dữ liệu vào: LSFIGHT.INP - Dòng đầu là số nguyên dương N (3<=N<=500). - N dòng sau là ma trận A[i, j], A[i, j] = 0 nếu thí sinh i thua thí sinh j và A[i, j] = 1 nếu ngược lại. Biết rằng luôn đảm bảo A[i, i]=1 với mọi i và A[i, j] + A[j, i] = 1 với i <> j. Các số viết cách nhau ít nhất 1 dấu cách. Kết quả: LSFIGHT.OUT - Dòng đầu là số nguyên dương M - số lượng thí sinh có khả năng thắng cuộc - M dòng sau mỗi dòng ghi một số là chỉ số của thí sinh có khả năng thắng cuộc theo thứ tự tăng dần của chỉ số. Time: 1s.. Ví dụ: LSFIGHT.INP 7 1111101 0101100 0111111. LSFIGHT.OUT 3 1 3 6.
<span class='text_page_counter'>(10)</span> 0001101 0000101 1101111 0100001 Chương trình: const fi='LSFIGHT.INP'; fo='LSFIGHT.OUT'; maxn=501; var f:text; i,j,k,n,sl,sn:word; duoc:array[0..maxn]of boolean; a:Array[0..maxn,0..maxn]of byte; procedure input; begin assign(f,fi); reset(f); readln(f,n); for i:=1 to n do begin for j:=1 to n do read(f,a[i,j]); readln(f); end; close(f); end; procedure solve; begin fillchar(duoc,sizeof(duoc),false); for i:=1 to n do. for j:=1 to n do for k:=1 to n do if (a[i,j]=0)and(a[i,k]=1)and(a[k,j]=1) then a[i,j]:=1; end; procedure output; begin assign(f,fo); rewrite(f); for i:=1 to n do begin sl:=0; for j:=1 to n do if a[i,j]=1 then inc(sl); if sl=n then begin inc(sn);duoc[i]:=true;end; end; writeln(f,sn); for i:=1 to n do if duoc[i] then writeln(f,i); close(f); end; begin input; solve; output; end.. BÀI 2: COMBINE (10đ) Có n đoạn dây xích (N≤20000), mỗi đoạn dây xích là một chuỗi các mắt xích được nối với nhau. Các đoạn dây xích này tách rời nhau. Mỗi đoạn xích có không quá 20000 mắt xích Bằng cách cắt ra một mắt xích, sau đó hàn lại, ta có thể nối hai dây xích thành một đoạn. Thời gian để cắt và hàn mỗi mắt xích là 1 đơn vị thời gian và được xem như bằng nhau với mọi mắt xích. Yêu cầu: Hãy tính thời gian ngắn nhất để nối N đoạn dây xích thành 1 đoạn duy nhất. Dữ liệu vào: COMBINE.INP Dòng đầu ghi số N Dòng thứ 2 ghi N số nguyên dương, mỗi số là độ dài của 1 đoạn xích. Kết quả: COMBINE.OUT Một số duy nhất là thời gian ngắn nhất tìm được. Time: 1s. Ví dụ: COMBINE.INP COMBINE.OUT 4 3 5789 Chương trình: const fi='combine.inp'; begin assign(f,fo); fo='combine.out'; l:=d;r:=c;mid:=a[(d+c)div 2]; rewrite(f); maxn=20001; repeat tong:=0; var f:text; while a[l]<mid do inc(l); for i:=1 to n do i,n:word; while a[r]>mid do dec(r); begin tong:longint; if l<=r then inc(tong,a[i]); a:array[0..maxn]of word; begin if tong>=n-i-1 then break; procedure input; end; tam:=a[l];a[l]:=a[r];a[r]:=tam; begin if tong=n-i-1 then write(f,tong) inc(l);dec(r); assign(f,fi); else write(f,n-i); end; reset(f); close(f); until l>r; readln(f,n); end; if d<r then sort(d,r); for i:=1 to n do read(f,a[i]); begin if l<c then sort(l,c); close(f); input; end; end; sort(1,n); procedure solve; procedure sort(d,c:word); solve; begin var l,r,tam,mid:word; end..
<span class='text_page_counter'>(11)</span> Bài 1(10,0 điểm) - Số hình chữ nhật trên lưới. Trên một tờ giấy kẻ ô vuông, kích thước N x N người ta tạo ra một số hình chữ nhật bằng cách định vị một số ô liên tiếp kề nhau, các hình chữ nhật này từng đôi một không giao nhau, không liền kề theo phép kề đỉnh. Cho bảng A (N x N), giá trị phần tử của bảng được xác định như sau: A[i,j] = 1 nếu ô tương ứng trên tờ giấy thuộc một hình chữ nhật nào đấy. A[i,j] = 0 nếu ô tương ứng trên tờ giấy không thuộc một hình chữ nhật nào cả. Hãy tìm số lượng các hình chữ nhật và các tọa độ đỉnh trái trên, phải dưới của mỗi hình chữ nhật trong bảng. Dữ liệu vào lấy từ file văn bản “HCN.INP” dòng đầu ghi số N. N dòng tiếp theo mỗi dòng là xâu nhị phân độ dài N, giá trị 1 nếu ô tương ứng thuộc một hình chữ nhật, giá trị 0 nếu ô tương ứng không thuộc một hình chữ nhật nào cả. Kết quả ghi ra file văn bản “HCN.OUT” theo cấu trúc: - Dòng đầu ghi số M là số hình chữ nhật có trong bảng. - M dòng tiếp theo mỗi dòng ghi 4 số p, q, r, s với ý nghĩa: cặp số p, q là tọa độ đỉnh trái trên, cặp số r, s là tọa độ đỉnh phải dưới của một hình chữ nhật trong M hình chữ nhật có trên bảng.. Ví dụ: HCN.INP HCN.OUT 7 1110011 1110011 5 0111000 1123 0111011 1627 0000011 3244 1111011 4667 1111000 6174 Bài 2(10,0 điểm) - Di chuyển từ trái sang phải. Cho hình chữ nhật M x N ô vuông, mỗi ô chứa một số nguyên. Có thể di chuyển từ một ô sang ô thuộc cột bên phải cùng dòng hoặc chênh lệch một dòng. Tìm cách di chuyển từ một ô nào đó thuộc cột 1 đến một ô nào đó thuộc cột N sao cho tổng các số nguyên chứa trong các ô đi qua là nhỏ nhất. Dữ liệu vào lấy từ file văn bản “Dichuyen.inp” dòng đầu là 2 số nguyên dương M, N. M dòng tiếp theo mỗi dòng ghi N số nguyên của hình chữ nhật. Kết quả ghi ra file văn bản “Dichuyen.out” gồm 2 dòng: - Dòng thứ nhất ghi tổng các số nguyên chứa trong các ô đi qua. - Dòng thứ hai ghi N số là chỉ số dòng của các ô đi qua từ cột 1 đến cột N.. Ví dụ: DICHUYEN.INP 2 3 5 2 3 4 3 2 I. Phần chương trình nguồn Bài 1: Var f:text; a: array[1..100,1..100] of 0..1; td: array[1..4,1..100] of byte; n, dem: byte; procedure docfile; var i, j : byte; ch: char; begin fillchar(a,sizeof(a),0); dem:=0; assign(f,'hcn.inp'); reset(f); readln(f,n); for i:=1 to n do begin for j:=1 to n do begin read(f,ch); if ch= '1' then a[i,j]:= 1; end; readln(f); Bài 2:. DICHUYEN.OUT 8 2 1 2. end; close(f); end; procedure tim; var i,j,k,l,d,c:byte; begin for i:=1 to n do for j:=1 to n do if a[i,j]=1 then begin inc(dem); td[1,dem]:=i; td[2,dem]:=j; d:=i; c:=j; while (d<n) and (a[d+1,j]=1) do inc(d); while (c<n) and (a[i,c+1]=1) do inc(c); td[3,dem]:=d; td[4,dem]:=c;. for k:=i to d do for l:=j to c do a[k,l]:=0; end; end; procedure vietfile; var i:byte; begin assign(f,'hcn.out'); rewrite(f); writeln(f,dem); for i:=1 to dem do writeln(f,td[1,i],' ',td[2,i],' ',td[3,i],' ',td[4,i]); close(f); end; BEGIN docfile; tim; vietfile; END..
<span class='text_page_counter'>(12)</span> uses crt; const maxmn = 100; fi = 'bt.inp'; fo = 'bt.out'; var a,t :array[0..maxmn,0..maxmn] of integer; kq :array[1..maxmn] of byte; m,n :byte; procedure doc_file; var f :text; i,j:byte; begin assign(f,fi); reset(f); readln(f,m,n); for i:=1 to m do begin for j:=1 to n do read(f,a[i,j]); readln(f); end; close(f); end; function min(i,j:byte):byte; var p: integer; d: byte; begin p:=a[i-1,j-1]; d:=i-1; if a[i,j-1]< p then begin Bài 1: Test 1 HCN.INP HCN.OUT 7 1110011 5 1110011 1123 0111000 1627 0111011 3244 0000011 4667 1111011 6174 1111000 2 Test 2 1123 5 3244 11100 11100 01110 01110 00000. p:=a[i,j-1]; d:=i; end; if a[i+1,j-1]< p then begin p:=a[i+1,j-1]; d:=i+1; end; min:=d; end; procedure tao_nhan; var i,j,d : byte; begin for j:= 0 to n do a[0,j]:= maxint; for j:= 0 to n do a[m+1,j]:=maxint; fillchar(t,sizeof(t),0); for j:=2 to n do for i:=1 to m do begin d := min(i,j); a[i,j]:= a[d,j-1]+a[i,j]; t[i,j]:=d; end; end; procedure tim_duong; var i,j,d:byte; p :integer; f :text; Bài 2: Test 1: DICHUYEN.INP 2 3 523 432 Test 2: 3 4 5231 4320 1368 Test 3: 4 5 5 2 3 1 -3 4 3 2 0 1 1 3 6 8 -2 1 2 3 4 5. begin p:=maxint; for i:=1 to m do if a[i,n]< p then begin d:=i; p:=a[1,n]; end; j:=n; i:=d; kq[j]:=d; assign(f,fo); rewrite(f); writeln(f,a[i,j]); while j>0 do begin i:=t[i,j]; j:=j-1; kq[j]:=i; end; for j:=1 to n do write(f,kq[j],' '); close(f); end; BEGIN doc_file; tao_nhan; tim_duong; END.. DICHUYEN.OUT 8 212. 6 3222. 3 32221.
<span class='text_page_counter'>(13)</span>