Thông Báo:
Mọi thắc mắc xin liên hệ facebook: Bá Sơn
fb.com/sonden2000
Posted by : Unknown
Wednesday, March 15, 2017
BÀI
TẬP VỀ SẮP XẾP.
1.NUMCON -
Ghép số lớn
|
Vaxia đã viết được một
số lớn trên một cuộn giấy dài và muốn khoe với anh trai Petia về thành quả vừa
đạt được. Tuy nhiên, khi Vaxia vừa ra khỏi phòng để gọi anh trai thì cô
em Kachia chạy vào phòng và xé rách cuộn giấy thành một số mảnh. Kết quả là
trên mỗi mảnh có một hoặc vài kí số theo thứ tự đã viết.
Bây giờ Vaxia không
thể nhớ chính xác mình đã viết số gì. Vaxia chỉ nhớ rằng đó là một số rất lớn.
Để làm hài lòng cậu em
trai, Petia quyết định truy tìm số nào là lớn nhất mà Vaxia đã có thể
viết lên cuộn giây trước khi bị xé. Bạn hãy giúp Petia làm việc này.
Dữ liệu vào:
Ghi một hoặc nhiều
dòng. Mỗi dòng ghi một dãy kí số. Số dòng không vượt quá 100. Mỗi dòng ghi từ 1
đến 100 kí số. Bảo đảm rằng có ít nhất một dòng mà kí số đầu tiên khác 0.
Dữ liệu ra:
Ghi ra số lớn nhất đã
có thể viết trên cuộn giấy trước khi bị xé rách.
Ví dụ
Input
|
Output
|
2
20 004 66 |
66220004
|
3
|
3
|
HƯỚNG DẪN:
• Lấy tư tưởng Quick Sort, ta tiến hành thêm
vào đuôi số đó chữ số đầu tiên của nó cho đến khi có độ dài bằng với số có độ
dài lớn nhất. Khi này các số có độ dài bằng nhau ta tiến hành sắp xếp chúng giảm
dần rồi ghi ra. Với mỗi số ta chỉ ghi m chữ số đầu tiên với m là độ dài ban đầu
của nó.
/// code tham khảo:
- Program
NUMCON;
- Var
- n :Byte;
- A :Array[1..101] of String[100];
-
- procedure
Enter;
- begin
- n:=0;
- while
not EoF do
- begin
- Inc(n); ReadLn(A[n]);
- end;
- end;
-
- procedure
Swap(i,j :Byte);
- var
- tmp :String[100];
- begin
- tmp:=A[i]; A[i]:=A[j]; A[j]:=tmp;
- end;
-
- procedure
Greedy;
- var
- i,j :Byte;
- begin
- for i:=1 to n-1 do
- for
j:=i+1 to n do
- if (A[i]+A[j]<A[j]+A[i]) then Swap(i,j);
- end;
-
- procedure
Escape;
- var
- i :Byte;
- begin
- for i:=1 to n do
Write(A[i]);
- end;
-
- Begin
- Assign(Input,'');
Reset(Input);
- Assign(Output,'');
Rewrite(Output);
- Enter;
- Greedy;
- Escape;
- Close(Input); Close(Output);
- End.
2.
INSUL - Cách nhiệt
|
Cho một dãy N viên gạch lần lượt có độ
cách nhiệt là các số a1.. aN.
Nếu xếp lần lượt các viên gạch theo trình tự đó thì độ cách nhiệt cả khối là a1 + a2 + ... + aN + max(0, a2 - a1) +
max(0, a3 - a2) +
... + max(0, aN - aN -
1). Nhiệm vụ của bạn là tìm cách xếp sao cho độ cách nhiệt của cả
khối là lớn nhất có thể.
Dữ liệu
- Dòng đầu ghi số nguyên dương N (0
< n ≤ 10^5).
- N dòng sau mỗi dòng ghi một số ai ( 1 ≤ i ≤ N và 1 ≤ ai ≤ 10000).
Kết qủa
Ghi trên một dòng kết quả cần tìm.
Ví dụ
Dữ liệu:
4
5
4
1
7
Kết qủa
24
CODE:
- Program
INSUL;
- Var
- n,res :LongInt;
- A :Array[1..100000] of LongInt;
-
- procedure
Enter;
- var
- i :LongInt;
- begin
- ReadLn(n); res:=0;
- for i:=1 to n do
- begin
- ReadLn(A[i]); res:=res+A[i];
- end;
- end;
-
- procedure
Swap(i,j :LongInt);
- var
- tmp :Integer;
- begin
- tmp:=A[i]; A[i]:=A[j]; A[j]:=tmp;
- end;
-
- procedure
Sort(l,h :LongInt);
- var
- i,j,k :LongInt;
- begin
- if (l>=h) then
Exit;
- i:=l; j:=h; k:=A[(l+h) div 2];
- repeat
- while
(A[i]<k) do Inc(i);
- while
(A[j]>k) do Dec(j);
- if (i<=j) then
- begin
- if (i<j) then Swap(i,j);
- Inc(i); Dec(j);
- end;
- until
(i>j);
- Sort(l,j); Sort(i,h);
- end;
-
- procedure
Greedy;
- var
- i,j :LongInt;
- begin
- i:=1; j:=n;
- while
(i<j) do
- begin
- res:=res+A[j]-A[i];
- Inc(i); Dec(j);
- end;
- end;
-
- Begin
- Assign(Input,'');
Reset(Input);
- Assign(Output,'');
Rewrite(Output);
- Enter;
- Sort(1,n);
- Greedy;
- Write(res);
- Close(Input); Close(Output);
- End.
NOIXICH - Nối Xích
|
Người ta có N đoạn dây xích(N <=
20000), mỗi đoạn dây xích là 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 mắt 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 là
bằng nhau với mọi mắt xích. Nhiêm vụ của bạn là phải nối chúng lại thành một
đoạn dây xích duy nhất với thời gian ít nhất( hay số mắt xích bị cắt và hàn lại
là ít nhất).
Input
Dữ liệu vào cho trong file văn bản có
cấu trúc như sau: Dòng đầu tiên là số N, số đoạn xích. Những dòng tiếp theo ghi
N số nguyên dương, số thứ i là số mắt xích có trong đoạn xích thứ i(i <= i
<= N) Hai số cạnh nhau trên cùng một dòng cách nhau ít nhất một dấu cách.
Output
Một dòng duy nhất là số đơn vị thời
gian mà bạn cần để nối N đoạn xích đã cho.
Example
Input:
3
2 3
4
Output:
2
Hướng dẫn thuật toán: – Sắp xếp số đoạn xích tăng dần.
– Luôn xử lý các đoạn xích có độ dài bằng 1 theo cách chặt ra rồi đem đi nối 2 đoạn xích khác.
– Xử lý chặt từ đoạn xích ngắn nhất, tăng dần khi không còn đoạn xích ngắn hơn. Chặt các đoạn xích ngắn (có độ dài lớn hơn 1) theo cách chặt dần mắt xích của nó đem đi nối các đoạn xích khác, cho tới khi nó có độ dài là 1.
– Việc chặt-hàn dừng lại khi số đoạn xích chỉ còn 1.
– Luôn xử lý các đoạn xích có độ dài bằng 1 theo cách chặt ra rồi đem đi nối 2 đoạn xích khác.
– Xử lý chặt từ đoạn xích ngắn nhất, tăng dần khi không còn đoạn xích ngắn hơn. Chặt các đoạn xích ngắn (có độ dài lớn hơn 1) theo cách chặt dần mắt xích của nó đem đi nối các đoạn xích khác, cho tới khi nó có độ dài là 1.
– Việc chặt-hàn dừng lại khi số đoạn xích chỉ còn 1.
Code tham khảo:
- Program
NOIXICH;
- Var
- n,m :Integer;
- A :Array[1..20000] of Integer;
-
- procedure
Enter;
- var
- i :Integer;
- begin
- ReadLn(n); i:=0;
- while
not EoF do
- while
not EoLn do
- begin
- Inc(i); Read(A[i]);
- end;
- end;
-
- procedure
Swap(i,j :Integer);
- var
- tmp :Integer;
- begin
- tmp:=A[i]; A[i]:=A[j]; A[j]:=tmp;
- end;
-
- procedure
Sort(l,h :Integer);
- var
- i,j,k :Integer;
- begin
- if (l>=h) then
Exit;
- i:=l; j:=h; k:=A[(l+h) div 2];
- repeat
- while
(A[i]<k) do Inc(i);
- while
(A[j]>k) do Dec(j);
- if (i<=j) then
- begin
- if (i<j) then Swap(i,j);
- Inc(i); Dec(j);
- end;
- until
(i>j);
- Sort(l,j); Sort(i,h);
- end;
-
- procedure
Solve;
- var
- i :Integer;
- begin
- i:=1; m:=0;
- while
(n>1) do
- begin
- if (A[i]>n-1) then Break;
- m:=m+A[i];
- Dec(n,A[i]+1);
- Inc(i);
- end;
- m:=m+n-1;
- end;
-
- Begin
- Assign(Input,'');
Reset(Input);
- Assign(Output,'');
Rewrite(Output);
- Enter;
- Sort(1,n);
- Solve;
- Write(m);
- Close(Input); Close(Output);
- End.
BWPOINTS -
VOI 2011 Nối điểm đen trắng
|
Trên trục số thực cho
n điểm đen và n điểm trắng hoàn toàn phân biệt. Các điểm đen có tọa độ nguyên
a1, a2, …, an còn các điểm trắng có tọa độ nguyên b1, b2, …, bn. Người ta muốn
chọn ra k điểm đen và k điểm trắng để nối mỗi một điểm đen với một điểm trắng
sao cho k đoạn thẳng tạo được đôi một không có điểm chung.
Yêu cầu: Cho tọa độ của n điểm đen a1, a2, …, an
và tọa độ của điểm trắng b1, b2, …, bn. Hãy tìm giá trị k lớn nhất thỏa mãn yêu
cầu trên.
Dữ liệu:
- Dòng
thứ nhất chứa số nguyên dương n (n <= 10^5).
- Dòng
thứ hai chứa các số a1, a2, …, an (|ai| <= 10^9, i = 1, 2,…, n)
- Dòng
thứ ba chứa các số b1, b2, …, bn (|bi| <= 10^9, i = 1, 2,…, n)
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 một số nguyên duy nhất là số k
lớn nhất tìm được
Ví dụ:
Dữ liệu
|
Kết quả
|
3
0 3 1
-3 5 -1
|
2
|
Ràng buộc: 50% số test ứng với 50% số điểm của bài
có 1 <= n <= 100
CODE THAM KHẢO:
- type
- arr1 = array[1..200001] of longint;
- var
- fi,fo : text;
- n,res,nhoa,nhob:longint;
- a:arr1;
- b,vt:arr1;
- {------------------------------------------------------------------------}
- procedure
nhap;
- var i,j:longint;
- begin
- readln(n);
- for i:=1 to n do
- read(a[i]);
- readln;
- for i:=1 to n do
- read(b[i]);
- end;
- {------------------------------------------------------------------------}
- procedure
khoitao;
- var i,j:longint;
- begin
- res:=0;
- fillchar(vt,sizeof(vt),0);
- end;
- {------------------------------------------------------------------------}
- procedure
doicho(var x,y:longint);
- var tg:longint;
- begin
- tg:=x;
- x:=y;
- y:=tg;
- end;
- {------------------------------------------------------------------------}
- procedure
sort(l,r:longint);
- var
i,j,mid:longint;
- begin
- i:=l;
- j:=r;
- mid:=a[(l+r)div 2 ];
- repeat
- while
a[i]<mid do inc(i);
- while
a[j]>mid do dec(j);
- if
i<=j then
- begin
- doicho(a[i],a[j]);
- doicho(vt[i],vt[j]);
- inc(i);
- dec(j);
- end;
- until
i>j;
- if
l<j then sort(l,j);
- if
i<r then sort(i,r);
- end;
- {------------------------------------------------------------------------}
- {------------------------------------------------------------------------}
- procedure
xuly;
- var
i,j,tg:longint;
- begin
- for
i:=n+1 to n*2 do
- begin
- a[i]:=b[i-n];
- vt[i]:=1;
- end;
- sort(1,n*2);
- i:=1;
- while
i<2*n do
- begin
- if vt[i]<>vt[i+1] then
- begin
- inc(res);
- i:=i+2;
- end
- else inc(i);
- end;
- end;
- {------------------------------------------------------------------------}
- procedure
inkq;
- begin
- write(res);
- readln;
- end;
- {------------------------------------------------------------------------}
- {------------------------------------------------------------------------}
- {------------------------------------------------------------------------}
- {------------------------------------------------------------------------}
- BEGIN
- nhap;
- khoitao;
- xuly;
- inkq;
- END.
NKSGAME - VOI08 Trò chơi với dãy số
|
Hai bạn học sinh trong lúc nhàn rỗi
nghĩ ra trò chơi sau đây. Mỗi bạn chọn trước một dãy số gồm n số nguyên. Giả sử
dãy số mà bạn thứ nhất chọn là:
b1, b2,
..., bn
còn dãy số mà bạn thứ hai chọn là
c1, c2,
..., cn
Mỗi lượt chơi mỗi bạn đưa ra một số
hạng trong dãy số của mình. Nếu bạn thứ nhất đưa ra số hạng bi (1 ≤ i ≤ n), còn bạn thứ hai đưa ra số
hạng cj (1
≤ j ≤ n) thì giá của lượt chơi đó sẽ là |bi+cj|.
Ví dụ: Giả sử dãy số bạn thứ nhất chọn
là 1, -2; còn dãy số mà bạn thứ hai chọn là 2, 3. Khi đó các khả năng có thể
của một lượt chơi là (1, 2), (1, 3), (-2, 2), (-2, 3). Như vậy, giá nhỏ nhất
của một lượt chơi trong số các lượt chơi có thể là 0 tương ứng với giá của lượt
chơi (-2, 2).
Yêu cầu
Hãy xác định giá nhỏ nhất của một lượt
chơi trong số các lượt chơi có thể.
Dữ liệu
- Dòng đầu tiên chứa số nguyên dương n
(n ≤ 105)
- Dòng thứ hai chứa dãy số nguyên b1, b2, ..., bn (|bi| ≤ 109, i=1, 2,
..., n)
- Dòng thứ hai chứa dãy số nguyên c1, c2, ..., cn (|ci| ≤ 109, i=1, 2,
..., n)
Hai số liên tiếp trên một dòng được ghi
cách nhau bởi dấu cách.
Kết quả
Ghi ra giá nhỏ nhất tìm được.
Ràng buộc
- 60% số tests ứng với 60% số điểm của
bài có 1 ≤ n ≤ 1000.
Ví dụ
Dữ liệu:
2
1 -2
2 3
Kết qủa
0
HƯỚNG DẪN:
Bài yêu cầu với mỗi số b[i] tìm c[j] sao
cho |b[i]+c[j]| nhỏ
nhất. Suy ra chọn sao cho b[i]+c[j] có giá trị gần 0 nhất
Thuật toán sẽ là:
1. Sắp
xếp lại mảng c[].
2. Với
mỗi b[i] tìm
kiếm nhị phân c[j] thỏa mãn b[i]+c[j] có
giá trị gần 0 nhất.
CODE THAM
KHẢO:
- >
- bài tập dạng sắp xếp pascal , các bài tập sắp xếp pascal , sắp xếp pascal , sắp xếp pascal. >
- Bài tập về sắp xếp có lời giải.