1. Trang chủ
  2. » Công Nghệ Thông Tin

Chuyên Đề Quy Hoạch Động CĐ5

13 176 0

Đ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

Thông tin cơ bản

Định dạng
Số trang 13
Dung lượng 107,5 KB

Nội dung

Chuyên đề:Một số bài toán quy hoạch động thiên về công “Một số bài toán quy hoạch động thiên về công thức toán “Một số bài toán quy hoạch động thiên về công... Một số bài toán quy hoạch

Trang 1

Chuyên đề:

Một số bài toán quy hoạch động thiên về công

“Một số bài toán quy hoạch động thiên về công

thức toán “Một số bài toán quy hoạch động thiên về công

Trang 2

Một số bài toán quy hoạch động thiên về công thức toán

“Một số bài toán quy hoạch động thiên về công “Một số bài toán quy hoạch động thiên về công

I/ Đặt vấn đề.

Về quy hoạch động đã có quá nhiều tài liệu, chuyên đề nói đến, ở đây chúng ta chỉ xét một số bài tập khi giảI quyết nó nếu suy nghĩ theo hớng toán học sẽ thuận lợi hơn (tất nhiên vẫn có thể giảI theo nhiều cách)

II Bài tập.

Bài 1 Đếm chữ số Tên chơng trình DEMCHUSO.???

Cho 2 số nguyên a và b (0 ≤ a ,b ≤ 1000 000 000) Xét tất cả các số nguyên nằm giữa a va b (kể cả 2 số này)

Hãy đếm số lợng từng chữ số thập phân xuất hiện trong tất cả các số đó

Ví dụ, với a = 1024 và b = 1032, ta có dãy số nguyên:

1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032

Trong dãy này có 10 chữ số 0, 10 chữ số 1, 7 chữ số 2, 3 chữ số 3, 1 chữ số 4, 1 chữ số 5, 1 chữ số 6, 1 chữ số 7, 1 chữ số 8, 1 chữ số 9

Dữ liệu: vào từ file văn bản DEMCHUSO.INP gồm nhiều dòng (nhng không quá

5000) Mỗi dòng ứng với 1 test chứa 2 số nguyên a và b

Kết quả: Đa ra file văn bản DEMCHUSO.OUT, kết quả mỗi test trên một dòng,

gồm 10 số nguyên cho biết số lợng các chữ số 0, 1, 2, ,9 Giữa 2 số cách nhau

ít nhát 1 dấu khoảng trống

Ví dụ:

1 10

44 497

346 542

1004 502

1 2 1 1 1 1 1 1 1 1

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 2 Viết số Tên chơng trình VIETSO.???

cách viết các số từ 1 đến 2N vào lới, mỗi số 1 ô, số i và số i + 1 đợc viết vào 2 ô

kề cạnh

Dữ liệu: Vào từ file VIETSO.INP gồm duy nhất 1 dòng chứa số nguyên N.

Kết quả: đa ra VIETSO.OUT số cách viết.

Ví dụ

Trang 3

Bài 3 Qua cầu Tên chơng trình CROSS.???

(Bài 6 thi HSG Quốc gia năm 2012)

Một nhóm n bạn đi tập văn nghệ về khuya Cả nhóm chỉ có một chiếc đèn pin và phải qua một cây cầu gồm m đoạn, các đoạn đợc đánh số từ 1 đến m kể từ bờ

đang đứng sang bờ bên kia Coi vị trí n bạn đang đứng là đoạn thứ 0 và đầu cầu bên kia là đoạn thứ m +1 Cây cầu đã cũ, do đó có 1 số đoạn cầu đã hỏng và không thể đi vào đợc, hơn nữa cầu chỉ chịu đựng đợc sức nặng của không quá hai ngời Để qua cầu an toàn các bạn phải tổ chức qua cầu theo cách sau: mỗi lợt chỉ

có hai ngời cầm đèn pin để cùng nhau qua cầu và không đợc đi vào những vị trí

đoạn cầu đã bị hỏng Sau khi hai ngời qua đến đầu cầu bên kia thi những ngời đã qua cầu phải cử một ngời đem đèn pin trở lại đầu cầu bên này để các bạn khác

nghĩa là nếu bạn thứ i đang đứng ở đoạn thứ s của cây cầu thì bạn có thể di

Việc thực hiện một bớc đi đòi hỏi 1 đơn vị thời gian Do đó có thể có ngời qua cầu nhanh hơn Nếu hai bạn cùng qua cầu thì họ phải di chuyển qua cầu với thời gian của bạn chậm hơn Vì đã qua khuya nên cả nhóm bàn nhau tim cách qua cầu sớm nhất có thể đợc

Yêu cầu: Cho biết vị trí các đoạn càu bị hỏng và khả năng di chuyển của từng

Dữ liệu: Vào từ file văn ban CROSS.INP:

 Dòng thứ nhất chứa hai số nguyên dơng n và m tơng ứng là số bạn trong nhóm và số đoạn của cây cầu ( n ≤ 10000, m ≤100000);

 Dòng th 3 cha một xâu gồm m ký tự ‘0’ hoặc ‘1’ mô tả trạng thái của cây cầu Ký tự thứ i của xâu là ‘0’ nếu đoạn thứ i không bị hỏng có thể đi vào

đợc, là ‘1’ nếu đoạn cầu th i bị hỏng không thể đi vào đợc

Các số trên cùng một dòng đợc ghi cách nhau ít nhất một dấu cách

Kết quả : ghi ra file văn bản CROSS.OUT một số nguyên là khoảng cách thời gian ngắn nhất để n bạn vợt qua đợc cây cầu

Ví dụ:

3 5

2 2 4

00100

8

Trang 4

III Phân tích

Bài 1 Gọi d[i] là số chữ số i cần tìm (i = 0 9)

Cách thứ nhất: cách tự nhiên nhất là xét tất cả các số từ a đến b (trong trờng hợp a

> b) ta chỉ việc đổi 2 giá trị cho nhau nh ở thủ tục tinhd dới đây), với mỗi số ta lại xét từng chữ số của nó

Ta có chơng trình con tính mảng d nh sau:

procedure tinhd;

var i,j:longint;

k:integer;

begin

for i:=0 to 9 do do d[i]=0;

if a>b then

begin

j:=a; a:=b; b:=j;

end;

for i:=a to b do

begin

J:=i;

while j > 0 do

begin

k := j mod 10;

inc(d[k]);

J:=j div 10;

end;

end;

end;

Cách này cực kỳ đơn giản, nhng độ phức tạp của thuật toán là O(số dòng x b x số

Cách thứ 2: Giả thiết a ≤ b Nh cách 1 ta luôn có thể đảm bảo đợc điều này

Gọi fa[i] là số chữ số i của các số 1, 2, …a - 1

Gọi fb[i] là số chữ số i của các số 1, 2, …b

Gọi kq[i] là số chữ số i của các số a,a+1, …,b

(i = 0 9)

Ta sẽ có kq[i]:=fb[i]-fa[i];

Để tính số chữ số i khi viết các số t 1 đến x ta xhỉ cần xét x

Gọi FX[i] là số chữ số i khi viết 1, 2, …,x, ta có:

FX[i] = Số chữ số i ở hàng đơn vị của các số 1, 2, …x

+ Số chữ số i ở hàng chục của các số 1, 2, …,x

+ Số chữ số i ở hàng trăm của các số 1, 2, …,x

Ta thử xét chữ số i ở hàng đơn vị:

Số chữ số 0 sẽ là s vì ta có 10, 20, …s0

Trang 5

Chữ số x0+1 đến 9 là s.

Ta hãy tính số các chữ số ở vị trí j tổng quát

Ta có thể tổng quát cả 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 := 0 to 9 do fx[i] := 0;

t:=1;

q:=0;

s :=x;

while s > 0 do

begin

k:=s mod 10;

s:=s div 10;

If k > 0 then fx[0]:=fx[0] + s*t+q else fx[0]:=fx[0]+ (s-1)*t+q +1; for i:=1 to k-1 do fx[i]:=fx[i]+(s+1)*t;

ì k > 0 then fx[k]:=fx[k] + s*t+q + 1;

for i:=k+1 to 9 do fx[i]:=fx[i] + s*t;

q: = k*t + q;

t:=t *10;

end;

end;

Chơng trình chí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

Trang 6

for i := 0 to 9 do fx[i] := 0;

t:=1;

q:=0;

s :=x;

while s > 0 do

begin

k:=s mod 10;

s:=s div 10;

If k > 0 then fx[0]:=fx[0] + s*t+q else fx[0]:=fx[0]+ (s-1)*t+q +1; for i:=1 to k-1 do fx[i]:=fx[i]+(s+1)*t;

× k > 0 then fx[k]:=fx[k] + s*t+q + 1;

for i:=k+1 to 9 do fx[i]:=fx[i] + s*t;

q: = k*t + q;

t:=t *10;

end;

end;

Begin

clrscr;

mofile;

while not eof(f1) do

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 9 do write(f2,fb[i]-fa[i],’ ‘);

writeln(f2);

end;

close(f1); close(f2);

End

Trang 7

Bài 2 Để tính số cách viêt các số từ 1 đến 2N chúng ta có thể thử viết số 1 vào 1

ô, sau đó viết các số còn lại

+ Viết 2 vào ô (1,2): có duy nhất 1 cách viết

+ Viết 2 vào ô (2,1), lúc này 3 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 này ta có công thức FG(n) = 1 + FG(n-1) Có thể dung hàm đệ quy để tinh FG(n) Nhng nếu xét thêm 1 chút nữa ta dễ dàng suy

ra FG(n) = n Với n ≥ 2 ta có 4 ô góc

1

+ 2 viết vào ô bên phải : ứng dụng kết quả phía trên số cách viết sẽ là j-1

+ 2 viết vào ô bên trái : ứng dụng kết quả phía trên số cách viết sẽ là n-j

Nh vậy số cách viết trong trờng hớp này là: n-j+j-1 = n-1

Với 1 viết vào ô (2,j) ta đợc kết quả hoàn toàn tơng tự

Tổng hợp lại ta có 4 ô góc, 2(n-2) ô không ở góc:

Kết quả sẽ 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ừ 1 đến 2x vào lới vuông 2 dòng, x cột mà

số i và 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);

exit(y);

End;

{với x = 1 là trờng hợp đặc biệt, đợc tính riêng, còn x = 2 mặc du chỉ có 4 ô góc, công thức (*) vẫn đúng}

Trang 8

Ch¬ng tr×nh chÝ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 9

Bài 3.

Nhận xét: để giải quyết bài toán này chúng ta phải tiến hành qua 2 bớc.

Bớc 1: Tính thời gian qua cầu nhanh nhất cho mỗi bạn.

Bớc 2 : Tính thời gian qua cầu nhanh nhất cho cả nhóm.

Nh vậy ta có thể tách bài toán này thành 2 bài toán nhỏ:

Bài toán 1: Cho cây cầu có độ dài m, một ngời có bớc dài r, mỗi đơn vị thời gian

ngời đó có thể bớc không quá r đoạn, nghĩa là anh ta đang ở vị trí s thì có thể bớc tới các vị trí s+1, s+2, …,s+r nếu đoạn đó không bị hỏng Bài toán 1 dễ dàng đợc giải quyết bằng quy hoạch động với hàm tính thời gian nh sau:

f(r) cho ta thời gian nhanh nhất qua cầu của mọt bạn có bớc nhảy là r

function f(r:integer):longint;

var d:aray[-100 100001] of longint;

i,j:longint;

begin

for i:=1 to m+1 do d[i]:=100001;

for i:=-100 to 0 do d[i]:=0;

for i:=1 to m+1 do

if x[i]=0 then

for j:=i-r to i-1 do

if d[i] > d[j]+1 then d[i]:=d[j]+1;

f:=d[m+1];

end;

Sau khi giải quyết xong bài toán 1, ta dễ dàng tính thời gian cho tất cả các bạn bằng cách áp dụng n lần sử dụng hàm f

Trong trờng hợp này độ phức tạp của thuật toán sẽ là O(n.m.r) là quá lớn

Ta lại có thể cải tiến hàm f nh sau: Độ phức tạp là O(m)

function f(r:integer):longint;

var d:aray[-100 100001] of longint;

i,j,v0,v1:longint;

begin

for i:=1 to m+1 do d[i]:=100001;

for i:=-100 to 0 do d[i]:=0;

v0:=0;v1:=0;

for i:=1 to m+1 do

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 là vị trí xa nhất của bớc trớc đó V1 là vị trí gần i nhất đã đợc bớc tới

Để giải quyết bài toán 2 dễ dàng ta còn phải tính thời gian cho các nhóm, sắp xếp chúng theo thứ tự tăng dần: việc này có thể dễ dàng giải quyết với suy luận bạn

Ta có 3 mảng sau:

Trang 10

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 nhất với bớc nhảy là r

tg[1 10000] of longint tg[i] thời gian qua cầu của 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 do

begin

read(f,r);

sn[r]:=sn[r]+1;

end;

readln(f);

readln(f,x);

close(f);

end;

procedure tinhtg;

var ig,k:integer;

begin

for ig:=1 to 100 do if sn[ig]>0 then t[ig]:=f[ig];

k:=0;

for ig:=100 downto 1 do

for jg:=1 to sn[ig] do

begin

k:=k+1;

tg[k]:=t[ig];

end;

End;

Bài toán 2: Để qua cầu nhanh nhất xét theo quan điểm toán học ta có 2 sự u tien

sau:

trong các bạn đã qua cầu

hoặc đi với ngời nhanh nhất (để giảm thời gian về đón)

Ta có thể giải quyết riêng các 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 = 4

Ta ký hiệu (i,j) là bạn i và bạn j qua cầu (i) bạn i quay lại

Phơng án 1 theo u tiên trên (1,2) (1) (3,4)(2)(1,2)

Thời gian qua cầu của nhóm là T1 = tg[2]+tg[1]+tg[4]+tg[2]+tg[2];

(tg[3] đợc ẩn đi)

Phơng án 2 theo u tiên trên (1,2) (1) (1,3)(1)(1,4)

Thời gian qua cầu của nhóm là T2 = tg[2]+tg[1]+tg[3]+tg[1]+tg[4];

Xét T1-T2 = 2tg[2] – (tg[1] + tg[3])

Trang 11

Dễ thấy nếu 2tg[2] < tg[1] + tg[3] đi theo phơng án 1 lợi hơn, ngợc lại đi theo phơng án hai lợi hơn

Mở rộng cho n bạn (đã sắp xếp theo thời gian tăng dần)

Hàm tính kết quả nh sau:

function tinhkq:longint;

var k,i:integer;

begin

if n=1 then exit(tg[1]);

kq:=0;

k:=n;

while (k>3) and (2tg[2] < tg[1] + tg[k-1]) do

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 do kq:=kq+tg[i] ; {(1,i)}

kq:=kq+(k-2)*tg[1];

exit(kq);

end;

Đánh giá độ phức tạp: Nhập dữ liệu O(n+m)

Tính thời nhan theo các nhóm O(m.r)

Tính mảng tg O(n)

Tính kết quả O(n)

Do nmax khá nhỏ so với mmax :Đánh giá chung O(m.r)

Chơng trình chí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);

for i:=1 to m do

begin

read(f,r);

sn[r]:=sn[r]+1;

Trang 12

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 do d[i]:=100001;

for i:=-100 to 0 do d[i]:=0;

v0:=0;v1:=0;

for i:=1 to m+1 do

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 do if sn[ig]>0 then t[ig]:=f(ig); k:=0;

for ig:=100 downto 1 do

for jg:=1 to sn[ig] do

begin

k:=k+1;

tg[k]:=t[ig];

end;

end;

function tinhkq:longint;

var k,i:integer;

begin

if n=1 then exit(tg[1]);

kq:=0;

k:=n;

while (k>3) and (2tg[2] < tg[1] + tg[k-1]) do

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 do kq:=kq+tg[i] ; {(1,i)}

kq:=kq+(k-2)*tg[1];

exit(kq);

Trang 13

procedure inkq;

var g:text;

begin;

assign(g,fo);

rewrite(g);

writeln(g,tinhkq);

close(g);

end;

Begin

clrscr;

nhapdl;

tinhtg;

inkq;

end

Ngày đăng: 04/02/2018, 22:46

TỪ KHÓA LIÊN QUAN

w