Trong khu vườn, người ta trồng một hàng cây chạy dài gồm có N cây, mỗi cây có độ cao là a1, a2,…aN.
Người ta cần lấy M mét gỗ bằng cách đặt cưa máy sao cho lưỡi cưa ở độ cao H (mét) để cưa tất cả các cây có độ cao lớn hơn H (dĩ nhiên những cây có độ cao không lớn hơn H thì không bị cưa).
Ví dụ: Nếu hàng cây có các cây với độ cao tương ứng là 20; 15; 10 và 18 mét, cần lấy 7 mét gỗ. Lưỡi cưa đặt tại độ cao hợp lí là 15 mét thì độ cao của các cây còn lại sau khi bị cưa tương ứng là 15; 15; 10 và 15 mét. Tổng số mét gỗ lấy được là 8 mét (dư 1 mét).
Yêu cầu: Hãy tìm vị trí đặt lưỡi cưa hợp lí (số nguyên H lớn nhất) sao cho lấy được M mét gỗ và số mét gỗ dư ra là ít nhất.
Dữ liệu vào:Đọc từ file văn bản WOOD.INP có cấu trúc
- Dòng thứ nhất chứa 2 số nguyên dương N và M (1≤N≤106; 1≤M≤2.109) cách nhau một dấu cách.
- Dòng thứ hai chứa N số nguyên dương ai là độ cao của mỗi cây trong hàng (1≤ai≤109; i=1…N), mỗi số cách nhau ít nhất một dấu cách.
Kết quả: Ghi ra file WOOD.OUT, một dòng duy nhất ghi một số nguyên cho biết giá trị cần tìm.
Ví dụ:
WOOD.INP |
WOOD.OUT |
4 7 20 15 10 18 |
15 |
Hướng dẫn:
Gọi Max là giá trị lớn nhất của hàng cây.
Duyệt vị trí đặt lưỡi cưa từ Max về 0, Nếu thỏa mãn thì lấy vị trí và kết thúc.
Function IsOk(h:Longint):Boolean;
Var i:Longint;
Begin
S:=0;
For i:=1 To N Do
If A[i]>h Then S:=S+A[i]-h;
Exit(S>=M);
End;
Function Wood:Longint;
Begin
For h:=Max Downto 0 Do
If IsOK(h) Then Exit(h);
End;
Độ phức tạp là O(N.Max).
Tìm kiếm nhị phân theo độ cao cần đặt lưỡi cưa như sau:
d=0, c= Max,
Lặp khi d ≤ c.
h=(d+c) Div 2
Kiểm tra số mét gỗ được lấy ra khi chặt ở độ cao h có thỏa không?
- Nếu thỏa Thì tìm kiếm nhị phân h từ d=h đến c.
- Ngược lại thì tìm kiếm nhị phân h từ d đến c=h-1
Function Wood:Longint;
Begin
d:=0;c:=Max;
While d ≤ c Do
Begin
h:=(d+c) Div 2;
If IsOK(h) Then d:=h
Else c:=h-1;
End;
Exit(h);
End;
Độ phức tạp là O(N.Log(Max)).
» Tin mới nhất:
» Các tin khác: