Thứ Hai, 16 tháng 12, 2013

Đoạn gối 3



Cho N đoạn thẳng trên trục số với các điểm đầu ai và điểm cuối bi là những số nguyên trong khoảng
 -1000..1000, ai < bi. i = 1..n. Liệt kê các đoạn thẳng gối nhau có tổng chiều dài C lớn nhất.


DOAN.INP

DOAN.OUT
Dữ liệu vào: tệp văn bản DOAN.INP: xem bài Đoạn gối 1.
Dữ liệu ra: tệp văn bản DOAN.OUT
Dòng đầu tiên: số tự nhiên C.
Mỗi dòng tiếp theo chứa một số tự nhiên biểu thị chỉ số của đoạn thẳng gối nhau liên tiếp trong dãy tìm được.
Thí dụ này cho biết hai đoạn 2  và 4 tạo thành dãy đoạn gối nhau liên tiếp có tổng chiều dài max là 39.

8
2 7
1 3
7 9
3 40
3 5
2 3
5 9
9 16


39
2
4


Thuật toán

Phương pháp: Quy hoạch động kết hợp với con trỏ trước t để giải trình kết quả.  
Giả sử các đoạn được sắp tăng theo đầu phải b. Kí hiệu c(i) là tổng chiều dài lớn nhất các đoạn thẳng gối nhau liên tiếp tạo thành một dãy nhận đoạn i làm phần tử cuối dãy (khi khảo sát các đoạn từ 1..i). Để ý rằng (bi -  ai) là chiều dài đoạn thứ i, ta có
c(1)  = chiều dài đoạn 1 = b1 - a1,
Với i = 2..N:    c(i) = max { c(j) | 1 £ j < i,  đoạn j kề trước đoạn i: bj = ai } + (bi -  ai), 
Nếu j là chỉ số đạt max thì đặt ti =  j.
            Độ phức tạp:  N2.
(*  Pascal  *)
(*=============================================
    Doan Goi 3: Liet ke cac doan goi nhau
                co tong chieu dai max
  ============================================*)
program DoanGoi3;
uses crt;
const
  mn = 1001; bl = #32; nl = #13#10;
  fn = 'doan.inp'; gn = 'doan.out';
type
  KieuDoan = record a,b,id: integer; end;
  md1 = array[0..mn] of KieuDoan;
  mi1 = array[0..mn] of integer;
var n,m: integer; { n – số lượng đoạn, m – số đoạn được chọn }
    d: md1;
    f,g: text;
    c: mi1; {c[i] = chieu dai max nhan i lam doan cuoi}
    t: mi1; { tro truoc }
procedure Doc; tự viết
procedure Qsort(l,r: integer); tự viết
procedure XuLi;
var i,j,jmax: integer;
begin
  fillchar(t,sizeof(t),0);{ Khơỉ tạo mảng trỏ trước }
  c[1] := d[1].b - d[1].a; { Chieu dai doan 1 }
  for i := 2 to n do
    begin
      c[i] := 0; jmax := i;
        for j := i-1 downto 1 do
          begin
            if (d[j].b < d[i].a) then break;
            if (d[j].b = d[i].a) then
               if (c[j] > c[jmax]) then
                         jmax := j;                
          end;
      c[i] := c[jmax] + (d[i].b - d[i].a); t[i] := jmax;
    end;
end;
procedure GiaiTrinh(i: integer); tự viết
procedure Ket; tự viết
BEGIN
  Doc; Qsort(1,n); XuLi; Ket;
END.

Nguồn:

SÁNG TẠO
TRONG THUẬT TOÁN
LẬP TRÌNH

Không có nhận xét nào:

Đăng nhận xét