Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 19 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
19
Dung lượng
107,5 KB
Nội dung
Chuyên đề: Một số toán quyhoạchđộng thiên công thức toán - Trang - Một số toán quyhoạchđộng thiên công thức toán I/ Đặt vấn đề Về quyhoạchđộng có nhiều tài liệu, chuyênđề nói đến, xét số tập giảI suy nghĩ theo hớng toán học thuận lợi (tất nhiên giảI theo nhiều cách) II Bài tập Bài Đếm chữ số Tên chơng trình DEMCHUSO.??? Cho số nguyên a vµ b (0 ≤ a ,b ≤ 1000 000 000) Xét tất số nguyên nằm a va b (kể số này) Hãy đếm số lợng chữ số thập phân xuất tất số Ví dụ, với a = 1024 b = 1032, ta có dãy số nguyên: 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032 Trong d·y có 10 chữ số 0, 10 chữ số 1, ch÷ sè 2, ch÷ sè 3, ch÷ sè 4, ch÷ sè 5, ch÷ sè 6, ch÷ sè 7, ch÷ sè 8, ch÷ số Dữ liệu: vào từ file văn DEMCHUSO.INP gồm nhiều dòng (nhng không 5000) Mỗi dòng ứng với test chứa số nguyên a b Kết quả: Đa file văn DEMCHUSO.OUT, kết test dòng, gồm 10 số nguyên cho biết số lợng chữ số 0, 1, 2, ,9 Giữa số cách nhát dÊu kho¶ng trèng VÝ dơ: DEMCHUSO.INP 10 44 497 346 542 1004 502 DEMCHUSO.OUT 1211111111 85 185 185 185 190 96 96 96 95 93 40 40 40 93 136 82 40 40 40 40 107 105 100 101 101 197 200 200 200 200 Bµi ViÕt sè VIETSO.??? Tên chơng trình - Trang - Cho lới ô vuông gồm dòng N cột N 109 Cần biết có cách viết số từ đến 2N vào lới, số ô, số i số i + đợc viết vào ô kề cạnh Dữ liệu: Vào từ file VIETSO.INP gồm dòng chứa số nguyên N Kết quả: đa VIETSO.OUT số cách viÕt VÝ dô VIETSO.INP VIETSO.OUT - Trang - Bài Qua cầu Tên chơng trình CROSS.??? (Bài thi HSG Quốc gia năm 2012) Một nhóm n bạn tập văn nghệ khuya Cả nhóm có đèn pin phải qua cầu gồm m đoạn, đoạn đợc đánh số từ ®Õn m kĨ tõ bê ®ang ®øng sang bê bên Coi vị trí n bạn đứng đoạn thứ đầu cầu bên đoạn thứ m +1 Cây cầu cũ, có số đoạn cầu hỏng vào đợc, cầu chịu đựng đợc sức nặng không hai ngời Để qua cầu an toàn bạn phải tổ chức qua cầu theo cách sau: lợt có hai ngời cầm đèn pin để qua cầu không đợc vào vị trí đoạn cầu bị hỏng Sau hai ngời qua đến đầu cầu bên thi ngời qua cầu phải cử ngời đem đèn pin trở lại đầu cầu bên để bạn khác tiếp tục qua cầu Mỗi đơn cị thời gian, bạn thứ i bớc không ri đoạn, nghĩa bạn thứ i đứng đoạn thứ s cầu bạn di chuyển vào đoạn thứ s+1, s+2, ,s+ ri đoạn không bị hỏng Việc thực bớc đòi hỏi đơn vị thời gian Do có ngời qua cầu nhanh Nếu hai bạn qua cầu họ phải di chuyển qua cầu với thời gian bạn chậm Vì qua khuya nên nhóm bàn tim cách qua cầu sớm đợc Yêu cầu: Cho biết vị trí đoạn càu bị hỏng khả di chuyển bạn (đợc mô tả số r1, r2, ,rn) Hãy tính khoảng thời gian ngắn để n bạn qua đợc cầu Giả thiết có cách để nhóm vợt qua cầu Dữ liệu: Vào từ file văn ban CROSS.INP: Dòng thứ chứa hai số nguyên dơng n m tơng ứng số bạn nhóm số đoạn cầu ( n 10000, m 100000); Dòng thứ hai chứa n số nguyên dơng r1, r2, …,rn (ri ≤100, i = 1, 2, …,n); • Dòng th cha xâu gồm m ký tự mô tả trạng thái cầu Ký tự thứ i xâu đoạn thứ i không bị hỏng vào đợc, đoạn cầu th i bị hỏng vào đợc Các số dòng đợc ghi cách dấu cách - Trang - Kết : ghi file văn CROSS.OUT số nguyên khoảng cách thời gian ngắn để n bạn vợt qua đợc cầu VÝ dô: CROSS.INP 35 224 00100 CROSS.OUT - Trang - III Phân tích Bài Gọi d[i] số chữ số i cần tìm (i = 9) Cách thứ nhất: cách tự nhiên xét tất số từ a đến b (trong trờng hợp a > b) ta việc đổi giá trị cho nh thủ tục tinhd dới đây), với số ta lại xét chữ số Ta có chơng trình tính mảng d nh sau: procedure tinhd; var i,j:longint; k:integer; begin for i:=0 to do d[i]=0; if a>b then begin j:=a; a:=b; b:=j; end; for i:=a to b begin J:=i; while j > begin k := j mod 10; inc(d[k]); J:=j div 10; end; end; end; Cách đơn giản, nhng độ phức tạp thuật toán O(số dòng x b x số chữ số củ b) = O(5000 x 10 x10 9) =O(5 x 1013) ta chØ gi¶i quyÕt tèt a, b ≤ 104 Cách thứ 2: Giả thiết a b Nh cách ta đảm bảo đợc điều Gọi fa[i] số chữ số i số 1, 2, a - Gọi fb[i] số chữ sè i cđa c¸c sè 1, 2, …b Gäi kq[i] số chữ số i số a,a+1, ,b (i = 9) Ta sÏ cã kq[i]:=fb[i]-fa[i]; §Ĩ tÝnh số chữ số i viết số t ®Õn x ta xhØ cÇn xÐt x - Trang - Gọi FX[i] số chữ số i viết 1, 2, …,x, ta cã: FX[i] = Sè ch÷ sè i hàng đơn vị số 1, 2, x + Số chữ số i hàng chục số 1, 2, ,x + Số chữ số i hàng trăm số 1, 2, ,x Ta thử xét chữ số i hàng đơn vị: Số x có dạng xnxn-1.x0 sx0 : Số chữ số s ta có 10, 20, s0 Chữ số đến x0 -1 s+1 ta cã i,1i, 2i, …si Ch÷ sè x0 còng cã s+1 Chữ số x0+1 đến s Ta tính số chữ số vị trí j tổng quát X= sxjq Trong q có j chữ số s cã n-j ch÷ sè ta cã: Sè ch÷ sè vị trí s.10 j xj > 0,ngợc lại (s-1) x 10j + q+1 Số chữ số i, với < i xj lµ s s.10j Ta tổng quát trờng hợp chữ số hàng đơn vị Ta có thủ tục tinh mảng fx nh sau: procedure tinhf(x:longint,var fx:mcso); var s,q,t:longint; i, k:integer; begin for i := to fx[i] := 0; t:=1; q:=0; s :=x; while s > begin k:=s mod 10; s:=s div 10; If k > then fx[0]:=fx[0] + s*t+q else fx[0]:=fx[0]+ (s1)*t+q +1; for i:=1 to k-1 fx[i]:=fx[i]+(s+1)*t; × k > then fx[k]:=fx[k] + s*t+q + 1; for i:=k+1 to fx[i]:=fx[i] + s*t; q: = k*t + q; t:=t *10; - Trang - end; end; Chơng trình uses crt; type mcso=array[0 9] ß int64; const fi =’demchuso.inp’; fo =’demchuso.out’; Var a,b,j:longint; i:integer; fa,fb:mcso; f1,e2:text; procedure mofile; begin assign(f1,fi); reset(f1); assign(f2,fo); rewrite(f2); end; procedure tinhf(x:longint,var fx:mcso); var s,q,t:longint; i, k:integer; begin for i := to fx[i] := 0; t:=1; q:=0; s :=x; while s > begin k:=s mod 10; s:=s div 10; If k > then fx[0]:=fx[0] + s*t+q else fx[0]:=fx[0]+ (s1)*t+q +1; for i:=1 to k-1 fx[i]:=fx[i]+(s+1)*t; × k > then fx[k]:=fx[k] + s*t+q + 1; for i:=k+1 to fx[i]:=fx[i] + s*t; q: = k*t + q; t:=t *10; end; end; - Trang - Begin clrscr; mofile; while not eof(f1) begin readln(f1,a,b); if a>b then begin j:=a; a:=b; b:=j; end; tinhf(a-1,fa); tinhf(b,fb); for i:=0 to write(f2,fb[i]-fa[i],’ ‘); writeln(f2); end; close(f1); close(f2); End - Trang 10 - Bài Để tính số cách viêt số từ ®Õn 2N chóng ta cã thĨ thư viÕt sè vào ô, sau viết số lại - Nếu viết vào ô (1,1) : + Viết vào ô (1,2): có cách viÕt 2n n n +1 + Viết vào ô (2,1), lúc phải viết vào ô (2,2) Bài toán trở thành : tìm số cách viết 2(n-1) số Trong trờng hợp ta có c«ng thøc FG(n) = + FG(n-1) Cã thĨ dung hàm đệquyđể tinh FG(n) Nhng xét thêm chút ta dễ dàng suy FG(n) = n Víi n ≥ ta cã « gãc - Nếu viêt vào ô (1,j) , (1 < j < n) + viÕt vào ô bên phải : ứng dụng kết phía số cách viết j-1 2(n-j) +1 2(nj) … … n-j nj+1 + viết vào ô bên trái : ứng dụng kết phía số cách viết n-j j … … J+1 2j 2j+1 … … Nh vËy số cách viết trờng hớp là: n-j+j-1 = n-1 Với viết vào ô (2,j) ta đợc kết hoàn toàn tơng tự Tổng hợp lại ta có ô góc, 2(n-2) ô không góc: Kết là: 4n + 2(n-2)(n-1) (*) cách viết Hàm F(x) sÏ cho ta sè c¸ch viÕt c¸c sè tõ đến 2x vào lới vuông dòng, x cột mà số i số i+1 kề cạnh function f(x:longint):int64; var y:int64; begin if x=1 then exit(2); y:=x; y:=4*y+2*(y-2)*(y-1); - Trang 11 - exit(y); End; {víi x = lµ trêng hợp đặc biệt, đợc tính riêng, x = mặc du có ô góc, công thức (*) đúng} - Trang 12 - Chơng trình uses crt; const fi =’vietso.inp’; fo =’viet.out’; Var n:longint; f1,e2:text; procedure mofile; begin assign(f1,fi); reset(f1); assign(f2,fo); rewrite(f2); end; function f(x:longint):int64; var y:int64; begin if x=1 then exit(2); y:=x; y:=4*y+2*(y-2)*(y-1); exit(y); End; Begin clrscr; mofile; read(f1,n); writeln(f1,f(n)); close(f1); close(f2); end - Trang 13 - Bài Nhận xét: để giải toán phải tiến hành qua bớc Bíc 1: TÝnh thêi gian qua cÇu nhanh nhÊt cho bạn Bớc : Tính thời gian qua cầu nhanh nhÊt cho c¶ nhãm Nh vËy ta cã thĨ tách toán thành toán nhỏ: Bài toán 1: Cho cầu có độ dài m, ngời có bớc dài r, đơn vị thời gian ngời bớc không r đoạn, nghĩa vị trí s bớc tới vị trí s+1, s+2, ,s+r đoạn không bị hỏng Bài toán dễ dàng đợc giải quyhoạchđộng với hàm tính thêi gian nh sau: f(r) cho ta thêi gian nhanh qua cầu mọt bạn có bớc nhảy r function f(r:integer):longint; var d:aray[-100 100001] of longint; i,j:longint; begin for i:=1 to m+1 d[i]:=100001; for i:=-100 to d[i]:=0; for i:=1 to m+1 if x[i]=0 then for j:=i-r to i-1 if d[i] > d[j]+1 then d[i]:=d[j]+1; f:=d[m+1]; end; Hàm có độ phức tạp O(m r2) Sau giải xong toán 1, ta dễ dàng tính thời gian cho tất bạn cách áp dụng n lần sử dụng hàm f Trong trờng hợp độ phức tạp thuật toán O(n.m.r) lớn Tuy nhiên ri 100, nên ta cần tính thời gian lần cho bạn có bớc dài giông nhau, bên cạnh Từ O(n.m.r) giảm xuống O(m.r2) Ta lại cải tiến hàm f nh sau: Độ phức tạp O(m) function f(r:integer):longint; var d:aray[-100 100001] of longint; - Trang 14 - i,j,v0,v1:longint; begin for i:=1 to m+1 d[i]:=100001; for i:=-100 to d[i]:=0; v0:=0;v1:=0; for i:=1 to m+1 if x[i]=0 then if v0+r > =i then begin d[i]:=d[v0]+1;v1:=i;end else begin d[i]:=d[v1] + 1;v0:=v1;v1:=i; end; f:=d[m+1]; End; Trong v0 vị trí xa bớc trớc V1 vị trí gần i đợc bớc tới Để giải toán dễ dàng ta phải tính thời gian cho nhóm, xếp chúng theo thứ tự tăng dần: việc dễ dàng giải với suy luận bạn ri> rj ti tj Ta có mảng sau: sn[1 100] : s[r] số bạn cã bíc nh¶y r t[1 100] :t[r] thêi gian qua cầu với nhanh với bớc nhảy r tg[1 10000] of longint tg[i] thời gian qua cầu bạn nhanh thø i; procedure nhapdl; var f:text; i,r:integer; begin fillchar(sn,sizÌo(sn),0); assgn(f,fi); readln(f,n,m); for i:=1 to m begin read(f,r); sn[r]:=sn[r]+1; end; readln(f); readln(f,x); close(f); end; procedure tinhtg; - Trang 15 - var ig,k:integer; begin for ig:=1 to 100 if sn[ig]>0 then t[ig]:=f[ig]; k:=0; for ig:=100 downto for jg:=1 to sn[ig] begin k:=k+1; tg[k]:=t[ig]; end; End; Bµi toán 2: Để qua cầu nhanh xét theo quan ®iĨm to¸n häc ta cã sù u tien sau: - Ngời cầm đèn trở lại để bạn qua cầu phải bạn có thời gian nhỏ bạn qua cầu - Ngời chậm với ngời chậm nhì (để giảm thời gian qua cầu) với ngời nhanh (để giảm thời gian đón) Ta giải riêng trờng đặc biệt n = 1, kq = tg[1] n = 2, kq = tg[2] n = 3, kq = tg[1]+tg[2]+tg[3] Ta xÐt víi n = Ta ký hiệu (i,j) bạn i bạn j qua cầu (i) bạn i quay lại Phơng án theo u tiên (1,2) (1) (3,4)(2)(1,2) Thời gian qua cầu nhóm T1 = tg[2]+tg[1]+tg[4]+tg[2]+tg[2]; (tg[3] đợc ẩn đi) Phơng ¸n theo u tiªn trªn (1,2) (1) (1,3)(1)(1,4) Thêi gian qua cầu nhóm T2 = tg[2]+tg[1]+tg[3]+tg[1]+tg[4]; Xét T1-T2 = 2tg[2] – (tg[1] + tg[3]) DÔ thÊy nÕu 2tg[2] < tg[1] + tg[3] theo phơng án lợi hơn, ngợc lại theo phơng án hai lợi Mở rộng cho n bạn (đã xếp theo thời gian tăng dần) Hàm tính kết nh sau: function tinhkq:longint; var k,i:integer; begin - Trang 16 - if n=1 then exit(tg[1]); kq:=0; k:=n; while (k>3) and (2tg[2] < tg[1] + tg[k-1]) begin kq:=kq+tg[2]; {(1,2)} kq:=kq+tg[1]; {(1)} kq:=kq+tg[k]; {(k-1,k)} kq:=kq+tg[2] ; {(2)} k:=k-2; End; for i:=2 to k kq:=kq+tg[i] ; {(1,i)} kq:=kq+(k-2)*tg[1]; exit(kq); end; Đánh giá độ phức tạp: Nhập liệu O(n+m) Tính thời nhan theo nhóm O(m.r) Tính mảng tg O(n) Tính kết O(n) Do nmax nhỏ so với mmax :Đánh giá chung O(m.r) r = max{ri} Từ ta tăng m 107 Chơng trình uses crt; const fi =’cross.inp’; fo =’ cross.out’; Var f:text; n:integer; m:longint; sn:array[1 100] of integer; t:array[1 100] of longint; tg:aray[1 10000] of longint; procedure nhapdl; var f:text; i,r:integer; begin fillchar(sn,sizÌo(sn),0); assgn(f,fi); readln(f,n,m); - Trang 17 - for i:=1 to m begin read(f,r); sn[r]:=sn[r]+1; end; readln(f); readln(f,x); close(f); end; function f(r:integer):longint; var d:aray[-100 100001] of longint; i,j,v0,v1:longint; begin for i:=1 to m+1 d[i]:=100001; for i:=-100 to d[i]:=0; v0:=0;v1:=0; for i:=1 to m+1 if x[i]=0 then if v0+r > =i then begin d[i]:=d[v0]+1;v1:=i;end else begin d[i]:=d[v1] + 1;v0:=v1;v1:=i; end; f:=d[m+1]; End; procedure tinhtg; var ig,k:integer; begin for ig:=1 to 100 if sn[ig]>0 then t[ig]:=f(ig); k:=0; for ig:=100 downto for jg:=1 to sn[ig] begin k:=k+1; tg[k]:=t[ig]; end; end; function tinhkq:longint; var k,i:integer; - Trang 18 - begin if n=1 then exit(tg[1]); kq:=0; k:=n; while (k>3) and (2tg[2] < tg[1] + tg[k-1]) begin kq:=kq+tg[2]; {(1,2)} kq:=kq+tg[1]; {(1)} kq:=kq+tg[k]; {(k-1,k)} kq:=kq+tg[2] ; {(2)} k:=k-2; end; for i:=2 to k kq:=kq+tg[i] ; {(1,i)} kq:=kq+(k-2)*tg[1]; exit(kq); end; procedure inkq; var g:text; begin; assign(g,fo); rewrite(g); writeln(g,tinhkq); close(g); end; Begin clrscr; nhapdl; tinhtg; inkq; end - Trang 19 -