DeOnTap OLP30 4 de01 02 solution (1)

17 35 0
DeOnTap OLP30 4 de01 02 solution (1)

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

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

đề ôn tập olympic 304 cho học sinh trung học phổ thông, giáo viên, học sinh có thể tham khảo Câu 1. SUMMIN (6 điểm) Trên máy tính thời gian để thự hiện việc tính tổng của hai số nguyên dương là phụ thuộc vào giá trị của chúng. Giả sử khi cộng hai số nguyên dương x và y ta phải trả chi phí thời gian có giá trị bằng 5% giá trị của tổng hai số. Yêu cầu: Cho dãy A gồm N số nguyên dương a1, a2, ..., aN . Cần tìm cách tính tổng của các số này với tổng chi phí thời gian là nhỏ nhất. Input: SUMMIN.inp Dòng đầu tiên ghi số nguyên dương N (2  N  15000) Dòng tiếp theo ghi N số nguyên dương mà ta cần tính tổng, hai số liên tiếp được ghi cách nhau bởi ít nhất một dấu cách ( ai  105 , i =1..N). Output: SUMMIN.out Gồm một dòng ghi tổng chi phí theo cách thực hiện tính tổng tìm được. Kết quả được ghi với hai chữ số sau dấu chấm thập phân.

ĐỀ 01 Câu SUMMIN (6 điểm) Trên máy tính thời gian để thự việc tính tổng hai số nguyên dương phụ thuộc vào giá trị chúng Giả sử cộng hai số nguyên dương x y ta phải trả chi phí thời gian có giá trị 5% giá trị tổng hai số Yêu cầu: Cho dãy A gồm N số nguyên dương a1, a2, , aN Cần tìm cách tính tổng số với tổng chi phí thời gian nhỏ Input: SUMMIN.inp - Dòng ghi số nguyên dương N (2  N  15000) - Dòng ghi N số nguyên dương mà ta cần tính tổng, hai số liên tiếp ghi cách dấu cách (  105, i =1 N) Output: SUMMIN.out Gồm dòng ghi tổng chi phí theo cách thực tính tổng tìm Kết ghi với hai chữ số sau dấu chấm thập phân Ví dụ: SUMMIN.inp SUMMIN.out 0.10 11 2.35 17492 HD: - Để cộng N số lại với nhau, ta cần thực phép cộng (N-1 phép cộng) - Nếu với phép cộng ta chi phí bé tổng N-1 phép cộng ta có tổng chi phí bé - Sử dụng Heap_Min -Tạo Heap_Min chứa n phần tử dãy A: a1, a2, , aN - Gọi Res chi phí thời gian bé cần tìm, khởi tạo Res :=0; - Lặp Lấy hai phần tử bé Heap_Min x:=pop(1); y:=pop(1); Cộng chi phí tính tổng hai số x y vào Res Res:=Res+(x+y)*5/100; Khi công hai số x y sinh giá trị (x+y), nạp giá trị (x+y) vào Heap_Min push(x+y); Cho đến Heap_Min phần tử Kết : Res Chương trình tham khảo Program SUMMIN; Const fi='SUMMIN.inp'; fo='SUMMIN.out'; Var f,g:text; Res:Extended; top,N,K:longint; a:array[0 15000] of longint; q:array[0 15000] of int64; procedure doicho(i,j:longint); var tg:int64; begin tg:=q[i]; q[i]:=q[j]; q[j]:=tg; end; procedure Up_heap(i:longint); begin if (i=1) then exit; if (q[i div 2]>q[i]) then begin doicho(i,i div 2); up_heap(i div 2); end; end; procedure down_heap(i:longint); var j:longint; begin j:=i*2; if j > top then exit; if (jq[j+1]) then j:=j+1; if(q[i]>q[j]) then begin doicho(i,j); down_heap(j); end; end; procedure push(giatri:int64); begin inc(top); q[top]:=giatri; up_heap(top); end; function pop(vitri:longint):int64; begin pop:=q[vitri]; q[vitri]:=q[top]; dec(top); up_heap(vitri); down_heap(vitri); end; Procedure Doc; Var i,j:longint; Begin Assign(f,fi); reset(f); Readln(f,N); For i:=1 to N Read(f,a[i]); Close(f); End; Procedure Xuly; Var i:Longint; x,y:int64; Begin top:=0; For i:=1 to N push(a[i]); Res:=0; While top>1 Begin x:=pop(1); y:=pop(1); Res:=Res+(x+y)*5/100; push(x+y); End; End; Procedure ghi; Var i,j:longint; Begin Assign(g,fo); Rewrite(g); Writeln(g,Res:0:2); Close(g); End; BEGIN doc; xuly; ghi; END Câu FGIRD (7 điểm) Cho xâu S có độ dài 2N-1 lưới vng A có kích thước NxN, ô lưới ghi chữ Một người tìm cách di chuyển góc trái đến góc phải, lần di chuyển quyền sang có chung cạnh bên phải phía cho chữ ô đường di chuyển tạo thành xâu S Yêu cầu: Cho trước lưới ô vuông A xâu S, xác định số cách di chuyển thỏa mãn yêu cầu đặt Input: FGIRD inp - Dòng ghi số N (2≤ N ≤1000); - N dòng tiếp theo, dòng chứa N chữ Latin in thường (không thiết phải khác nhau); - Dòng cuối ghi xâu S gồm 2N-1 chữ Latin in thường Output: FGIRD out Gồm dòng ghi số nguyên phần dư phép chia số cách di chuyển thỏa điều kiện cho 1000003 Ví dụ: FGIRD inp FGIRD out aaa aba baa aabaa HD: - Vị trí (i,j) bảng A tương ứng với vị trí (i+j)-1 xâu S - Gọi L[i,j] số cách di chuyển đến ô A[i,j] để thu xâu S[1 (i+j)-1] - Khởi tạo L[0,1] = L[1,0] =0 L[0,1] = L[1,0] =1 - Cơng thức tính L[i,j]: L[i,j] = a[i,j] s[i+j-1] L[i,j] = L[i-1,j] + L[i, j-1] a[i, j] = s[i+j-1] - Kết L[n,n] Chương trình tham khảo const fi='FGIRD.inp'; fo='FGIRD.out'; max=1000; var f:text; a:array[0 max] of ansistring; s:ansistring; n:longint; l:array[0 max,0 max] of longint; procedure doc; var i,j:longint; begin assign(f,fi);reset(f); readln(f,n); for i:=1 to n readln(f,a[i]); readln(f,s);close(f); end; procedure xuly; var i,j:longint; begin L[0,1] := 1; L[1,0] :=0; for i:=1 to n for j:=1 to n if a[i][j]=s[i+j-1] then l[i,j]:=(l[i,j-1]+l[i-1,j]) mod 1000003 else l[i,j]:=0; end; procedure ghi; begin assign(f,fo);rewrite(f); write(f,l[n,n]); close(f) end; begin doc; xuly; ghi; end Câu FGRAPH( điểm ) Sống thành phố lớn có mật độ dân số cao giao thông phức tạp, ông Bình lo nạn kẹt xe Để thuận tiện cho việc lại, ơng Bình tìm hiểu đường ngắn dẫn từ nhà đến quan Bạn giúp ơng Bình thực cơng việc kho khăn Bản đồ thành phố gồm có N nút giao thông M đường hai chiều nối nút giao thông Độ dài đường số nguyên dương Nhà ông Binh nút giao thơng 1, quan ơng bình nút giao thơng N Input: FGRAPH.inp Dịng thứ ghi hai số nguyên N M (1 ≤ N ≤ 200, ≤ M ≤ 20000) M dòng tiếp theo, dòng ghi số nguyên dương U, V, L ( đường nối U đến V với độ dài L, L ≤ 32000) Output: FGRAPH.out Gồm dòng ghi số lượng đường ngắn Ví dụ: FGRAPH.inp FGRAPH.out 33 123 134 231 Thuật toán: Áp dụng thuật toán Dijkstra HD: Gọi D[i] độ dài đường ngắn từ đến i Gọi Count[i] số lượng đường ngắn từ đến i Giả sử tìm đường số lượng đường ngắn từ đỉnh đến đỉnh u Với đỉnh v kề u, - Nếu đường  u  v ngắn đường  v Nếu D[v]> D[u]+a[u,v] + D[v]=D[u]+a[u,v] + Count[v] = Count[u] - Nếu đường  u  v đường  v Nếu D[v]=D[u]+a[u,v] + L[v] = L[u] + L[v] Count[n] kết cần tìm Chú ý: Ln có đường từ đến n Chương trình tham khảo: Program FGRAPH; const fi='FGRAPH.inp'; fo='FGRAPH.out'; maxn=200; maxm=20000; vc=1000000000; var n,m: longint; f: text; d: array [-1 maxn+4] of longint; count: array [-1 maxn+4] of int64; dd: array [-1 maxn+4] of boolean; c: array [1 maxn+4,1 maxn+4] of longint; procedure doc; var i,j,u,v,t: longint; begin assign(f,fi); reset(f); fillchar(c,sizeof(c),0); readln(f,n,m); for i := to n for j := to n if i = j then c[i, j] := else c[i, j] := vc; for i := to m begin Readln(f, u, v, t); if c[u,v] > t then begin c[u,v] := t; c[v,u] := t; end; end; close(f); end; procedure dijkstra; var i,u,v,min: longint; begin fillchar(dd,sizeof(dd),true); for i:=1 to n count[i]:=0; count[1]:=1; for i:=1 to n d[i]:=vc; d[1]:=0; repeat u := 0; := vc; for i := to n if dd[i] and (d[i] < min) then begin := d[i]; u := i; end; if (u = 0) then Break; dd[u]:=false; for v := to n if dd[v] then if (d[v] > d[u] + c[u, v]) then begin d[v] := d[u] + c[u, v]; count[v]:=count[u]; end else if (d[v]=d[u]+c[u,v]) then count[v]:=count[v]+count[u]; until False; end; procedure ghi; var i: longint; begin assign(f,fo); rewrite(f); write(f,count[n]); close(f); end; BEGIN doc; dijkstra; ghi; END ĐỀ 02 Bài 1: Duyệt kết hợp chặt nhị phân Bài 2: Bánh sinh nhật Nhận xét: Giả sử x[i] vị trí cuối Bình dừng lại ăn bánh để đạt kết tối ưu Ta tốn khoảng thời gian để từ đến x[i], gọi thời gian T0 Cơng việc cịn lại cần làm tìm cách ăn bánh cho số bánh ăn nhiều Dễ dàng nhận thấy việc chọn ăn bánh nhỏ cho tổng thời gian ăn bánh + T0 T pop bánh có thời gian ăn lớn Sau cập nhật lại kết tối ưu Bài 3: Phát biểu ngắn Cho đồ thị có hướng có trọng số dương cung G=(V,E, C), hai đỉnh (s,t) tập cạnh A={ (ui, vi), i=1,2, ,k} Cần chọn cạnh e A cho việc bổ sung vào đồ thị G làm cho độ dài đường từ s đến t giảm nhiều Thuật tốn: Tính d1(s,v) độ dài đường ngắn từ s đến v, v  V \ { s} (1) Tính d2(v,t) độ dài đường ngắn từ v đến t, v  V \ { t} (2) Tính Kq1:=min { d1(s,u) + c(u,v) + d2(v,t) : (u,v) A} Kq2: =min { d1(s,v) + c(u,v) + d2(u,t) : (u,v) A} (3) Khi kq:=min(kq1,kq2, d1(s,t)) đáp số cần tìm CHƯƠNG TRÌNH THAM KHẢO Chương trình đề nghị giải Bài {$Mode ObjFPC} Const fi='GROUP.INP'; fo='GROUP.OUT'; nMax=51; Var a,b:array[1 nMax] of longint; f:text; n,k,i:longint; aMax,Low,High,Mid:int64; Res:int64; Sum:qword; Procedure Enter; Begin 10 Assign(f,fi); Reset(f); Readln(f,n,k); aMax:=0; For i:=1 to n Begin Read(f,a[i]); aMax:=aMax+a[i]; End; Close(f); aMax:=aMax div k +1; End; Function Check(u:int64):boolean; Begin Sum:=0; b:=a; For i:=1 to n Begin If b[i]>u then b[i]:=u; Sum:=Sum+b[i]; End; Exit(Sum>=u*k); End; Procedure Main; Begin Low:=0; High:=aMax; While Low0)and(T[H[c]] L[1][T1] then res := L[1][T1]; if res > L[2][S1] then res := L[2][S1]; for i:=1 to K begin readln(fi,x,y,z); tmp := Cal(x,y,z); if res > tmp then res := tmp; tmp := Cal(y,x,z); if res > tmp then res := tmp; end; if (res = Ulti) then writeln(fo,-1) else writeln(fo,res); END; BEGIN assign(fi,FINP); reset(fi); Process; close(fi); close(fo); assign(fo,FOUT); rewrite(fo); 16 END 17 ... n,m: longint; f: text; d: array [-1 maxn +4] of longint; count: array [-1 maxn +4] of int 64; dd: array [-1 maxn +4] of boolean; c: array [1 maxn +4, 1 maxn +4] of longint; procedure doc; var i,j,u,v,t:... Close(f); End; Procedure Xuly; Var i:Longint; x,y:int 64; Begin top:=0; For i:=1 to N push(a[i]); Res:=0; While top>1 Begin x:=pop(1); y:=pop(1); Res:=Res+(x+y)*5/100; push(x+y); End; End; Procedure... Res:Extended; top,N,K:longint; a:array[0 15000] of longint; q:array[0 15000] of int 64; procedure doicho(i,j:longint); var tg:int 64; begin tg:=q[i]; q[i]:=q[j]; q[j]:=tg; end; procedure Up_heap(i:longint);

Ngày đăng: 22/10/2021, 10:18

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

  • Đang cập nhật ...

Tài liệu liên quan