.14 Xếp đoạn

Một phần của tài liệu Sáng tạo trong thuật toán và lập trình Quyển 2 (Trang 39 - 41)

Cho N đoạn thẳng trên trục số với các điểm đầu xi là những số nguyên trong khoảng 1000..1000

và độ dài di là những số nguyên dương trong khoảng 1..1000, i = 1..N. Tính tổng chiều dài các đoạn đó phủ trên trục số.

DOAN.INP OUTPUT Dữ liệu vào: tệp văn bản DOAN.INP Dòng đầu tiên: số tự nhiên 1 < N  1000.

Dòng thứ i trong N dòng tiếp theo, mỗi dòng chứa hai số nguyên ai di cách nhau qua dấu cách, biểu thị điểm đầu và chiều dài của đoạn thứ i, i = 1..N.

Dữ liệu ra: hiển thị trên màn hình tổng chiều dài t các đoạn phủ trên trục số. 5 3 5 -11 3 -20 4 -12 8 2 5 28 Thuật toán Phương pháp: tham.

Sắp tăng các đoạn theo điểm đầu x.

Ta dùng kí hiệu [x,y] biểu diễn cho đoạn thẳng có điểm đầu x và điểm cuối y, x:d biểu diễn cho đoạn thẳng có điểm đầu x và chiều dài d. Ta định nghĩa một làn là đoạn tạo bởi các đoạn giao nhau liên tiếp. Hai đoạn [a,b] và [c,d] được gọi là giao nhau nếu chúng có điểm chung. Điều kiện này có nghĩa điểm đầu của đoạn này nằm trong đoạn thứ hai, tức là a  c  b hoặc c  a  d. Do các đoạn đã được sắp tăng theo điểm đầu x nên hai đoạn xi:di và xj:dj sẽ giao nhau khi và chỉ khi xj  xi + di. Để ý rằng xi + di là điểm cuối của đoan i. Nếu hai đoạn i và j giao nhau thì ta hợp chúng thành một đoạn [a,b] với a = xi và b = max(xi + di,

xj+dj). Kết hợp các đoạn giao nhau liên tiếp đến mức tối đa ta thu được một làn gọi là làn tối đại [a,b] có

chiều dài b – a.

Ta khởi trị làn [a, b] bằng đoạn đầu tiên x1:d1, cụ thể là a := x1, b := x1+d1 (= a + d1). Với mỗi đoạn i := 2..N ta xét:

- Nếu đoạn i giao với làn [a,b], tức là xi  b thì ta hợp đoạn i với làn để tạo ra làn mới [a,b] bằng cách chỉnh b := max(b, xi + di) .

- Nếu đoạn i không giao với làn [a,b] thì ta cộng tích lũy chiều dài của làn [a,b] hiện có vào biến tổng t rồi sinh ra làn mới từ đoạn i.

a := xi ; b := a + di;

Sau khi kết thúc duyệt các đoạn ta cộng nốt làn cuối cùng vào tổng t bằng thao tác t := t + (b – a).

Độ phức tạp: O(N.logN) – chi phí cho sắp xếp Qsort.

(* Pascal *) (************************************** Xep doan ***************************************) program XepDoan; uses crt; const bl = #32; fn = 'DOAN.INP'; mn = 1001;

type KieuDoan = record x: integer; d: integer; end; md1 = array[0..mn] of KieuDoan;

var c: md1; { chua cac doan } n: integer;

f: text; procedure Doc; var i: integer; begin

assign(f,fn); reset(f); readln(f,n);

for i := 1 to n do readln(f,c[i].x,c[i].d); close(f);

end;

(*--------------------------------- Sap tang cac doan theo

diem dau x

---------------------------------*) procedure Qsort(t,p: integer): tự viết; function max(a,b: integer): tự viết function Tong: longint;

var t: longint; { tong do dai } a, b: integer; { lan [a, b] } i: integer;

begin t := 0;

a := c[1].x; b := a + c[1].d; { Khoi tri lan } for i := 2 to n do

if (c[i].x <= b) then b := max(b,c[i].x + c[i].d) else begin t := t + (b - a); a := c[i].x; b := a + c[i].d; end; Tong := t + (b - a); end; BEGIN

Doc; Qsort(1,n); writeln(Tong); END. // C# using System; using System.IO; using System.Collections; namespace SangTao2 {

class XepDoan {

const string fn = "doan.inp"; const string gn = "doan.out";

static public int n; // so luong doan static public Doan[] c; // cac doan static void Main(string[] args) { Doc(); QSort(0, n - 1);

Console.WriteLine("\n \n Dap so: "+CoverSum()); Console.WriteLine("\n Fini ");

Console.ReadLine(); }

static public void Doc(): tự viết static public int CoverSum() {

int a = c[0].x, b = a + c[0].d, t = 0; for (int i = 1; i < n; ++i)

if (c[i].x <= b) b = Max(b, c[i].x + c[i].d); else { t += (b-a); a = c[i].x; b = a+c[i].d; } return t + (b - a);

}

static public int Max(int a, int b): tự viết // Sap cac doan tang theo diem dau x

static public void QSort(int s, int e): tự viết } // XepDoan

public struct Doan: tự viết } // SangTao2

Một phần của tài liệu Sáng tạo trong thuật toán và lập trình Quyển 2 (Trang 39 - 41)

Tải bản đầy đủ (PDF)

(161 trang)