1. Trang chủ
  2. » Luận Văn - Báo Cáo

CHUYÊN đề cấu TRÚC dữ LIỆU HEAP

35 1,7K 4

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 35
Dung lượng 5,51 MB

Nội dung

Thực ra, bí mật sự thành công của Ivan là ở chổ không phải chính anh nghĩ ra các tình huống mà là người em trai Alexei.. Hai anh em phân tích bảng chu kỳ sinh học của Alexei và thấy rằng

Trang 1

MỤC LỤC

MỤC LỤC 1

Khái niệm 2

Các thao tác thường dùng đối với Heap Max 2

Khai báo 2

UpHeap 2

DownHeap 3

Push 4

Pop 4

Dijkstra Heap 5

Một số bài tập ứng dụng 6

1.Bài tập 1: Heapuri 6

2.Bài tập 2: Thả xốp 8

3.Bài tập 3:PILOT 10

Bài tập4:Tiểu thuyết trinh thám 13

Bài tập 5: Cezar 18

Bài tập 6:Toy Cars 22

Bài tập 7:BASE3 26

Một số bài tập vận dụng 30

Bài tập 1: BOCSOI13 30

Bài tập 2: Kế hoạch làm bài 31

Bài tập 3: CATUN 31

Bài tập 3: Barbar 32

Bài tập 4:Cầu cảng 33

4.Bài tập 5:K TỔNG BÉ NHẤT 33

Bài tập 6: BINLADEN 34

Tài liệu tham khảo 35

Trang 2

CHUYÊN ĐỀ: CẤU TRÚC DỮ LIỆU HEAP Khái niệm

Heap là một trong những cấu trúc dữ liệu đặc biệt quan trọng, nó giúp ta có thể giải được nhiều bài toán trong thời gian cho phép Độ phức tạp thông thường khi làm việc với

Heap là O(logN).

Heap thực chất là một cây cân bằng thỏa mãn các điều kiện sau:

• Một nút có không quá 2 nút con

• Với Heap Max thì nút gốc là nút lớn nhất, mọi nút con đều không lớn hơn nút cha của nó Với Heap Min thì ngược lại

Mặc dù được mô tả như cây nhưng Heap có thể được biểu diễn bằng mảng Nút con của nút i là 2*i và 2*i+1 Do Heap là cây cân bằng nên độ cao của 1 nút luôn <= logN.Ứng dụng chủ yếu của Heap là tìm Min, Max trong 1 tập hợp động (có thể thay đổi, thêm, bớt các phần tử) nhưng như vậy đã là quá đủ

(Mô hình biểu diễn Heap bằng cây nhị phân và bằng mảng)

Các thao tác thường dùng đối với Heap Max

Trang 3

Procedure UpHeap(i : LongInt);

Begin

if (i = 1) or (Heap[i] < Heap[i div 2]) then exit; // Nếu i là nút gốc hoặc

nhỏ hơn nút cha thì không làm việc

swap(Heap[i] , Heap[i div 2]); // Đổi chỗ 2 phần tử trong Heap;

UpHeap(i div 2); // Tiếp tục di chuyển lên trên

end;

DownHeap

Nếu 1 nút nhỏ hơn nút con thì đẩy nó xuống dưới:

Trang 4

Procedure DownHeap(i : LongInt);

Var

j : LongInt;

Begin

j := i*2;

if j > nHeap then exit; // Nếu i không có nút con thì không làm việc

if (j < nHeap) and (Heap[j] < Heap[j+1]) then Inc(j); // Nếu i có 2 nút con thì

chọn nút ưu tiên hơn

if Heap[i] < Heap[j] then // Nếu nút cha nhỏ hơn nút con

Inc(nHeap); // Tăng số phần tử của Heap

Heap[nHeap] := x; // Thêm x vào Heap

Pop := Heap[v]; // Lấy phần tử ở vị trí v ra khỏi Heap

Heap[v] := Heap[nHeap]; // Đưa phần tử ở cuối Heap vào vị trí v

Dec(nHeap); // Giảm số phần tử của Heap đi 1

Trang 5

{Chỉnh lại Heap}

UpHeap(v);

DownHeap(v);

End;

Ngoài ra, khi sử dụng thuật toán Dijkstra/Prim kết hợp cấu trúc Heap, bạn còn

có thể sử dụng cách Push và Pop khác thuận lợi hơn so với cách trình bày ở trên:

child := pos[v]; // child là vị trí của đỉnh v trong Heap

if child = 0 then // Nếu đỉnh v chưa có trong Heap

begin

Inc(nHeap); // Tăng số phần tử của Heap

child := nHeap; // Đưa v vào cuối Heap

end;

parent := child div 2; // parent là nút cha của child

while (parent > 0) and (d[Heap[parent]] > d[v]) do // Nếu đỉnh ở nút parent

kém ưu tiên hơn v thì bị “kéo xuống” nút child

begin

Heap[child] := Heap[parent]; // Đẩy đỉnh được lưu trong nút cha xuống nút con pos[Heap[child]] := child; // Ghi nhận lại vị trí mới của đỉnh đó

child := parent; // Tiếp tục di chuyển lên

parent := child div 2;

v := Heap[nHeap]; // v là đỉnh ở nút lá cuối Heap, sẽ được đảo lên đầu và vun đống

Dec(nHeap); // Giảm số phần tử của Heap

r := 1; // Bắt đầu từ nút gốc

while r*2 <= nHeap do // Chừng nào r chưa phải là lá

begin

c := r*2; // c là nút con của r

if (c <nHeap) and (d[Heap[c]] > d[Heap[c+1]]) then Inc(c); // Trong

2 nút con chọn nút con chứa đỉnh ưu tiên hơn

if d[Heap[c]] >= d[v] then break; // Nếu v ưu tiên hơn thì không làm việc nữa Heap[r] := Heap[c]; // Chuyển đỉnh lưu ở nút con lên nút cha

pos[Heap[r]] := r; // Cập nhật lại vị trí mới trong Heap của đỉnh đó

r := c; // Tiếp tục di chuyển xuống dưới

Trang 6

end;

Heap[r] := v; // Đỉnh v được đặt vào vị trí r để đảm bảo cấu trúc Heap

pos[v] := r; // Ghi nhận vị trí mới của đỉnh v trong Heap

- Thao tác 1 : Cho phần tử x vào danh sách

- Thao tác 2 : Xóa phần tử thứ t (theo thứ tự nhập vào)

- Thao tác 3: Lấy ra phần tử nhỏ nhất trong danh sách

Yêu cầu: Hãy cho biết các kết quả của thao tác 3 ?

Dễ thấy đây là một danh sách động (số lượng phần tử thay đổi), vì vậy ta xây dựng một heapmin để lấy ra giá trị nhỏ nhất ở các thao tác 3 Để xóa phần tử thứ t theo thứ tự nhập vào thì ta lưu thêm một mảng Pos

Trang 7

if (y*2<=L && A[Heap[x]]>A[Heap[y*2]]) x = y*2;

if (y*2+1<=L && A[Heap[x]]>A[Heap[y*2+1]]) x = y*2+1;

Trang 10

If (heap[j] >heap[j+1]) and (j <nheap) then inc(j);

If heap[i] > heap[j] then

Trang 11

HT airline có tất cả N phi công (N là số chẵn), các phi công được đánh số từ 1 đến N (Phi công 1 là phi công trẻ nhất, phi công i là phi công có tuổi cao thứ i,… phi công n là phi công cao tuổi nhất) HT airline cần chính xác

2

N

phi hành đoàn, mỗi phi hành đoàn

gồm 2 phi công (một lái chính và một lái phụ), lái chính phải nhiều tuổi hơn lái phụ

Hợp đồng mà công ty kí với các phi công có 2 điều khoản rõ ràng: tiền lương khi là lái chính và tiền lương khi là lái phụ Rõ ràng, đối với 1 phi công, tiền lương lái chính bao giờ cũng cao hơn tiền lương khi lái phụ Tuy nhiên, với một phi hành đoàn, có thể tiền lương của lái chính lại thấp hơn lái phụ

Để giảm chi phí trả tiền lương, HT phải xác định một cách phân chia tối ưu

2

N

phi hành đoàn

Bạn hãy giúp HT viết chương trình xác định số tiền tối thiểu để trả lương cho N phi công

Time limits / test: 1s

Ta có nhận xét sau: Theo thứ tự i nhập vào từ 1 đến N, thì cứ i lẻ thì phải có 1 lái phụ Vì vậy, ta xây dựng một heap max, lần lượt cho vào heap, khi i lẻ thì ta lấy trong heap ra một nút, đây chính là lái phụ

Trang 12

Arr1 = array[1 max] of longint;

begin

if (i = 1) or (h[i] < h[i div 2]) then exit;

if h[i div 2] < h[i] then

Trang 13

Bài tập4:Tiểu thuyết trinh thám

Ivan Đneprôp viết truyện tiểu thuyết trinh thám Truyện của anh ta không có gì đặc sắc: không có các tình huống ly kỳ đặc biệt, cũng không có các chi tiết hài hước tế nhị Thậm chí một hiệu sách đã bán các sáng tác của Ivan theo cân! Nhưng độc giả lại thích truyện của Ivan Nó dễ hiểu và giúp người ta thư giản sau một ngày lao động mệt nhọc

Trang 14

Thực ra, bí mật sự thành công của Ivan là ở chổ không phải chính anh nghĩ ra các tình huống mà là người em trai Alexei Ivan có nhiệm vụ viết nó thành các bestsellers Dĩ nhiên hai anh em chia nhau hợp lý số tiền kiếm được Điều đáng tiếc là khả năng sáng tạo các tình huống ly kỳ của Alexei lại phụ thuộc vào chu kỳ sinh học của anh Hai anh em phân tích bảng chu kỳ sinh học của Alexei và thấy rằng trong thời gian tới Alexei sẽ nghĩ

được n chủ đề mới, chủ đề thứ i sẽ được nghĩ ra ở ngày r i Trong cùng một ngày có thể Alexei nghĩ ra tới vài câu chuyện

Với mỗi chủ đề, Ivan thời lượng cần thiết để hoàn thành tác phẩm và tính được rằng

chủ đề thứ i cần có p i ngày để viết Ivan có trí nhớ cực tốt, vì vậy anh có thể tạm bỏ dở một truyện, chuyển sang viết truyện khác sau đó quay lại hoàn thành nốt các truyện dở dang

Dĩ nhiên, hai anh em muốn sách được viết càng nhanh càng tốt, tức là phải cực tiểu hóa thời gian trung bình từ thời điểm hiện tại tới thời điểm lúc tiểu thuyết hoàn thành Vì

số sách là cố định, nên điều này tương đương với việc cực tiểu hóa tổng thời gian viết tất

cả các cuốn sách Điều này có nghĩa là nếu cuốn sách thứ i được hoàn thành vào ngày c i

thì ∑c i phải được cực tiểu hóa Ví dụ, ở ngày thứ nhất Alexei nghĩ ra một cốt chuyện mà Ivan cần viết trong 5 ngày, Ivan bắt tay viết ngay Ngày thứ 2 Alexei nghĩ thêm một cót chuyện mới cần viết trong một ngày Ivan chuyển sang viết chuyện mới, ngày thứ 3: chuện thứ hai hoàn thành và Ivan quay lại viết tiếp chuyện thứ nhất, mất thêm 4 ngày nữa, đến ngày thứ 7 chuyện thứ nhất hoàn thành Tổng các thời điểm hoàn thành là 3+7 = 10

1 Sort tăng theo R[i]

2 Ví dụ với các thời điểm , dễ dàng ta thấy

3 Với mỗi khoảng thời gian t = R[i] – R[i-1], ta ưu tiên giải quyết công việc cần ít thời gian nhất, giả sử là công việc P (Thấy ngay là sử dụng Heap để lấy công việc

có thời gian nhỏ nhất)

a Nếu thời gian thực hiện công việc P < t thì thực hiện hết công việc P, thời gian còn lại thực hiện tiếp các công việc có thời gian nhỏ tiếp theo

Trang 15

b Nếu thời gian thực hiện công việc P > t thì chúng ta thực hiện công việc P trong khoảng thời gian t, thời gian còn lại là t[P] – t ta lưu lại trong Heap để tính tiếp.

4 Sau khi xét đến thời điểm N, lúc này ta sẽ phải làm tất cả các công việc còn lại tuần

tự từ nhỏ đến lớn, hay là lấy tất cả các phần tử trong Heap ra là xong

if (i = 1) or (h[i] > h[i div 2]) then exit;

if h[i div 2] > h[i] then

Trang 17

push(p[i]);sum := r[i];

end;

whilenh> 0 do

begin

x := pop;

sum := sum + x;

res := res + sum;

end;

end;

{* -*}

procedure sort(x,y:longint); var i,j,key1,key2 : longint; begin i := x; j := y; key1 := r[x+random(y-x+1)]; key2 := p[x+random(y-x+1)]; repeat while (r[i] < key1) or ((r[i] = key1) and (p[i] < key2)) do inc(i); while (r[j] > key1) or ((r[j] = key1) and (p[j] > key2)) dodec(j); if i <= j then begin doicho(r[i],r[j]); doicho(p[i],p[j]); inc(i); dec(j); end; until i > j ; if x < j then sort(x,j); if y > i then sort(i,y); end; {* -*}

{* -*}

procedureinkq; begin assign(fo,tfo);rewrite(fo); write(fo,res); close(fo); end; {* -*}

{* -*}

{* -*}

{* -*} BEGIN

randomize;

nhap;

Trang 18

Mỗi thượng nghị sĩ khi đi từ nhà mình đến thượng viện, phải trả 1 USD khi đi qua một con phố (phố = đường nối trực tiếp 2 nhà bất kỳ) HT – người đứng đầu thượng viện -

đã nghĩ cách làm sao cho số tiền mà các thượng nghĩ sĩ phải trả là tối thiểu Vì vậy, HT quyết định

• Có k con phố miễn phí (thượng nghị sĩ sẽ không phải trả tiền khi đi trên con phố này)

• Đặt tòa nhà thượng viện ở một trong n ngôi nhà

Bạn hãy viết chương trình tính xem chi phí tối thiểu là bao nhiêu?

5-7, 7-8, 8-10

đường miễn phí

8 là thượng

việnChi phí tối thiểu là:

9 10

13

Trang 19

Time limit:0.5 s/test

Thuật toán:

1 Chúng ta sẽ tìm con đường phải trả phí đi lại

2 Khởi tạo D[i] = trọng số của đỉnh i với ý nghĩa = số lượng người đi đến thượng viện phải đi qua con đường này Ban đầu

3 Tại mỗi bước chúng ta sẽ cho các nút lá vào Heap, mỗi lần lấy 1 phần tử trong heap chúng ta sẽ update lại trọng số của đỉnh kề với đỉnh vừa lấy ra và nếu đỉnh vừa update thành nút lá ta lại cho vào trong heap Sau khi lấy xong đỉnh thì cập nhật đáp án

Trang 21

Repeat

root := child div 2;

If (root=0) or (cost[heap[root]] <= cost[u]) then break; heap[child] := heap[root];

cost[ke[i]] := cost[ke[i]] + cost[v];

If deg[ke[i]] = 1 then push(ke[i]);

Trang 22

Bài tập 6:Toy Cars

Bé Tom là một đứa trẻ ba tuổi và rất thích chơi đồ chơi oto Bé Tom có n chiếc oto khác nhau, chúng được đặt trên một chiếu giá cao mà Tom không thể tự mình lấy được

Phòng của Tom cũng rất nhỏ, tại một thời điểm, không thể có nhiều hơn k chiếc oto đồ

chơi ở trên sàn nhà.

Tom chơi với một trong nhưng chiếc oto trên sàn nhà, Mẹ của Ton luôn ở trong phòng với Tom trong cả thời gian chơi của Tom Khi Bé Tom muốn chơi với một chiếc oto khác, nếu chiếc này ở trên sàn nhà, Tom sẽ tự lấy để chơi, còn nếu chiếc oto này ở trên giá, Mẹ của Tom sẽ lấy xuống cho Tom (Khi Mẹ của Tom lấy 1 chiếc oto cho Tom,cùng lúc cô ấy có thể lấy một chiếc oto bất kỳ khác ở sàn nhà để đặt lên giá – để có đủ khoảng không gian cho k chiếc oto)

Trang 23

Mẹ của Tom là người mẹ rất hiểu ý thích của con mình, cô ta có thể biết được những chiếc oto nào mà con trai mình muốn chơi Cô ta muốn biết số lần ít nhất mà cô ta giúp Tom lấy xe oto từ trên giá.

INPUT: TOYCARS.INP

- Dòng 1: 3 số nguyên dương N, K, P

lần lượt là số lượng oto mà Tom có, số lượng oto có thể đặt trên sàn tại cùng một thời điểm và độ dài dãy các oto mà Tom muốn chơi Các oto được đánh số từ 1 đến N.

- P dòng tiếp theo, mỗi dòng 1 số nguyên dương là chiếc oto mà Tom muốn chơi

(theo thứ tự thời gian)

2 Xét lần lượt các thời điểm i :

a Nếu món P[i] đang nằm trên sàn : bỏ qua và xét thời điểm tiếp theo

b Nếu mon P[i] đang nằm trên giá :

i Nếu sàn chưa đầy : Ta lấy món P[i] để lên sàn

ii Nếu sàn đầy : Ta chọn từ sàn một món đồ chơi có độ tồi lớn nhất và đặt lên giá, sau đó lấy món P[i] để lên sàn

3 Dễ dàng nhận thấy có thể sử dụng cấu trúc Heap để thực hiện thuật giải trong thời gian N.logK

const

tfi = 'toycars.inp';

tfo = 'toycars.out';

type

arr1 = array[0 1000000] of longint;

arr2 = array[0 100000] of boolean;

var

Trang 24

var j:longint;

Trang 25

j:=i*2;

if j>nheap then exit;

if (d[a[j]]<d[a[j+1]])and(j<nheap) then inc(j);

Trang 26

{ -} procedureinkq;

Cho 3 số ở hệ cơ số 3 (viết bởi 3 số 0, 1, 2) Hãy tìm một chữ số N ở hệ cơ số 3 sao cho N

có một số lẻ chữ số và số 1 nằm ở chính giữa số N Số N phải thu được từ việc liên kết 3

số cho trước, mỗi số trong 3 số có thể được sử dụng 0 hoặc nhiều lần:

13

Giải thích

N = 2020001001001

Time limit/test: 0.4

Ký tự 1 ở giữa của xâu kết quả phải thuộc 1 trong 3 xâu:

Giả sử ký tự 1 của kết quả nằm ở vị trí I của xâu , ta sẽ xây dựng xâu kết quả bằng cách thêm từng xâu vào trái hoặc phải (phần L là trái, ký tự 1 ở giữa, phần R là phải)

Ta sẽ xây dựng xâu đến khi thì dừng lại (yêu cầu đề bài)

L

Trang 27

Dễ thấy, ta chỉ quan tâm tới ghi nhận kết quả Tức là nếu tồn tại cách xây dựng L’, R’ mà

thỏa mãn cũng sử dụng cách xây dựng đó được với các cặp với , chỉ cần lưu 1 cặp có

Quy hoạch động = cách xếp có với

Nếu mỗi lần ta luôn nắp xâu vào nửa ngắn hơn thì luôn đảm bảo

(do ) Với trạng thái , ta cập nhật cho trạng thái + độ dài xâu nắp thêm vào Bài toán trở thành Dijkstra Heap

về trạng thái Các trạng thái cơ sở có thể là các ký tự 1 của 1 trong 3 xâu ban đầu Đáp án bài toán là

Trang 28

h[i] := h[i div 2] ;

h2[i] := h2[i div 2];

if d[x,y] <= d[h[j],h2[j]] then break ;

Trang 30

Ví dụ: Nếu chúng ta có 4 đống sỏi với số lượng sỏi là 10, 11, 12 và 13

- Bước 1: Ghép 2 đống 10 và 11 thành 1 đống có số lượng 21 (chi phí là 1.05)

- Bước 2: Ghép đống 21 vừa thu được với đống 12 thành đống có số lượng 33 (chi phí 1.65)

- Bước 3: Ghép đống 33 vừa thu được với đống 13 thành 1 đống cuối cùng có số lượng sỏi là 46 (chi phí 2.3)

- Vậy tổng chi phí là 5.00 Tuy nhiên đây không phải là phương án ghép đống tối ưu, chúng ta có phương án ghép 4 đống này thành 1 đống với chi phí nhỏ nhất là 4.60.Các bạn hãy tìm giúp Bé Bi phương án chơi tối ưu nhé!

INPUT:BOCSOI13.INP:

- Dòng 1: Số nguyên dương N là số đống sỏi

- Dòng tiếp theo, ghi N số nguyên dương, tương ứng là số lượng sỏi trong từng đống

Số lượng sỏi không vượt quá 10.000

OUTPUT:BOCSOI13.OUT:

- Ghi 1 số thực duy nhất là chi phí nhỏ nhất phải trả để ghép N đống sỏi thành 1 đống Kết quả ghi dưới dạng 2 chữ số sau dấu thập phân

Trang 31

Bài tập 2: Kế hoạch làm bài

Nobita được giao n bài tập về nhà đánh số từ 1 tới n Mỗi bài tập cần đúng 1 đơn vị thời gian để làm và tại mỗi thời điểm, Nobita chỉ có thể làm được 1 bài tập Bài tập thứ I cần hoàn thành không muộn hơn thời điểm ti và nếu bài thứ I bị nộp muộn thì Nobita sẽ bị thày giáo cho pi điểm 0

Giả sử Nobita định làm bài tập từ thời điểm a đến hết thời điểm b Hãy giúp Nobita lên

kế hoạch làm bài tập để số điểm 0 phải nhận là ít nhất

INPUT: PENALTY.INP

- Dòng 1: Chứa 3 số nguyên dương n ;

- N dòng tiếp theo, dòng thứ I chứa hai số nguyên dương ti, pi

25 Làm bài 1 từ thời điểm 1 đến thời điểm 2

Làm bài 4 từ thời điểm 2 đến thời điểm 3

Làm bài 5 từ thời điểm 3 đến thời điểm 4

Bài 2 và bài 3 bị nộp muộn

Bài tập 3: CATUN

Tại vương quốc HT có N thị trấn đánh số từ 1 đến N và M con đường nối 2 thị trấn bất

kỳ Trong số N thị trấn thì có K thị trấn là pháo đài chống giặc ngoại xâm Khi có giặc ngoại xâm, 1 pháo đài bất kỳ sẽ bảo vệ những thị trấn gần nó nhất Nếu co 1 thị trấn nào

đó có khoảng cách tới 2 pháo đài bằng nhau thì thị trấn này được bảo vệ bởi pháo đài có chỉ số nhỏ hơn?

INPUT: CATUN.IN

- Dòng 1: N, M và K (

- Dòng 2: K số nguyên dương là chỉ số của K pháo đài

- M dòng tiếp theo, mỗi dòng ghi 3 số x, y, z có nghĩa là có con đường 2 chiều nối thị trấn x với thị trấn y có chiều dài là z

OUTPUT: CATUN.OUT

Ngày đăng: 14/10/2015, 14:02

TỪ KHÓA LIÊN QUAN

w