pascal tuan anh

Màu nền
Font chữ
Font size
Chiều cao dòng

Đề số 1

Bài 1. Số nguyên tố

áp dụng thuật toán Sàng Eratosthene như sau: xây dựng một tập hợp các phần tử từ 2 đến n gọi là sàng. Ta sẽ lọc dần các số ra khỏi sàng theo cách sau đây: Số nhỏ nhất trong sàng (theo cách xây dựng của ta là số nguyên tố) được in ra. Sau đó ta lọc khỏi sàng tất cả các bội số của số nhỏ nhất này kể cả chính nó. Số nguyên tố tiếp theo chính là số nhỏ nhất trong phần còn lại của sàng. Ta tiếp tục xử lý phần còn lại này theo quy cách trên cho tới khi sàng không còn số nào. Như vậy không một số nguyên tố nào bị lọc khỏi sàng mà không được in ra.

PROGRAM Sang;

Uses crt;

Const max=60000;

out='snt.txt';

Var n:integer;

mark:array[1..max] of boolean;

i,j:integer;

f:text;

BEGIN

clrscr;

write('Cho n = ');

readln(n);

for i:=1 to n do mark[i]:=false;

assign(f,out);

rewrite(f);

for i:=2 to n do

if not mark[i] then

write(f,i,' ');

j:=2*i;

while j<n do

mark[j]:=true;

j:=j+i;

end;

end;

if i mod 1000=0 then writeln(f);

end;

close(f);

END.

Bài 2. Hệ đếm

Có thể có nhiều cách giải khác nhau nhưng tất cả đều cần phải giải quyết các vấn đề:

- Kiểm tra xem một số có là số nguyên tố hay không?

- Tìm dạng biểu diễn nhị phân của một số.

- Kiểm tra một số có là đối xứng không?

- Chọn các số đối xứng (trong hệ thập phân) thích hợp để kiểm tra.

Việc giải quyết rất đơn giản, xin dành lại cho bạn đọc.

PROGRAM Bienso;

Uses crt;

Var m,i,j,k,n,l:integer;

a,b:array[1..14] of integer;

Procedure chuyenma(i:integer);

Begin

l:=0;

while i<>0 do

l:=l+1;

a[l]:=i mod 2;

i:=i div 2;

end;

End;

Function ngto(i:integer):boolean;

var b:boolean;

j:integer;

Begin

b:=true;

j:=1;

while (j<trunc(sqrt(i))) and b do

j:=j+1;

if i mod j = 0 then b:=false;

end;

ngto:=b;

End;

Function doixung:boolean;

var b:boolean;

j:integer;

Begin

b:=true;

i:=1;

while (i<=l div 2) and b do

if a[i]<>a[l-i+1] then b:=false

else i:=i+1;

end;

doixung:=b;

End;

BEGIN

clrscr;

b[1]:=1; b[2]:=3;

b[3]:=7; b[4]:=9;

for m:=1 to 4 do

for k:=0 to 9 do

n:=101*b[m] + 10*k;

if ngto(n) then

chuyenma(n);

if doixung then

write('Bien so can tim: ',n:5,' Ma nhi phan la ');

for j:=1 to l do

write(a[j]:2);

writeln;

end

else

writeln('So ngto doi xung nhung ma nhi phan khong doi xung ',n:5);

end;

end;

END.

Đề số 2

Bài 1. Tính giá trị biểu thức

Đây chỉ là một bài toán tính toán giá trị biểu thức thông thường, tuy nhiên ta cần lưu ý hai vấn đề sau:

- Có một số biểu thức con xuất hiện ở một số nơi trong biểu thức. Nếu ta trình bày lại biểu thức như đầu bài thì có nghĩa là đ• tính "lặp" các biểu thức con đó. Việc tính lặp đó, một mặt sẽ gây rối rắm khi viết chương trình, mặt khác làm chương trình thực hiện lâu hơn. Bởi vậy việc "làm tốt hơn" chương trình cả về trình bày lẫn thực hiện luôn luôn được đặt ra (Với các bài toán lớn thì ý nghĩa của công việc đó càng cao). Người ta gọi việc làm đó là tối ưu chương trình". Khi thể hiện cách thức đó thường chúng ta cần thêm biến phụ để lưu trữ các giá trị trung gian đó.

- Việc tổ chức dữ liệu vào đúng đắn cũng được thể hiện thông qua toán tử REPEAT - UNTIL ở đây sử dụng các siêu lệnh dịch ({$I+} và {$I-}) để làm điều đó.

PROGRAM Bieuthuc;

Uses crt;

Var c,d:integer;

i:byte;

gt,x1,x2,phu,phu2:real;

BEGIN

clrscr;

write('Cho hai so c va d: ');

repeat

gotoxy(22,1);

clreol;

{$I-}

readln(c,d);

i:=ioresult;

{$I+}

if i<>0 then writeln(#7);

until i=0;

phu:=sqrt(9+4*abs(c*d));

x1:=(3+phu)/2;

x2:=(3-phu)/2;

phu2:=c*x1*x1*x1+d*x2*x2;

phu:=sin(abs(phu2-c*d));

gt:=abs(phu)*phu*phu;

phu:=(phu2-x1);

gt:=abs(gt/(sqrt(phu*phu+3.14)));

gt:=gt+(sin(phu)/cos(phu));

write('Gia tri cua bieu thuc la: ',gt);

readln;

END.

Bài 2. Quan hệ

Lập mảng XEP[1..N] khởi tạo mọi giá trị bằng 0. Bắt đầu chia nhóm từ người thứ nhất cho tới người thứ N. Khi xét người thứ i, những khả năng sau có thể xảy ra:

- Nếu XEP[i]=0 (chưa được xếp nhóm) thì xếp vào nhóm 1 (XEP[i]=1) và xếp những người j quen i vào nhóm 2 (cho XEP[j]=2).

- Nếu XEP[i]=1 và trong số những người quen i có một người j mà XEP[j] cũng bằng 1 thì kết luận không xếp được.

- Nếu XEP[i]=2 và trong số những người quen i có một người j mà XEP[j] cũng bằng 2 thì kết luận không xếp được.

PROGRAM QuanHe;

Uses crt;

Const inp='quanhe.inp';

out='quanhe.out';

Var n:integer;

f:text;

a:array[1..100,1..100] of integer;

xep:array[1..100] of integer;

Procedure readinp;

var i,j:integer;

Begin

assign(f,inp);

reset(f);

readln(f,n);

for i:=1 to n do

for j:=1 to n do

read(f,a[i,j]);

readln(f);

end;

close(f);

End;

procedure continue(i,k:integer);

var j:integer;

for j:=1 to n do

if a[i,j]<>0 then

if xep[j]=0 then

xep[j]:=k;

continue(j,3-k);

end

else

if xep[j]=3-k then

write(f,'KHONG XEP DUOC');

close(f);

halt;

end;

end;

Procedure select;

var i,j:integer;

Begin

for i:=1 to n do

xep[i]:=0;

for i:=1 to n do

if xep[i]=0 then

xep[i]:=1;

continue(i,2);

end;

End;

var i:integer;

BEGIN

readinp;

assign(f,out);

rewrite(f);

select;

for i:=1 to n do

if xep[i]=1 then write(f,i,' ');

writeln(f);

for i:=1 to n do

if xep[i]=2 then write(f,i,' ');

close(f);

END.

4

0 1 0 1

1 0 1 0

0 1 0 0

1 0 0 0

Đề số 3

Bài 1. Phân số

Khởi tạo phân số có dạng 1/1 (P=1, Q=1). Chừng nào Q<max, nếu P/Q<R thì tăng P một đơn vị, nếu P/Q>R thì tăng Q lên 1.

PROGRAM Phantich;

Uses crt;

Const out='kq.txt';

Var socach, q, r:integer;

a:array[0..50] of integer;

f:text;

Procedure tach(n,k:integer); {tach n so con lai, truoc do da tach duoc k so}

var j,l:integer;

Begin

if (n>0) then

if (k=0) then l:=1

else l:=a[k];

for j:=l to n do

k:=k+1;

a[k]:=j;

tach(n-j,k);

k:=k-1;

end;

end

else

if k>1 then

inc(socach);

write(f,a[1]);

for j:=2 to k do

write(f,'+',a[j]:2);

writeln(f);

end;

End;

BEGIN

clrscr;

repeat

write('Cho mot so nam giua 2 va 50: ');

readln(q);

until ((q>1) and (q<51));

writeln('Cac cach phan tich ',q,' thanh tong cac so nho hon');

writeln;

socach:=0;

r:=0;

assign(f,out);

rewrite(f);

tach(q,r);

close(f);

END.

Bài 2. Kiến thiết xâu văn bản

Ta gọi mọi d•y thoả m•n điều kiện đề bài là d•y hợp lệ. Dễ dàng nhận xét được rằng không thể xây dựng d•y hợp lệ bằng cách mở rộng thêm một phần tử vào phần đuôi của một d•y không hợp lệ. Nói một cách khác, một d•y hợp lệ B hoặc là d•y gồm một phần tử hoặc chỉ được xây dựng bằng cách khai triển d•y hợp lệ A (A<B). Do vậy ta tìm và đưa ra các d•y hợp lệ bằng cách kiến thiết lần lượt, vừa mở rộng vừa kiểm tra tính hợp lệ.

Ta có thể áp dụng phương pháp quay lui sau: Nếu giá trị phần tử cuối của d•y hợp lệ nhỏ hơn 3 thì tăng lên một đơn vị và kiểm tra tính hợp lệ, ngược lại giảm chiều dài của d•y đi một đơn vị.

PROGRAM XauVanBan;

Uses crt;

Const n=4;

out='xvb.txt';

Var d:array[0..n] of integer;

good:boolean; {kiem tra day co hop le hay khong}

length,s,i,k,m,mlimit:integer;

f:text;

BEGIN

clrscr;

length:=0;

s:=0;

d[0]:=0;

assign(f,out);

rewrite(f);

Repeat

if length<n then

length:=length+1;

d[length]:=0;

end;

Repeat

while d[length]=3 do

length:=length-1;

if length=0 then break;

d[length]:=d[length]+1;

good:=true;

m:=1;

mlimit:=length div 2;

while ((m<=mlimit) and good) do

k:=0; {kiem tra cac xau con lien ke}

repeat

good:=d[length-k]<>d[length-m-k];

k:=k+1;

until ((k=m) or good);

m:=m+1;

end;

Until good;

if length=0 then break;

i:=0;

s:=s+1;

Repeat

i:=i+1;

write(f,d[i]);

Until i=length;

writeln(f);

Until length=0;

writeln(f);

writeln(f,'Tat ca co ',s,' day hop le');

close(f);

END.

Đề số 4

Bài 1. Điểm trên mặt phẳng

Trong bài này ta sử dụng một kiến thức về hình học: Điểm (x,y) muốn thuộc đường thẳng đi qua hai điểm (x1,y1) và (x2,y2) khi và chỉ khi nó thoả m•n:

(x-x2)(y1-y2)=(y-y2)(x1-x2) hay

(x-x2))y1-y2)-(y-y2)(x1-x2)=0 (*)

Đường thẳng l sẽ chia các điểm không thuộc nó thành 2 loại (tương ứng với hai nửa mặt phẳng): một loại làm cho vế trái của (*) dương và loại còn lại làm cho nó âm. Vì lẽ đó nếu 2 điểm cùng phía khi và chỉ khi tích hai vế dương.

PROGRAM MatPhang;

Uses crt;

Var a,b,c,d,e,f,g,h:real;

BEGIN

clrscr;

write('Cho toa do e,f: ');

readln(e,f);

write('Cho toa do g,h: ');

repeat

readln(g,h);

until (not ((g=e) and (f=h))) and (not ((g=f) and (h=e)));

write('Cho toa do a,b: ');

repeat

readln(a,b);

until (g-e)*(b-f)<>(h-f)*(a-e); {khong thuoc l}

write('Cho toa do c,d: ');

repeat

readln(c,d);

until (g-e)*(d-f)<>(h-f)*(c-e); {khong thuoc l}

if ((g-e)*(d-f)-(h-f)*(c-e))*((g-e)*(b-f)-(h-f)*(a-e))>0 then

writeln('hai diem nam cung phia so voi l')

else

writeln('hai diem nam khac phia so voi l');

readln;

END.

Bài 2. Chia vật

Trong bài toán này có rất ít mối liên hệ để có thể tìm ra được một công thức trực tiếp tính toán số cách chia. Vì vậy ta sẽ phải dùng giải pháp đệ quy.

PROGRAM Chiaphan;

uses crt;

var sovat,songuoi:integer;

Function chia(m,n:integer):integer;

if m=0 then chia:=1

else

if n=0 then chia:=0

else

if m<n then chia:=chia(m,m)

else chia:=chia(m,n-1) + chia(m-n,n);

end;

BEGIN

clrscr;

write('Cho so vat va so nguoi: ');

readln(sovat,songuoi);

writeln('So cach chia la: ', chia(sovat,songuoi));

readln;

END.

Đề Số 5

Bài 1. Tìm nghiệm phương trình siêu việt

Ta áp dụng phương pháp chia đôi như sau: giả sử (a,b) là một khoảng nào đó sao cho f(a)<0, f(b)>0. Gọi c là trung điểm của (a,b). Nếu f(c)=0 thì c chính là nghiệm. Ngược lại nếu f(c)>0 thì ta thay b bằng c, nếu f(c)<0 thì ta thay a bằng c. Quá trình này cứ tiếp diễn và khoảng (a,b) luôn luôn được điều chỉnh với mục đích:

- Đảm bảo giá trị của hàm f tại hai mút luôn trái dấu. Vì f là một hàm liên tục nên trong khoảng (a,b) luôn luôn có nghiệm.

- Mỗi lần điều chỉnh, độ dài của khoảng giảm hai lần. Gọi nghiệm đúng là x, với bất cứ giá trị c nào nằm trong đoạn [a,b] ta luôn có đánh giá: |x-c|<|b-a|. Vì vậy nếu ở một bước nào đó ta chọn a làm nghiệm xấp xỉ thì sai số cũng không vượt quá b-a.

PROGRAM chiadoi;

uses crt;

const saiso=0.000001;

var a,b,c,f:real;

nghiemdung:boolean;

i:integer;

BEGIN

nghiemdung:=false;

a:=-1; b:=0;

while (b-a>saiso) and (not nghiemdung) do

c:=(a+b)/2;

f:=c*c*c+exp(c);

if f>0 then b:=c

else

if f<0 then a:=c

else nghiemdung:=true;

end;

if nghiemdung then

write('Nghiem dung = ',c:9:6)

else

write('Nghiem gan dung = ',c:9:6);

END.

Bài 2. Đặt phép tính

Ta tiến hành duyệt các khả năng đặt dấu '+' và '-' giữa các số để tìm biểu thức có giá trị đ• cho. Mỗi vị trí có ba phương án là đặt dấu '+', dấu '-' hoặc không đặt dấu gì cả.

PROGRAM Datdau;

uses crt;

type dau=(cong,tru,khong);

var i,j:byte;

vitri:array[1..9] of dau;

n:integer;

Procedure inketqua;

var i:byte;

Begin

writeln;

write('1');

for i:=1 to 8 do

case vitri[i] of

cong: write('+');

tru: write('-')

end;

write(i+1);

end;

writeln;

halt;

End;

Procedure tinhgiatri;

var j:byte;

kq,phu:longint;

dautien:dau;

b:boolean;

Begin

kq:=0;

dautien:=cong;

phu:=1;

j:=1;

repeat

while (vitri[j]=khong) and (j<9) do

j:=j+1;

phu:=phu*10+j;

end;

case dautien of

cong: kq:=kq+phu;

tru: kq:=kq-phu;

end;

b:=j<9;

if b then

dautien:=vitri[j];

inc(j);

phu:=j;

end;

until not b;

if kq=n then inketqua;

End;

Procedure thuchien(j:byte);

var dau0:dau;

Begin

for dau0:=cong to khong do

vitri[j]:=dau0;

if j=8 then tinhgiatri

else thuchien(j+1);

end;

End;

BEGIN

clrscr;

write('Vao so <32767: ');

readln(n);

vitri[9]:=cong;

thuchien(1);

writeln('Khong co bieu thuc nao thoa man');

END.

Đề số 6

Bài 1. Trò chơi bốc sỏi

Gọi số lượng bốc tối đa mỗi lần là k. Chiến thuật thắng cho máy là cố gắng bốc số sỏi sao cho số lượng còn lại chia hết cho k+1 (mod (k+1) =0). Còn nếu số sỏi trước khi bốc đang chia hết cho k+1 thì chỉ nên cho máy bốc một viên để hạn chế khả năng thắng của đối thủ.

PROGRAM Bocsoi;

uses crt;

var sosoi,soboctoida,soluongboc:integer;

maytinhboc:boolean;

BEGIN

clrscr;

repeat

write('Cho so vien soi:');

readln(sosoi);

write('Cho so vien duoc boc toi da: ');

readln(soboctoida);

until (sosoi>0) and (soboctoida>0);

maytinhboc:=true;

while sosoi>0 do

if maytinhboc then

if sosoi mod (soboctoida+1)=0 then

soluongboc:=1

else

soluongboc:=sosoi mod (soboctoida+1);

writeln('May tinh boc ',soluongboc,' vien');

maytinhboc:=false;

sosoi:=sosoi-soluongboc;

end

else

repeat

write('Ban boc bao nhieu vien ');

readln(soluongboc);

until (soluongboc>0) and (soluongboc<=soboctoida);

maytinhboc:=true;

sosoi:=sosoi-soluongboc;

end;

if maytinhboc then

writeln('May thua - Nguoi thang')

else writeln('Nguoi thua - May thang');

END.

Bài 2. Chu trình đơn hoạch

Đây chính là bài toán tìm chu trình Euler trên đồ thị vô hướng. Điều đó có nghĩa là có chu trình đơn hoạch khi và chỉ khi mọi đỉnh trong đồ thị đều là đỉnh bậc chẵn.

Thuật giải có thể được tiến hành như sau:

- Đầu tiên tìm một chu trình C bất kỳ trong đồ thị. Xoá các cạnh thuộc C đi ta được đồ thị mới H.

- Bắt đầu từ một đỉnh nào đó của chu trình C, đi theo các cạnh của chu trình C chừng nào chưa gặp phải đỉnh không cô lập của H. Nếu gặp phải đỉnh như vậy thì ta đi theo chu trình Euler của thành phần liên thông của H chứa đỉnh đó. Sau đó lại tiếp tục đi theo cạnh của C cho đến khi gặp phải đỉnh không cô lập của H thì lại theo chu trình Euler của thành phần liên thông tương ứng trong H ... Quá trình sẽ kết thúc khi ta trở về đỉnh xuất phát, tức là thu được chu trình đi qua mỗi cạnh của đồ thị đúng một lần.

PROGRAM ChuTrinhEuler;

Uses crt;

Var ke:array[1..1000] of shortint;

Tro,STACK,chuaxet,pre,bac,CE:array[1..100] of byte;

dd:array[1..100] of boolean;

f:text;

n,m,goc,giu,j:integer;

{-------------------------------------------------------}

Procedure Doc; {Nhap du lieu tu tep}

Var i:integer;

Begin

Assign(f,'dothi.txt');

Reset(f);

Readln(f,n); m:=0;

For i:=1 to n do

tro[i]:=m+1; bac[i]:=0;

while not eoln(f) do

inc(m); inc(bac[i]);

read(f,ke[m]);

end;

readln(f);

end;

tro[n+1]:=m+1;

For i:=1 to n do if bac[i] mod 2 <>0 then

write('Do thi khong phai la do thi EULER. ');

readln; halt;

end;

Close(f);

End;

{-------------------------------------------------------}

Function cycle(u:byte):boolean; {kiem tra ket thuc chu trinh}

Var truoc:byte;

Begin

truoc:=pre[u]; cycle:=true;

While truoc<>goc do

Begin

if truoc=u then exit;

truoc:=pre[truoc];

End;

if truoc=u then exit;

cycle:=false;

End;

{-----------------------------------------------------}

Procedure DFS(v:byte);

Var u,i,j:byte;

Begin

chuaxet[v]:=1;

For u:=tro[v] to tro[v+1]-1 do

if ke[u]>0 then

if chuaxet[ke[u]]=0 then

pre[ke[u]]:=v;

if ke[u+1]<0 then j:=tro[-ke[u+1]]-1

else j:=tro[ke[u+1]]-1;

for i:=tro[ke[u]] to j do

if ke[i]=v then

begin ke[i]:=-ke[i]; dd[i]:=true;i:=j; end;

ke[u]:=-ke[u]; dd[u]:=true;

DFS(-ke[u]);

end

else

if cycle(ke[u]) then begin giu:=v;exit; end;

End;

{-----------------------------------------------------}

Procedure ChuTrinh(i:byte); {tim 1 chu trinh bat dau tu 1 dinh}

Var j:integer;

Begin

Fillchar(chuaxet,sizeof(chuaxet),0);

Fillchar(dd,sizeof(dd),false);

goc:=i; pre[i]:=i;

DFS(i);

For j:=1 to m do if dd[j] then ke[j]:=-ke[j];

End;

{-------------------------------------------------------}

Procedure Inketqua;

Var i:integer;

Begin

Writeln(' Chu trinh EULER trong do thi la :');

For i:=1 to j-1 do write(CE[i],'==>'); write(CE[j]);

End;

{-------------------------------------------------------}

Procedure loaicanh(x,y:integer);

Var i,d,c:integer;

Begin

for i:=tro[x] to tro[x+1]-1 do

if ke[i]=y then begin ke[i]:=-ke[i]; i:=tro[x+1]-1; end;

for i:=tro[y] to tro[y+1]-1 do

if ke[i]=x then begin ke[i]:=-ke[i]; i:=tro[y+1]-1; end;

End;

{-------------------------------------------------------}

Procedure ChutrinhEULER;

Var u,v,i,k:integer;

Begin

u:=1; Chutrinh(u);

v:=1; j:=1; CE[j]:=1;

Repeat

if bac[v]<=2 then

for i:=tro[v] to tro[v+1]-1 do

if ke[i]>0 then

dec(bac[v]);

inc(j); CE[j]:=ke[i];

dec(bac[ke[i]]);

loaicanh(v,ke[i]);k:=tro[v+1]-1;

if ke[i]<0 then v:=-ke[i]

else v:=ke[i];

i:=k;

end;

end

else

chutrinh(v);

inc(j); CE[j]:=giu;

dec(bac[giu]); dec(bac[v]);

loaicanh(v,giu);

v:=giu;

end;

Until v=u;

Inketqua;

End;

{-------------------------------------------------------}

BEGIN

ClrScr;

Doc;

ChuTrinhEULER;

END.

Đề số 7

Bài 1. Phân tích số

Giả sử a1+...+an=n là một phân tích của n. Ta thấy mọi phân tích của n đều có thể nhận được từ việc tách khỏi n một số a1 và phân tích phần (n-a1) còn lại. a1 có thể nhận mọi giá trị từ 1 đến n. Do vậy ta sẽ dùng một thủ tục đệ quy để tách một số tự nhiên thành tổng các số tự nhiên khác. Do thứ tự bên trong tổng (a1+...+ak) là không quan trọng nên để tối ưu số bước tách và để tránh trùng lặp nhiều lần một phân tích ta giả thiết: a1<=a2<=...<=an. Sự phân tích sẽ hoàn tất nếu phần còn lại khi tách là bằng 0.

PROGRAM ChiaKeo;

Uses crt;

Const inp='keo.inp';

out='keo.out';

Var i,j,n,max,j1,j2,chenh:integer;

c:array[1..100] of integer;

v:array[1..2,0..20000] of byte;

f:text;

Procedure doc;

Begin

assign(f,inp);

reset(f);

readln(f,n);

for i:=1 to n do

read(f,c[i]);

close(f);

End;

Procedure chia;

Begin

fillchar(v,sizeof(v),0);

v[1,0]:=1; max:=0;

for i:=1 to N do

for j:=max downto 0 do

if v[1,j]=1 then

if v[1,j+c[i]]=0 then

v[1,j+c[i]]:=1;

v[2,j+c[i]]:=i;

end;

max:=max+c[i];

end;

j1:=max div 2;

while (v[1,j1]=0) do dec(j1);

j2:=max-j1;

chenh:=j2-j1;

End;

Procedure viet;

Begin

assign(f,out);

rewrite(f);

writeln(f,chenh);

i:=j1; j:=0;

while i>=1 do

inc(j);

write(f,v[2,i]:4);

i:=i-c[v[2,i]];

if (j mod 20 = 0) then writeln(f);

end;

i:=j2; j:=0;

writeln(f);

while i>=1 do

inc(j);

write(f,v[2,i]:4);

i:=i-c[v[2,i]];

if (j mod 20=0) then writeln(f);

end;

close(f);

End;

BEGIN

doc;

chia;

viet;

END.

3

6 3 2

Bài 2. Chia kẹo

Sử dụng phương pháp qui hoạch động. Lấy một mảng có độ dài bằng tổng số kẹo có nhiệm vụ đánh dấu số kẹo có thể được chia cho từng người. Nếu vị trí càng gần tổng số kẹo chia đôi được đánh dấu thì độ chênh lệch giữa hai nhóm càng ít.

PROGRAM Phanso;

Uses crt;

Var p,q,max:integer;

r,p0,q0:real;

BEGIN

clrscr;

write('Nhap so nguyen duong MAX: ');

readln(max);

write('Nhap so thuc R: ');

readln(r);

p:=1; q:=1;

while q<=max do

q0:=q; p0:=p;

if p0/q0<r then inc(p)

else inc(q);

end;

if q>max then dec(q);

write('Phan so tim duoc: ',p,'/',q);

readln;

END.

Đề số 8

Bài 1. Cân một vật

Bài này ta sử dụng phương pháp duyệt các khả năng đặt quả cân từng bên đĩa cho đến khi tìm được một phương án cân hoặc duyệt hết mà không tìm được phương án nào. Mỗi quả cân sẽ được nhận một trong 3 giá trị:

-1: đặt quả cân bên trái.

0: không sử dụng quả cân này.

1: đặt quả cân bên phải.

PROGRAM Can;

Uses crt;

Var n,i,y,vc:integer;

x,d:array[1..100] of integer;

Procedure Print;

Begin

writeln('Dat cac qua can nhu sau ');

writeln('Trai':24,'Phai':24);

for i:=1 to n do

if x[i]=1 then writeln('':20,d[i]);

if x[i]=-1 then writeln('':45,d[i]);

end;

halt;

End;

Procedure chon(i:integer);

var k:integer;

Begin

for k:=-1 to 1 do

y:=y+k*d[i];

x[i]:=k;

if y=vc then print

else

if i<n then chon(i+1);

x[i]:=0;

y:=y-k*d[i]

end;

End;

BEGIN

clrscr;

writeln('Vao trong luong can can');

readln(vc);

write('So luong qua can n = ');

readln(n);

writeln('Nhap trong luong cac qua can');

for i:=1 to n do readln(d[i]);

y:=0;

for i:=1 to n do x[i]:=0;

chon(1);

write('Khong can duoc');

END.

Bài 2. Ghép xâu

Ta dùng kỹ thuật quay lui để duyệt mọi cách biểu diễn S dưới dạng ghép của các xâu Ai.

PROGRAM GhepXau;

Uses crt;

Const inp='xau.inp';

out='xau.out';

Var a:array[1..100] of string[40];

kq:array[1..100] of string[10];

s:string;

n,i,j,k,u,sbd:byte;

f:text;

Procedure xep(var s:string);

var s2:string;

i:integer;

Begin

if s='' then

sbd:=sbd+1;

for i:=1 to k do write(f,kq[i]);

writeln(f);

end

else

for i:=1 to n do

u:=length(a[i]);

if a[i]=copy(s,1,u) then

k:=k+1;

{tam[k]:=i;}

str(i,s2);

kq[k]:='A['+s2+']';

delete(s,1,u);

xep(s);

k:=k-1;

s:=a[i]+s;

end;

end;

End;

BEGIN

assign(f,inp);

reset(f);

readln(f,s);

readln(f,n);

for i:=1 to n do readln(f,a[i]);

close(f);

assign(f,out);

rewrite(f);

sbd:=0;

k:=0;

xep(s);

if sbd=0 then writeln(f,'KHONG CO');

close(f);

END.

abcdef

11

ab

cd

ef

abc

def

a

c

d

f

Đề số 9

Bài 1. Đường đi ngắn nhất

Đây là một ví dụ điển hình của thuật toán Dijkstra dùng để tìm đường đi ngắn nhất giữa hai đỉnh của một đồ thị có trọng số không âm.

PROGRAM TT_Dijkstra;

Uses crt;

Const marr=101;

max=-1;

inp='input.txt';

out='output.txt';

Type arr1=array[0..marr,0..marr] of integer;

arr2=array[0..marr] of integer;

arr3=array[0..marr] of longint;

arr4=array[0..marr] of boolean;

Var a:arr1;

pre:arr2;

mark:arr4;

d:arr3;

n,u,v:integer;

m:longint;

f:text;

{----------------------------------------------------}

Procedure readinp;

var i,j:integer;

Begin

assign(f,inp);

reset(f);

readln(f,n,u,v);

for i:=1 to n do

for j:=1 to n do

read(f,a[i,j]);

readln(f);

end;

close(f);

End;

{----------------------------------------------------}

Procedure init;

var i:integer;

Begin

fillchar(mark,sizeof(mark),false);

fillchar(pre,sizeof(pre),0);

for i:=1 to n do d[i]:=max;

d[u]:=0;

End;

{----------------------------------------------------}

Procedure timmin(var j:integer);

var i:integer;

Begin

j:=1;

while mark[j] do inc(j);

for i:=j+1 to n do

if not mark[i] then

if d[i]<>max then

if (d[j]=max) or (d[i]<d[j]) then j:=i;

End;

{----------------------------------------------------}

Procedure dijkstra;

var i,j:integer;

Begin

repeat

timmin(j);

if (j=n+1) or (j=v) then exit;

mark[j]:=true;

for i:=1 to n do

if not mark[i] and (a[j,i]<>0) then

if (d[i]=max) or ((d[i]<>max) and (d[i]>d[j]+a[j,i])) then

d[i]:=d[j]+a[j,i];

pre[i]:=j;

end;

until j=n+1;

End;

{----------------------------------------------------}

Procedure find(i:integer);

Begin

if i=u then write(f,m,#10,#13,u,' ')

else

inc(m,a[pre[i],i]);

find(pre[i]);

write(f,i,' ');

end;

End;

{----------------------------------------------------}

Procedure writeout;

var i:integer;

Begin

assign(f,out);

rewrite(f);

m:=0;

find(v);

close(f);

End;

{----------------------------------------------------}

BEGIN

clrscr;

readinp;

dijkstra;

writeout;

END.

3 1 3

0 2 4

0 0 1

0 0 0

Bài 2. D•y số

Ta giải bài toán này bằng phương pháp quy hoạch động. Sử dụng hai mảng, tại vị trí thứ i, một mảng lưu số lượng d•y tăng dài nhất tính đến vị trí thứ i, còn một mảng lưu vị trí số liền kề với nó trong d•y trên.

PROGRAM Congty;

Uses crt;

Var a,tt,sl:array[1..1000] of integer;

f,f1:text;

n,max:integer;

Procedure Doc;

Var i:integer;

Begin

Assign(f,'ct.inp');

Reset(f);

Read(f,n);

For i:=1 to n do

read(f,a[i]);

Close(f);

End;

Procedure Chuan_bi;

Var i:integer;

Begin

For i:=1 to n do

sl[i]:=0;

tt[i]:=0;

end;

sl[1]:=1;

End;

Procedure Day_so;

Var i:integer;

Procedure xac_dinh(i:integer);

Var j,max,k:integer;

Begin

max:=0; k:=0;

For j:=1 to i-1 do

if (a[j]<=a[i]) and (sl[j]>max) then

max:=sl[j];

k:=j;

end;

sl[i]:=max+1;

tt[i]:=k;

End;

Begin

For i:=2 to n do

Xac_dinh(i);

End;

Procedure danh_dau;

Var i,jm,j:integer;

Begin

max:=0;

For i:=1 to n do

if sl[i]>max then

max:=sl[i];

j:=i;

end;

jm:=tt[j];

sl[j]:=-sl[j];

Repeat

sl[jm]:=-sl[jm];

jm:=tt[jm];

Until jm=0;

End;

Procedure Dua_ra;

Var i:integer;

Begin

Assign(f1,'ct.out');

Rewrite(f1);

Writeln(f1,max);

For i:=1 to n do

if sl[i]<0 then writeln(f1,i,' ',a[i]);

Write(' OK ');

Close(f1);

End;

Procedure test;

Begin

ClrScr;

Doc;

Chuan_bi;

Day_so;

Danh_dau;

Dua_ra;

Readln;

End;

BEGIN

END.

Đề số 10

Bài 1. Giai thừa

Do N lớn cho nên ta sẽ phải nhân các số rất lớn, vượt quá khả năng lưu trữ của biến đơn. Ta sẽ giải quyết bằng cách lưu kết quả vào một mảng các số nguyên, có nghĩa là ghép kết quả bằng nhiều biến nguyên. Và đương nhiên ta sẽ phải viết lại thủ tục nhân cho số được lưu bởi mảng đó.

Program giaithua;

uses crt;

Var

Result: array[1..32200] of Word;

i,n,leng: Word;

Count: LongInt;

timeStart,timeEnd,time: LongInt;

CurrentTime: LongInt absolute $0000:$046C;

{-------------------------------------------------}

procedure Multiply(count:Word);

var

carry,i: Word; {thu tuc nhan bien Result voi count}

mul: LongInt;

carry:=0; { carry : so nho }

for i:=1 to leng do { xet tung phan tu cua Result }

mul:=LongInt(Result[i])*count+carry;

Result[i]:=mul mod 10000; { Ket qua moi }

carry:=mul div 10000; { so nho moi }

end;

while carry<>0 do

Inc(leng);

Result[leng]:=carry mod 10000;

carry:=carry div 10000;

end;

end;

{-------------------------------------------------}

function Format(Number:Word; Count:Byte):string;

var

s:string;

Str(Number,s); { Chuyen so thanh chuoi }

while Length(s)<Count do s:='0'+s; { Them 0 vao dau chuoi so }

Format:=s;

end;

{-------------------------------------------------}

procedure WriteResult; { Thu tuc viet ket qua }

Writeln;

Write(n,'! = ',Result[leng]);

for i:=leng-1 downto 1 do Write(Format(Result[i],4));

Writeln;

end;

{-------------------------------------------------}

clrscr;

Writeln('Chuong trinh tinh giai thua (n! = 1.2.3...n)');

Write('Cho so n (n <= 31500) : ');

Readln(n);

timeStart:=CurrentTime; { Danh dau thoi diem bat dau }

leng:=1;

Result[1]:=1; { Gan gia tri ban dau la 1 }

for i:=1 to n do Multiply(i); { Tinh giai thua }

timeEnd:=CurrentTime; { Xac dinh thoi diem ket thuc }

WriteResult;

Count:=Length(Format(Result[leng],0))+LongInt(leng-1)*4;

Writeln('So chu so : ',Count);

time:=timeEnd-timeStart; { So nhip dem thoi gian }

Writeln('Thoi gian tinh la : ',time/18.2:0:1,' giay');

readln;

end. {1000! 0,1s 0,2}

{ 5000! 4,2s 8,1

{10000! 18,9s {35,4

30000!201,9s}

Bài 2. Biến đổi xâu

Sử dụng phương pháp qui hoạch động: giả sử độ dài của S1/S2 tương ứng bằng M/N, ta xây dựng mảng A[0..M,0..N] mà A[i,j] bằng số phép biến đổi ít nhất cần dùng để biến đổi đoạn độ dài i của S1 thành đoạn độ dài j của S2. Ta có A[0,j]=j và A[i,0]=i với 0<=i<=M và 0<=j<=N. Việc tính A[i,j] dựa vào công thức đệ quy:

A[i,j]=min(A[i,j-1]+1, A[i-1,j]+1, A[i-1,j-1]+T[i,j])

Với T[i,j]=0/1 tuỳ theo S1[i] bằng hay khác S2[j].

PROGRAM BienDoiXau;

Uses crt;

Const th:set of char=['A'..'Z','a'..'z','0'..'9'];

Type st100=string[100];

Var s1,s2:st100;

n,m:integer;

a:array[0..100,0..100] of integer;

b:boolean;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++}

Procedure Nhap(var s:st100);

Var c:char;

i,u,v,u1,v1:integer;

s:=''; u:=wherex;v:=wherey;

Repeat

c:=readkey;

if (c<>#8) and (c in th) then

s:=s+c;

write(c);

end

else

if (c=#8) and (s<>'') then

u1:=wherex;v1:=wherey;

if (v1>v) and (u1=1) then

gotoxy(80,wherey-1);

write(' '); gotoxy(80,wherey-1);

end

else

gotoxy(wherex-1,wherey);

write(' '); gotoxy(wherex-1,wherey);

end;

delete(s,length(s),1);

end;

Until c=#13;

writeln;

writeln(s);

End;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++}

Procedure thay(k:char;i:integer;var s:st100);

Begin

if s[i]<>k then

s[i]:=k;

writeln('Thay ',i,' ',k);

Writeln(s1);

Write(s2);readln;

end

else b:=true;

End;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++}

Procedure them(k:char;i:integer;var s:st100);

Var j:integer;

st:string;

Begin

st:=k;

Writeln('Them ',i,' ',k);

if i=1 then insert(st,s,i)

else

if i+1<=length(s) then insert(st,s,i+1)

else s:=s+st;

Writeln(s1);

Write(s2);readln;

End;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++}

procedure xoa(i:integer;var s:st100);

Writeln('Xoa ',i);

delete(s,i,1);

Writeln(s1);

Write(s2);readln;

end;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++}

Function min(a,b,c:integer):integer;

Begin

If a>b then

if b>c then min:=c

else min:=b

else

if a<c then min:=a

else min:=c;

End;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++}

Procedure xuly;

Var i,j:integer;

n:=length(s1); m:=length(s2);

For i:=1 to m do a[0,i]:=i;

For i:=1 to n do a[i,0]:=i;

For i:=1 to n do

for j:=1 to m do

if s1[i]=s2[j] then

a[i,j]:=min(a[i-1,j]+1,a[i,j-1]+1,a[i-1,j-1])

else a[i,j]:=min(a[i-1,j]+1,a[i,j-1]+1,a[i-1,j-1]+1);

End;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++}

Function tim(i,j:integer):byte;

Var t:integer;

Begin

t:=a[i,j];

if t = a[i-1,j]+1 then tim:=1

else

if t=a[i,j-1]+1 then tim:=3

else

if t=a[i-1,j-1]+1 then tim:=2

else

if t=a[i-1,j-1] then tim:=2;

End;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++}

Procedure inkq;

Var i,j,k:integer;

Begin

i:=n; j:=m;

b:=false;

Repeat

case tim(i,j) of

1 : begin xoa(i,s1); dec(i); end;

2 : begin thay(s2[j],i,s1);dec(i); dec(j); end;

3 : begin them(s2[j],i,s1); dec(j); end;

end;

Until (i=0) or (j=0) {or b};

if (i=0) and (j<>0) then

for k:=1 to j do them(s2[k],k,s1);

if (i<>0) and (j=0) then

for k:=i downto 1 do xoa(k,s1);

End;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++}

Procedure test;

Var ch:char;

Begin

ClrScr;

Writeln('Nhap xau 1 : ');

Nhap(s1);

Writeln('Nhap xau 2 : ');

Nhap(s2);

Xuly;

Inkq;

Writeln('Ket qua : ',#7);

Writeln(s1);

Writeln(s2);

{Write(a[n,m]);}

Readln;

End;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++}

BEGIN

END.

Đề số 11

Bài 1. M• đi tuần

Do chỉ phải đưa ra một cách đi cho nên ta sẽ áp dụng thuật toán kinh tế sau: Xuất phát từ một ô, con m• sẽ di chuyển đến ô chưa đến nào mà từ đó có ít khả năng lựa chọn để đi tiếp nhất. Bằng cách đi này con m• sẽ đi được qua tất cả 64 ô bàn cờ 8x8, mỗi ô đúng một lần.

Trong phần chương trình có sử dụng kỹ thuật đặt lính canh để kiểm soát các ô ngoài bàn cờ và kỹ thuật đặt hằng biểu diễn các ô con m• có thể nhảy đến.

PROGRAM Madituan;

Uses crt;

Const n=8;

gx: array[1..8] of integer = (-2,-1, 1, 2, 2, 1,-1,-2);

gy: array[1..8] of integer = ( 1, 2, 2, 1,-1,-2,-2,-1);

out='result.txt';

Var mark:array[-1..10,-1..10] of boolean;

x,y,x0,y0:integer;

f:text;

Procedure Prepare;

var i,j:integer;

Begin

fillchar(mark,sizeof(mark),false);

for i:=-1 to 10 do

mark[-1,i]:=true;

mark[0,i]:=true;

mark[n+1,i]:=true;

mark[n+2,i]:=true;

end;

for i:=-1 to 10 do

mark[i,-1]:=true;

mark[i,0]:=true;

mark[i,n+1]:=true;

mark[i,n+2]:=true;

end;

mark[x0,y0]:=true;

x:=x0; y:=y0;

End;

Function Capab(i,j:integer):integer;

var k,l:integer;

Begin

l:=0;

for k:=1 to 8 do

if not mark[i+gx[k],j+gy[k]] then inc(l);

Capab:=l;

End;

Procedure move;

var i,j,u,v,k,s,tg,h:integer;

Begin

repeat

s:=10;

h:=0;

for k:=1 to 8 do

i:=x+gx[k];

j:=y+gy[k];

if mark[i,j] then

inc(h);

continue;

end;

tg:=Capab(i,j);

if tg<s then

s:=tg;

u:=i;

v:=j;

end;

end;

if h=8 then exit;

x:=u; y:=v;

mark[x,y]:=true;

writeln(f,x,' ',y);

until h=8;

End;

BEGIN

clrscr;

write('Nhap vi tri xuat phat (0<x,y<9): ');

readln(x0,y0);

Prepare;

assign(f,out);

rewrite(f);

writeln(f,x,' ',y);

Move;

close(f);

END.

Bài 2. Sắp xếp

Đối với bài toán này thì ta không thể áp dụng các thuật toán sắp xếp thông thường được vì số lượng phần tử là quá lớn. ở đây ta nhận xét tuổi của dân cư là một số nguyên nằm trong khoảng từ 0 đến 100. Do vậy ta áp dụng thuật toán sắp xếp Pigeonhole như sau:

Chuẩn bị một mảng 101 phần tử từ 0 đến 100 kiểu Longint để lưu trữ số người cùng độ tuổi. Tiến hành đọc lần lượt từ file dữ liệu tuổi của dân cư, gặp độ tuổi nào thì tăng phần tử tương ứng của mảng lên 1. Sau khi đọc hết file dữ liệu ta sẽ được một mảng lưu giữ số lượng người cùng độ tuổi. Công việc cuối cùng bây giờ chỉ là ghi ra file kết quả lần lượt các số theo từng độ tuổi được lưu giữ trong mảng trên.

PROGRAM PigeonHole;

Uses crt;

Const inp='tuoi.inp';

out='tuoi.out';

n=100;

Var age:array[0..n] of longint;

f:text;

Procedure readinp;

var i,k:integer;

Begin

for i:=0 to n do

age[i]:=0;

assign(f,inp);

reset(f);

while not seekeof(f) do

read(f,k);

inc(age[k]);

end;

close(f);

End;

Procedure Writeout;

var i,j:integer;

Begin

assign(f,out);

rewrite(f);

for i:=0 to n do

for j:=1 to age[i] do

write(f,i,' ');

if (j mod 1000 = 0) or (j=age[i]) then writeln(f);

end;

end;

close(f);

End;

BEGIN

readinp;

writeout;

END.

1 2 20 45 4 65 3

2 4 55 2 4 5 100

Đề số 12

Bài 1. Ghép số nguyên tố

Để giải quyết hiệu quả bài toán này ta cần tìm thuật toán kiểm tra một số có thể có nhiều chữ số mà biến đơn không lưu được có phải là số nguyên tố hay không.

Việc xử lý với số lớn ta đ• nhắc đến trong bài toán tính giai thừa, có nghĩa là phải xử lý chuỗi. Còn để kiểm tra nhanh một số có phải là số nguyên tố hay không ta dựa vào nhận xét một số nguyên tố thì chia 6 dư 1 hoặc dư 5. Lưu ý, điều ngược lại là không đúng, cho nên ta kiểm tra thấy số đó chia 6 dư 1 hoặc dư 5 thì lại phải tiếp tục áp dụng các phương pháp kiểm tra số nguyên tố thông thường để làm.

{$N+}

PROGRAM GhepSont;

uses crt;

const

fileout='nt.txt';

maxn=300;

var

n:integer;

f:text;

procedure readf;

write('N=');

readln(n);

end;

function modb(x,y:extended):extended;

modb:=y*frac(x/y);

end;

function prime(x:extended):boolean;

var

j,k:longint;

if (x<=3)or(x=5) then

prime:=true;

exit;

end;

if (modb(x,2)=0)or(modb(x,3)=0)or(modb(x,5)=0) then

prime:=false;

exit;

end;

if x>3 then

prime:=true;

j:=5;k:=2;

while j+k<=sqrt(x) do

j:=j+k;

if modb(x,j) =0 then

prime:=false;

exit;

end;

k:=6-k;

end;

end;

end;

procedure solve;

var

i,bn:longint;

code,count:integer;

k,l,truoc:extended;

s,tg:string;

i:=2;

bn:=2;

count:=1;

repeat

if prime(i) then

if count=1 then

inc(count);

str(i,s);

truoc:=i;

end

else

count:=1;

str(i,tg);

s:=s+tg;

val(s,k,code);

if prime(k) then

dec(n);

writeln(f,k:0:0);

if n=0 then

close(f);

halt(0);

end;

end;

end;

end;

if i<5 then i:=i+1

else

i:=i+bn;

bn:=6-bn;

end;

until false;

end;

procedure result;

assign(f,fileout);

rewrite(f);

end;

BEGIN

clrscr;

readf;

result;

solve;

END.

Bài 2. Xếp việc

Sắp xếp các công việc theo trình tự không tăng của tỷ số T[i]/C[i], đó là trình tự thực hiện tốt nhất.

PROGRAM XepViec;

uses crt;

const

fileinp='xepviec.inp';

fileout='xepviec.out';

maxn=1000;

var

n:integer;

sum,money:longint;

d,p:array[1..maxn]of integer;

index:array[0..maxn]of real;

vt:array[0..maxn]of integer;

time:array[1..maxn]of longint;

procedure readf;

var

f:text;

i:integer;

assign(f,fileinp);

reset(f);

read(f,n);

sum:=0;

for i:=1 to n do

read(f,d[i],p[i]);

inc(sum,p[i]);

end;

close(f);

end;

procedure makeindex;

var

i:integer;

for i:=1 to n do

index[i]:=d[i]/p[i];

vt[i]:=i;

end;

index[0]:=0;

vt[0]:=0;

end;

procedure sort(l,r:integer);

var

i,j,t1:integer;

v,t:real;

if r>l then

v:=index[r];

i:=l-1;

j:=r;

repeat

repeat inc(i); until index[i]>=v;

repeat dec(j); until index[j]<=v;

t:=index[i];index[i]:=index[j];index[j]:=t;

t1:=vt[i];vt[i]:=vt[j];vt[j]:=t1;

until j<i;

index[j]:=index[i];index[i]:=index[r];index[r]:=t;

vt[j]:=vt[i];vt[i]:=vt[r];vt[r]:=t1;

sort(l,i-1);sort(i+1,r);

end;

end;

procedure result;

var

f:text;

i,ti:integer;

assign(f,fileout);

rewrite(f);

money:=0;

ti:=0;

for i:=1 to n do

time[vt[i]]:=ti;

inc(money,ti*p[vt[i]]);

inc(ti,d[vt[i]]);

end;

writeln(f,money);

for i:=1 to n do

writeln(f,time[i]);

close(f);

end;

BEGIN

readf;

makeindex;

sort(1,n);

result;

END.

Đề Số 13

Bài 1. Giao d?ch

Bài này ta chỉ cần sử dụng phương pháp loang một cách khéo léo. Xuất phát từ một đỉnh không có cung vào sẽ là nơi đặt trạm (hoặc nếu không có đỉnh nào như vậy thì lấy một đỉnh bất kỳ), ta loang ra toàn bộ đồ thị, sau đó loại bỏ các đỉnh vừa loang đó đi rồi làm lại như trên ta được số trạm ít nhất cần tìm. 2 câu sau chỉ là hệ quả của câu đầu tiên, xin dành cho bạn đọc tự giải quyết.

PROGRAM GiaoDich;

const tfi = 'GIAODICH.INP';

tfo = 'GIAODICH.OUT';

max = 100;

var a: array[1.. max, 1.. max] of Boolean;

VResult: array[1.. max * max, 1.. 2] of Byte;

Push: array[1.. max] of Integer;

Free, Visit: array[1.. max] of Boolean;

Number, Low: array[1.. max] of Integer;

n, count, countPush, countV: Integer;

f: Text;

procedure Enter;

var u, v: Integer;

FillChar(a, SizeOf(a), 0);

Assign(f, tfi); Reset(f);

Readln(f, n);

while not seekeof(f) do

Readln(f, u, v);

a[u, v]:= true;

end;

Close(f);

end;

procedure InitOne;

FillChar(Free, SizeOf(Free), 1);

count:= 0;

end;

procedure StandartDFS(u: Integer);

var v: Integer;

Free[u]:= false;

for v:= 1 to n do

if Free[v] and a[u, v] then

StandartDFS(v);

end;

procedure DFSOne(u: Integer);

var v: Integer;

Free[u]:= false;

for v:= 1 to n do

if Free[v] and a[u, v] then

DFSOne(v);

Inc(count);

Number[count]:= u;

end;

procedure PrintOne;

var i: Integer;

Writeln(f, countPush);

for i:= 1 to countPush do

Write(f, Push[i], ' ');

Writeln(f);

end;

procedure InitTwo;

FillChar(Free, SizeOf(Free), 1);

countV:= 0;

end;

procedure DFSTwo(u: Integer);

var v: Integer;

Free[u]:= false;

for v:= 1 to n do

if a[u, v] then

if not Free[v] then

Inc(countV);

VResult[countV, 1]:= u; VResult[countV, 2]:= v;

end

else DFSTwo(v);

end;

end;

procedure PrintTwo;

var i: Integer;

Writeln(f, countV);

for i:= 1 to countV do

Writeln(f, VResult[i, 1], ' ', VResult[i, 2]);

end;

procedure PrintThree;

var i: Integer;

Writeln(f, countPush - 1);

for i:= 2 to countPush do

Writeln(f, Push[1], ' ', Push[i]);

end;

procedure Solve;

var i: Integer;

{*****************************************************************}

InitOne;

for i:= 1 to n do

if Free[i] then DFSOne(i);

FillChar(Free, SizeOf(Free), true);

countPush:= 0;

for i:= n downto 1 do

if Free[Number[i]] then

Inc(countPush);

Push[countPush]:= Number[i];

StandartDFS(Number[i]);

end;

PrintOne;

{*****************************************************************}

InitTwo;

for i:= 1 to countPush do

DFSTwo(Push[i]);

PrintTwo;

{*****************************************************************}

PrintThree;

end;

Enter;

Assign(f, tfo); Rewrite(f);

Solve;

Close(f);

end.

Bài 2. Xoá số

Giả sử N=A1A2...Am với Ai là các chữ số thập phân đi từ trái sang phải d•y chữ số A1,A2,...,Am. Tìm chữ số Ai đầu tiên lớn hơn chữ số ngay sau nó, nếu có thì đó là chữ số cần xoá, nếu không thì xoá chữ số cuối cùng.

Chương trình ở đây giải quyết được số rất lớn nhập từ file.

Program FindNumber;

const tfi = 'NUMBER.INP';

tfo = 'NUMBER.OUT';

max = 11;

var Count: array[1.. max] of LongInt;

Number: array[1.. max] of Integer;

value, min: Integer;

n, m, k, pmin, vt: LongInt;

f: Text;

procedure Process;

while k > 0 do

if value < Number[k] then

if m >= count[k] then

m:= m - count[k];

Dec(k);

end

else

count[k]:= count[k] - m;

m:= 0;

Break;

end;

end

else

if Value = Number[k] then

Inc(count[k]);

Exit;

end

else

Inc(k);

Number[k]:= value;

count[k]:= 1;

Exit;

end;

end;

Inc(k);

Number[k]:= value;

Count[k]:= 1;

end;

procedure Enter;

var i: LongInt;

Assign(f, tfi); Reset(f);

Readln(f, n, m);

min:= 10;

for i:= 1 to m + 1 do

Read(f, value);

if (value <> 0) and (value < min) then

min:= value;

pmin:= i;

end;

if min = 1 then Break;

end;

Close(f);

FillChar(count, SizeOf(count), 0);

Assign(f, tfi); Reset(f);

Readln(f, n, m);

m:= m - pmin + 1;

for i:= 1 to pmin do

Read(f, value);

k:= 0;

vt:= n;

for i:= pmin + 1 to n do

Read(f, value);

Process;

if m = 0 then

vt:= i;

Break;

end;

end;

Close(f);

end;

procedure Print;

var i, j: LongInt;

fi: Text;

while m > 0 do

if m >= count[k] then

m:= m - count[k];

Dec(k);

end

else

count[k]:= count[k] - m;

m:= 0;

end;

end;

Assign(f, tfo); Rewrite(f);

Write(f, min, ' ');

for i:= 1 to k do

for j:= 1 to count[i] do

Write(f, Number[i], ' ');

Assign(fi, tfi); Reset(fi);

Readln(fi, n, m);

for i:= 1 to vt do

Read(fi, j);

for i:= vt + 1 to n do

Read(fi, j);

Write(f, j, ' ');

end;

Close(fi);

Close(f);

end;

Enter;

Print;

end.

16 7

2 1 2 3 2 9 5 8 0 2 3 7 5 6 3 2

Đề số 14

Bài 1. Lá bài

Xây dựng một mảng C[1..N] mà C[i] bằng số lá bài có màu i, 1<=i<=N. Nếu C[i] =0, loại lá bài i và giảm C[F[i]] một đơn vị, cứ như vậy cho đến khi mọi C[j] của các lá bài chưa bị loại đều khác 0.

PROGRAM LaBai;

Uses crt;

Const marr=10000;

inp='labai.inp';

out='labai.out';

Type mang=array[1..marr] of integer;

Var f:text;

n:integer;

bac,mau:mang;

{--------------------------------------------------------------}

Procedure Doc;

Var i,c:integer;

Begin

Assign(f,inp);

Reset(f);

Readln(f,n);

for i:=1 to n do begin bac[i]:=0; mau[i]:=0; end;

For i:=1 to n do

read(f,c);

mau[i]:=c;

inc(bac[c]);

inc(bac[i]);

end;

Close(f);

End;

{--------------------------------------------------------------}

Procedure xoadinh;

Var i,j:integer;

Begin

for i:=1 to n do

if bac[i]=1 then

j:=i;

while bac[j]=1 do

dec(bac[j]);

dec(bac[mau[j]]); mau[j]:=-mau[j];

j:=-mau[j];

end;

end;

End;

{--------------------------------------------------------------}

Procedure inkq;

Var i,s:integer;

Begin

Assign(f,out);

Rewrite(f); s:=1;

for i:=1 to n do

if mau[i]>0 then

write(f,i,' '); inc(s);

if s mod 30=0 then writeln(f);

end;

end;

writeln(f); s:=1;

for i:=1 to n do

if mau[i]>0 then

write(f,mau[i],' '); inc(s);

if s mod 30=0 then writeln(f);

end;

end;

Close(f);

End;

{--------------------------------------------------------------}

BEGIN

ClrScr;

Doc;

writeln('Wait !..');

xoadinh;

Inkq;

write('OK .');

{Readln;}

END.

4

3 1 1 2

Bài 2. Lịch gia công tuần tự hai máy

Nhận xét: vì phải làm trên máy A xong mới được làm trên máy B cho nên muốn thời gian nhỏ nhất có thể thì ta phải cho máy A làm liên tục, lúc đó

+ Tchờ

Do vậy Tchờ càng nhỏ càng tốt. Điều đó có nghĩa là máy A hoàn thành chi tiết càng nhanh càng tốt, ngược lại máy B hoàn thành chi tiết càng chậm càng tốt.

Từ đó ta áp dụng thuật toán Johnson như sau:

Chuẩn bị một d•y các ngăn rống (số ngăn bằng số chi tiết). Xếp thời gian hoàn thành các chi tiết đối với cả hai máy vào một bảng. Tìm thời gian nhỏ nhất của bảng. Nếu nó thuộc máy A thì xếp chi tiết vào bên trái nhất của ngăn còn rỗng, còn nếu nó thuộc máy B thì xếp chi tiết vào ngăn bên phải nhất còn rỗng. Sau đó xoá khỏi bảng chi tiết đó đi. Cứ làm như vậy đến khi không còn ngăn rỗng nào. Ta có thứ tự thực hiện các chi tiết từ trái sang phải.

PROGRAM LichGiaCong;

Uses crt;

Const inp='thoigian.txt';

out='lich.out';

marr=1000;

Var n,l,r:integer;

f:text;

ta,tb,sc:array[1..marr] of integer;

marka,markb:array[1..marr] of boolean;

Procedure readinp;

var i:integer;

Begin

assign(f,inp);

reset(f);

readln(f,n);

for i:=1 to n do read(f,ta[i]);

for i:=1 to n do read(f,tb[i]);

close(f);

End;

Procedure schedule;

var i,ja,jb,ma,mb:integer;

a,b:boolean;

for i:=1 to n do marka[i]:=false;

for i:=1 to n do markb[i]:=false;

l:=0; r:=n+1;

repeat

ma:=maxint;

for i:=1 to n do

if not marka[i] then

if ma>ta[i] then

ma:=ta[i];

ja:=i;

end;

mb:=maxint;

for i:=1 to n do

if not markb[i] then

if mb>tb[i] then

mb:=tb[i];

jb:=i;

end;

if ma<=mb then

inc(l);

sc[l]:=ja;

marka[ja]:=true;

markb[ja]:=true;

end

else

dec(r);

sc[r]:=jb;

marka[jb]:=true;

markb[jb]:=true;

end;

until l+1=r;

end;

Procedure writeout;

var i:integer;

Begin

assign(f,out);

rewrite(f);

for i:=1 to n do write(f,sc[i],' ');

close(f);

End;

BEGIN

readinp;

schedule;

writeout;

END.

5

2 5 3 7 3

5 1 5 6 6

Đề Số 15

Bài 1. D•y ngoặc

Kiểm tra tính hợp lệ của d•y ngoặc bằng cách sử dụng hai biến đếm T, V, một biến kiểm tra ngoặc tròn '()', một biến kiểm tra ngoặc vuông '[]'. Quy tắc kiểm tra như sau: duyệt từ đầu đến cuối d•y, nếu:

- gặp dấu ngoặc '(' thì tăng T lên 1

- gặp dấu ngoặc ')' thì giảm T đi 1

- gặp dấu ngoặc '[' thì tăng V lên 1

- gặp dấu ngoặc ']' thì giảm V đi 1

Trong quá trình duyệt nếu T (hoặc V) giảm xuống <0 thêm dấu một ngoặc tròn '(' (hoặc ngoặc vuông '[') ngay trước vị trí đó để T (hoặc V) bằng 0. Nếu T và V đều bằng 0 khi kết thúc quá trình duyệt thì d•y ngoặc là đúng.Trường hợp kết thúc d•y mà T và V vẫn lớn hơn 0 thì thêm đủ số ngoặc ')' và ']' vào cuối d•y để T và V cùng bằng 0.

PROGRAM Bracket;

Uses crt;

Const inp='bracket.inp';

out='bracket.out';

Var s:string[200];

f:text;

t,v:integer;

Procedure readinp;

Begin

assign(f,inp);

reset(f);

readln(f,s);

close(f);

End;

procedure lamnguoc;

var i:integer;

t:=0; v:=0;

i:=length(s);

while i>0 do

case s[i] of

'(': dec(t);

')': inc(t);

'[': dec(v);

']': inc(v);

end;

if t<0 then

insert(')',s,i+1);

t:=0;

end;

if v<0 then

insert(']',s,i+1);

v:=0;

end;

dec(i);

end;

end;

procedure lamxuoi;

var i:integer;

t:=0; v:=0;

i:=1;

while i<=length(s) do

case s[i] of

'(': inc(t);

')': dec(t);

'[': inc(v);

']': dec(v);

end;

if t<0 then

insert('(',s,i);

inc(i);

t:=0;

end;

if v<0 then

insert('[',s,i);

inc(i);

v:=0;

end;

inc(i);

end;

if (t>0) or (v>0) then lamnguoc;

end;

Procedure writeout;

Begin

assign(f,out);

rewrite(f);

write(f,s);

close(f);

End;

BEGIN

readinp;

lamxuoi;

writeout;

END.

((]]()(([[])

Bài 2. Đua ngựa

Ta áp dụng phương pháp của Tôn Tẫn giúp Điền Kỵ thắng vua Tề thời Xuân Thu. Có nghĩa là ta cho con ngựa có hệ số thấp nhất của mình đấu với con ngựa có hệ số cao nhất của vua Tề, rồi lấy con ngựa có hệ số thấp thứ hai đấu với con ngựa có hệ số cao thứ hai của vua Tề, ... cứ làm như vậy ta sẽ có số trận thắng nhiều nhất có thể. Tuy nhiên ở đây ta phải để ý đến trường hợp các con ngựa có cùng hệ số, lúc đó ta sẽ phải xét riêng.

PROGRAM Duangua;

Uses crt;

Const tf='heso.txt';

tf1='lich.txt';

Type bg=record

cs:integer;

gt:integer;

end;

mang= array[0..6000] of bg;

Var f:text;

a,b:mang;

x:array[1..6000] of integer;

n,diem:integer;

kd:boolean;

{-------------------------------------------------------------}

Procedure doc;

Var i:integer;

Begin

Assign(f,tf);

reset(f);

Read(f,n);

For i:=1 to n do

read(f,a[i].gt);

For i:=1 to n do

read(f,b[i].gt);

close(f);

End;

{-------------------------------------------------------------}

Procedure sapxep(var c:mang);

Var i,j:integer;

x:bg;

Begin

For i:=2 to n do

x:=c[i]; c[0].gt:=x.gt; j:=i-1;

while c[j].gt<x.gt do

c[j+1]:=c[j];

dec(j);

end;

c[j+1]:=x;

end;

End;

{-------------------------------------------------------------}

Procedure thubg(i,j:integer);

Var i1,j1:integer;

Bạn đang đọc truyện trên: Truyen2U.Pro