Tải bản đầy đủ (.doc) (22 trang)

Phân tích và đánh giá thuật toán ứng dụng thuật toán quy hoạch động để giải quyết bài toán thực tế

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (120.89 KB, 22 trang )

____________________________________________________

BÀI TẬP LỚP
MÔN: PHÂN TÍCH VÀ THIẾT KẾ THUẬT TOÁN

Học viên: Đỗ Đức Thọ.
Lớp

: Cao học HTTT - K25B.

Tháng 5 năm 2014


Mục lục
LỜI CẢM ƠN.....................................................................................3
1. Nội dung bài toán................................................................................................................4
Có 1 phòng để để chức các cuộc họp. Các cuộc họp được xếp vào lịch nếu khoảng thời gian
làm việc của chúng giao nhau không nhiều hơn thời điểm tiếp nối. Cho n cuộc họp, cuộc
họp thứ i bắt đầu vào thời điểm ai và kết thúc ở thời điểm bi. Hãy xếp lịch để phục vụ được
nhiều cuộc họp nhất................................................................................................................4
2. Diễn giả bài toán.................................................................................................................4
3. Hướng giải quyết bài toán...................................................................................................4
1.Thuật ngữ.............................................................................................................................5
2.Phương thức tiếp cận............................................................................................................5
3.Các bước để giải bài toán Quy Hoạch Động........................................................................5
1.Mô hình bài toán..................................................................................................................6
2.Xây dựng thuật toán QHĐ để tìm nghiệm tối ưu của bài toán............................................6
3.Đánh giá thuật toán..............................................................................................................9
a.Độ phức tạp dữ liệu..........................................................................................................9
b.Độ phức tạp tính toán.......................................................................................................9
4.Cải tiến thuật toán:...............................................................................................................9


a.Đổi thuật toán sắp xếp......................................................................................................9
b.Cải tiến thuật toán quy hoạch động tìm nghiệp tối ưu.....................................................9
5.Kết quả thức nghiệm..........................................................................................................11
a.Sử dung thuật toán ban đầu............................................................................................11
b.Sử dụng thuật toán cải tiến.............................................................................................12
1.Chương trình ban đầu.........................................................................................................13
a.Mô tả..............................................................................................................................13
b.Code...............................................................................................................................13
2. Chương trình cải tiến........................................................................................................17
a.Mô tả..............................................................................................................................17
b.Code...............................................................................................................................17


LỜI CẢM ƠN
Tôi xin trân trọng cảm ơn Học viên Kỹ thuật Quân sự đã tạo mọi điều kiện thuận lợi để
tôi học tập rèn luyện và hoàn thành môn học này.
Tôi xin bày tỏ lòng biết ơn sâu sắc đến Phó giáo sư, Tiến sĩ Đào Thanh Tĩnh, thầy đã
tận tình giúp đỡ lớp học nói chung và tôi nói riêng rất nhiều trong suốt quá trình học tập.
Tôi xin chân thành cảm ơn những người trong lớp và bạn bè trong nhóm, động viên,
giúp đỡ tôi trong suốt thời gian học tập vừa qua.
Do điều kiện về thời gian và hạn chế về kiến thức nên bài tập lớn này không tránh khỏi
nhiều thiếu sót. Vì vậy tôi mong muốn nhận được nhiều ý kiến đónh góp của thầy và bạn bè.
Tôi xin chân thành cảm ơn!


I. Tìm hiểu bài toán
1. Nội dung bài toán
Có 1 phòng để để chức các cuộc họp. Các cuộc họp được xếp vào lịch nếu khoảng thời
gian làm việc của chúng giao nhau không nhiều hơn thời điểm tiếp nối. Cho n cuộc họp, cuộc
họp thứ i bắt đầu vào thời điểm ai và kết thúc ở thời điểm bi. Hãy xếp lịch để phục vụ được

nhiều cuộc họp nhất.

2. Diễn giả bài toán.
Bài toàn bao gồm
Dữ liệu vào: S={[a1, b1],…, [an-1, bn-1], [an, bn]} trong đó :
+n:

Số lượng cuộc họp (n>0).

+ [ai, bi] : Khoảng thời gian diễn ra cuộc họp thứ i (1 ≤ i ≤ n) với:
- ai là thời điểm bắt đầu cuộc họp và
- bi là thời điểm kết thúc cuộc họp.
Dữ liệu ra:
+ Tập hợp Smax= {[ai1, bi1], [ai2, bi2], …, [aimax, bimax]} , 1<= i1,.., imax<= n
Thỏa mãn :
-

bik ≤ aik+1,với k ∈ [1..max-1] )

-

Số cuộc họp của tập Smax là lớn nhất.

3. Hướng giải quyết bài toán.
- Nhận xét: Với các bài toán như trên thì thông thường thuật toán đầu tiên mà những
người đọc vào có thể nghĩ tới là dùng thuật toán vét cạn, có nghĩa chúng ta sẽ quét tất cả các
trường hợp có thể xảy ra, với mỗi trường hợp người ta sẽ kiểm tra xem có thể bố trí chúng
trong cùng một phòng hay không và số lượng cuộc họp là bao nhiêu, tuy nhiên chi phí cho
việc làm này là không nhỏ. Để quét hết các trường hợp xảy ra người ta có thể sử dụng thuật
toán liệt kê tổ hợp Cnk với k = 1..n. và trong trường hợp xấu nhất thì chi phí chỉ cho việc đưa

ra tất cả các trường hợp đã là O(C n1+Cn2+ … +Cnn) = O(2n) còn chưa kể đến việc với mỗi
trường hợp xảy ra chúng ra lại phải vét thêm một lần nữa cho việc xét xem chúng có bố trí
được hay không, ví dụ với trường hợp ta chọn ra được một trường hợp là ba cuộc họp theo
thứ tự là 1, 4, 6 dễ thấy có thể bố trí chúng trong cùng một phòng với số lượng các cuộc họp
lớn nhất là 3 và theo thứ tự các cuộc họp là 4, 1, 6, tuy nhiên ta còn phải chi phí cho việc xét
và kiểm tra chúng thì mới có được thứ tự này mà thời gian chi cho nó cũng khá lớn.
- Giải quyết bài toán bằng Quy Hoạch Động được thực hiện bằng 2 xử lý chính.
+ Bước 1: Sắp xếp dữ liệu các cuộc họp ban đầu tăng dần theo thời gian kết thúc của
cuộc họp.


+ Bước 2: Tiến hành giải quyết bài toán bằng quy cách truy hồi dựa trên kết quả của
việc lựa chọn các cuộc họp.
+ Chi phí của bài toán sẽ bao gồm chi phí cho việc sử dụng thuật toán của bước 1 và
thuật toán của bước 2.
Để giải quyết bài toán ta cần tìm hiểu các lý thuyết về quy hoạch động như sau:

II. Thuật toán quy hoạch động
1. Thuật ngữ.
-

Trong ngành Khoa học máy tính, Quy Hoạch Động là một phương pháp giáp thời gian
chạy của các thuật toán thể hiện các tính chất của các “Bài toán con gối
nhau”(overlapping Subproblem) và “Cấu trúc con tối ưu”(optimal substructure).

-

Cấu trúc con tối ưu có nghĩa là các lời giải tối ưu cho các bài toán con có thể được sử
dụng để tìm các lời giải tối ưu cho bài toán toàn cục.


-

Đặc điểm :


Thường dùng để giải các bài toán tối ưu.



Phân rã thành bài toán con, hình thành lời giải từ bài toán con.



Lưu trữ lời giải của bài toán con trong một bảng dữ liệu thay cho giải lại các
bài toán con (đệ quy).

2. Phương thức tiếp cận.
Quy hoạch động thường dùng một trong hai cách tiếp cận:
-

Top-down (Từ trên xuống): Bài toán được chia thành các bài toán con, các bài toán
con này được giải và lời giải được ghi nhớ để phòng trường hợp cần dùng lại chúng.
Đây là đệ quy và lưu trữ được kết hợp với nhau.

-

Bottom-up (Từ dưới lên): Tất cả các bài toán con có thể cần đến đều được giải trước,
sau đó được dùng để xây dựng lời giải cho các bài toán lớn hơn. Cách tiếp cận này hơi
tốt hơn về không gian bộ nhớ dùng cho ngăn xếp và số lời gọi hàm. Tuy nhiên, đôi khi
việc xác định tất cả các bài toán con cần thiết cho việc giải quyết bài toán cho trước

không được trực giác lắm.

3. Các bước để giải bài toán Quy Hoạch Động.
-

Giải tất cả các bài toán cơ sở (thông thường rất dễ), lưu các lời giải vào bảng phương
án.

-

Dùng công thức truy hồi phối hợp những lời giải của các bài toán nhỏ đã lưu trong
bảng phương án để tìm lời giải của những bài toán lớn hơn và lưu chúng vào bảng
phương án. Cho tới khi bài toán ban đầu tìm được lời giải.

-

Dựa vào bảng phương án, truy vết tìm ra nghiệm tối ưu.


III. Ứng dụng thuật toán QHĐ để giải quyết bài toán thực tế.
1. Mô hình bài toán.
-

-

Phần dữ liệu đầu vào:


Nhập bằng tay qua màn hình (với số lượng cuộc họp ít)




Nhập bằng file (dữ liệu nhiều cuộc họp).

Phần thực hiện chương trình:


Dùng thuật toán sắp xếp để sắp xếp, để sắp xếp dữ liệu cuộc họp đầu vào tăng
dần theo thời gian kết thúc cuộc họp


-

Xây dựng thuật toán quy hoạch động để tìm ra nghiệm tối ưu của bài toán.

Phần dữ liệu đầu ra:


Hiển thị kết quả trên màn hình.



Xuất kết quả ra file.

2. Xây dựng thuật toán QHĐ để tìm nghiệm tối ưu của bài toán.
Hàm mục tiêu: f là số lượng cuộc họp.
- Gọi S là dãy các cuộc họp được bố trí thoả mãn yêu cầu đầu bài. Vì số lượng cuộc họp
trong S chỉ phụ thuộc vào dãy các cuộc họp đã cho ban đầu chính vì vậy bảng phương án
chỉ là một bảng 1 chiều.
- Ta bổ xung vào 2 đầu của dãy S hai cuộc họp thứ 0 ([-maxint, -maxint]) và cuộc họp thứ

n+1 ([maxint, maxint]) như sau:
S= {[-maxint, -maxint], [a1, b1], [a2, b2], …, [an, bn], [maxint, maxint]},
Chắc chắn dãy các cuộc họp có số lượng dài nhất sẽ bắt đầu ở cuộc họp thứ 0 và kết
thúc ở cuộc họp n+1.
- Gọi L(i) là độ dài lớn nhất của dãy các cuộc họp thoả mãn yêu cầu đầu bài bắt đầu từ
cuộc họp thứ i. L(i) sẽ được tính trong điều kiện các giá trị L(i+1)…L(n+1) đã biết.
Các bước xây dựng thuật toán QHĐ cho bài toán như sau:
Bước 1: Tìm cơ sở của phương án.
Dễ thấy nếu n = 1 hay nói cách khác là có 1 cuộc họp cần bố trí thì S = {[a 1, b1]} hay
phương án cơ sở L(1) = 1.
Bước 2: Tìm công thức truy hồi.
Tính L(i): Dãy các cuộc họp được bố trí dài nhất bắt đầu từ cuộc họp thứ i sẽ được bố
trí bằng cách ghép cuộc họp thứ i vào đầu dãy các cuộc họp dài nhất bắt đầu từ cuộc họp j


đứng sau cuộc họp i. Vậy ta chỉ ghép cuộc họp i vào đầu những dãy bắt đầu từ cuộc họp j
nào đó thoả mãn điều kiện bi ≤ aj , và dĩ nhiên ta chọn dãy dài nhất để ghép vào.
a.

L(i) được tính như sau:
1. Chọn trong số các chỉ số j từ i+1 đến n+1 mà bi ≤ aj
2. Chọn ra chỉ số jmax có L(jmax) lớn nhất.
3. Đặt L(i)= L(jmax)+1: L(i)= Max (L(j))+1 (với i
Cách xây dựng mảng L có thể diễn tả thông qua thủ tục xử lí sau:
procedure xuli;
var i,j,k,jmax:integer;
begin
for i:=n downto 0 do
begin

jmax:=n+1;
for j:=i+1 to n+1 do
if (a[j]>=b[i]) and (L[j]>L[jmax]) then jmax:=j;
L[i]:=L[jmax]+1;
<Ghi nhận lại vết đã đi qua>;
end;
end;
Bước 3: Lập bảng phương án.
Sử dụng mảng 1 chiều Trace[] để lưu lại dãy các cuộc họp theo nguyên tắc Trace[i]
sẽ cho biết cuộc họp đứng liền sau cuộc họp i trong dãy các cuộc họp dài nhất bắt đầu từ
cuộc họp i.
Bước 4: Tìm nghiệm của bài toán con thông qua nghiệm của bài toán con nhỏ hơn dựa
vào công thức truy hồi tại bước 2.
Bước 5: Xây dựng nghiệm của bài toán thông qua bảng phương án (mảng 1 chiều
Trace[]).
- Tại mỗi bước xây dựng L(i)= L(jmax)+1 với i+1 ≤ jmax ≤ n+1 thì Trace[i]= jmax để
lưu lại rằng cuộc họp Trace[i] đứng ngay sau cuộc họp i.
- Sau khi tính xong dãy L(i) và mảng Trace[] ta bắt đầu tại Trace[0] và kết thúc tại
n+1 nghĩa là dãy chỉ số các cuộc họp sẽ là:
Trace[0] → Trace[Trace[0]]… → n+1.



Quá trình truy vết có thể diễn tả thông qua thủ tục sau:
procedure truyvet;
var i,j,k:integer;
begin
i:=Trace[0];
while (i<>n+1) do
begin

<Thông báo ghi nhận lại cuộc họp i>;
i:=Trace[i];
end;
end;

3. Đánh giá thuật toán.
a. Độ phức tạp dữ liệu.
-

Dữ liệu đầu vào: 2 mảng 1 chiều a và b có cùng độ dài n nên có độ phức tạp tuyến tính
O(n).

-

Dữ liệu đầu ra: Mảng lưu trữ độ dài L và mảng truy vết Trace đều có độ dài n nên có
độ phức tạp tuyến tính O(n).

b. Độ phức tạp tính toán.
-

Thời gian sắp xếp dãy n cuộc họp theo thứ tự tăng dần theo thời gian kết thúc bằng
thuật toán sắp xếp lựa chọn. Thuật toán này đơn giản cho việc thực hiện nhưng có đố
phức tạp là O(n2).

-

Trong quá trình lập bảng phương án và tính công thức truy hồi ta đã sử dụng 2 vòng
for lồng nhau nên độ phức tạp của đoạn chương trình này là O(n2).

-


Tóm lại về tổng thể độ phức tạp dữ liệu và độ phức tạp tính để giải quyết bài toán này
là O(n2) và nó đã nhỏ hơn rất nhiều so với độ phức tạp của thuật toán vét cạn.

4. Cải tiến thuật toán:
a. Đổi thuật toán sắp xếp
-

Sử dụng thuật toán sắp xếp nhanh, với độ phức tạp là O(nlogn)

b. Cải tiến thuật toán quy hoạch động tìm nghiệp tối ưu.
-

Với mỗi số k, gọi St[k] là chỉ số x của cuộc họp x thoả mãn:




Dãy các cuộc họp dài nhất bắt đầu từ x có độ dài k. Nếu có nhiều cuộc họp
cùng thoả mãn điều kiện này thi ta chọn cuộc họp có a x là phần tử lớn nhất.
Việc tính các giá trị của St[k] được thực hiện đồng thời với việc tính các giá
trị L[?] bằng phương pháp sau:
St[1]:=n+1;
m:=1;
for i:=n downto 0 do
begin
<Tính L(i); đặt k:=L(i)>;
if (k>m) then
begin
m:=k;

St[k]:=i;
end;
else
if (a[i] > a[St[k]) then
St[k]:=i;
end;

-

Chú ý:


Khi bắt đầu vào một lần lặp với một giá trị i, ta biết được:

+ m: Độ dài dãy các cuộc họp dài nhất có chỉ số từ i+1 tới n+1 thoả mãn yêu
cầu đầu bài.
+ St[k] (1 ≤ k ≤ m): Giá trị của aSt[k] là giá trị lớn nhất trong số các giá trị a 1 cho
đến aSt[k-1] hay nói cách khác dãy các cuộc họp dài nhất bắt đầu từ cuộc họp thứ St[k]
sẽ có độ dài k. Do cách tính toán nên ta dễ thấy rằng : aSt[k] < aSt[k-1] <…-

Vậy điều kiện để có dãy các cuộc họp thoả mãn yêu cầu của đầu bài có độ dài p+1 bắt
đầu từ cuộc họp i chính là b i ≤ aSt[p] .Mặt khác nếu đem cuộc họp i ghép vào đầu dãy
các cuộc họp đã có trước đó có độ dài lớn nhất bắt đầu từ cuộc họp St[p] mà thu được
dãy phù hợp thì đem cuộc họp i ghép vào đầu dãy cuộc họp tăng dài nhất bắt đầu từ
St[p-1] cũng thu được dãy thoả mãn yêu cầu đầu bài. Vậy để tính L(i) ta có thể tìm số
p lớn nhất thoả mãn bi ≤ aSt[p] bằng thuật toán tìm kiếm nhị phân và rồi đặt L(i)= p+1.


5. Kết quả thức nghiệm

a. Sử dung thuật toán ban đầu.
-

-

-

Dữ liệu đầu vào :
Số thứ tự các cuộc họp

Thời điểm bắt đầu

Thời điểm kết thúc

1

9

13

2

8

10

3

9


15

4

4

6

5

3

5

6

4

5

7

1

2

8

5


8

9

7

8

Số thứ tự các cuộc họp

Thời điểm bắt đầu

Thời điểm kết thúc

1

1

2

2

3

5

3

4


5

4

4

6

5

5

8

6

7

8

7

8

10

8

9


13

9

9

15

Sau khi sắp xếp chọn:

Bảng kết quả chương trình:
Tính toán

i

0

1

2

3

4

5

6

7


8

9

[ai, bi]

[-M,-M]

[1,2]

[3,5]

[4,5]

[4,6]

[5,8]

L[i]

6

5

4

4

4


3

3

2

2

2

1

Trace[i]

1

2

5

5

6

7

7

10


10

10

0

[7,8] [8,10] [9,13] [9,15]

Truy vết
Kết quả là dãy các cuộc họp được bố trí như sau:
SMax= {[1, 2], [3, 5], [5, 8], [8, 10]}, độ dài Max= 4.

10
[M,M]


b. Sử dụng thuật toán cải tiến.
-

-

-

Dữ liệu đầu vào:
Số thứ tự các cuộc họp

Thời điểm bắt đầu

Thời điểm kết thúc


1

9

13

2

8

10

3

9

15

4

4

6

5

4

5


6

3

5

7

1

2

8

5

8

9

7

8

Số thứ tự các cuộc họp

Thời điểm bắt đầu

Thời điểm kết thúc


1

1

2

2

3

5

3

4

5

4

4

6

5

5

8


6

7

8

7

8

10

8

9

13

9

9

15

Sau khi sắp xếp nhanh:

Bảng kết quả chương trình:
Tính toán


I

0

1

2

3

4

5

6

7

8

9

[ai, bi]

[-M,-M]

[1,2]

[3,5]


[4,5]

[4,6]

[5,8]

L[i]

6

5

4

4

4

3

3

2

2

2

1


Trace[i]

1

4

6

6

6

9

9

10

10

10

0

St[i]

0

10


9

6

4

1

0

0

0

0

0

[7,8] [8,10] [9,13] [9,15]

Truy vết
Kết quả là dãy các cuộc họp được bố trí như sau:
SMax= {[1, 2], [4, 6], [7, 8], [9, 15]}, độ dài Max= 4.

10
[M,M]


IV.


Chương trình ( Lập trình bằng ngôn ngữ C)

1. Chương trình ban đầu
a. Mô tả.
-

Đầu vào : Nhập từ bàn phím

-

Chương trình:


Thuật toán sắp xếp chọn. Phức tạp O(N2)



Thuật toán chưa cải tiến. Phức tạp O(N2)

-

Đầu ra: Hiển thị kết quả trên màn hình

-

File Source : Source.c

b. Code.
#include <stdio.h>
#include <conio.h>

#define swap(type, a, b) {type temp = a; a = b; b = temp; } // Hàm hoàn vị
// Các hàm phụ trợ sắp xếp chọn cuộc họp
// Thuật toán sắp xếp thường sắp xếp 1 mảng, nhưng ở đây biến đổi 1 chút,
// vẫn sắp xếp 1 mảng nhưng khi đổi chỗ của thời điểm kết thúc thì cũng phải
// đỗi chỗ thời điểm bắt đầu tương ứng nên có 2 mảng đầu vào.
void SelectionSort(int batdau[],int ketthuc[],int n)
{
int i,j,min,tg;
for (i = 1; i <= n-1; i++)
{
min =i;
for (j = i+1; j <= n; j++)
{
if (ketthuc[min] > ketthuc[j])
{
min =j;
}
}


// chi doi cho khi phan tu min khong lam vi tri dau tien
if (min !=i)
{
// Đổi chỗ giá trị ketthuc cuộc họp
swap(int,ketthuc[min],ketthuc[i]);
swap(int,batdau[min],batdau[i]);
}
}
}


// Phần chương trình
int main(int argc, char* argv[])
{
// khai bao bien
int n; // Số n, số cuộc họp
int batdau[1001]; // Mảng lưu thời gian bắt đầu của các cuộc họp
int ketthuc[1001]; // Mảng lưu thời gian kết thúc của các cuộc họp
int L[1001];// Lưu lại số lượng cuộc họp được bố trí vi trí thứ i, i=1,n
int VT[1001]; // Lưu lại vị trí mà L[i] đạt max
int jmax;
int i;// Chỉ số duyệt dùng để duyệt mảng
int j;// Chỉ số duyệt dùng để duyệt mảng
/*------------------ Phần nhập dữ liệu đầu vào ------------------------*/
// Nhập số lượng cuộc họp, nếu số cuộc < 1 và lớn hơn 1000 thì nhập lại
do
{
printf("Nhap so cuoc hop:= ");
scanf("%d",&n);
}
while (n<1|| n>1000);


// Nhập thời gian bắt đầu và thời gian kết thúc của n cuộc họp
for (i=1;i<=n;i++)
{
// Cuộc họp phải có thời gian kết thúc lớn hơn bắt đầu
// bắt đầu phải lớn hơn 1
// Nếu thời gian không thỏa mãn thì bắt buộc phải nhập lại
do
{

printf("Thoi gian bat dau cuoc hop %d:=", i );
scanf("%d", &batdau[i]);
printf("Thoi gian ket thuc cuoc hop %d:=", i );
scanf("%d", &ketthuc[i]);
}
while (batdau[i] >= ketthuc[i]|| batdau[i] <1);
}

/*--------------- Phần thuật toán xử lý chương trình-------------------*/
// Sử dụng hàm phụ trợ sắp xếp chọn
SelectionSort(batdau,ketthuc,n);
// Khởi tạo
// Min của kiểu số nguyên trong C là -32767, nhưng ở đây có thể dụng = 0
// vì lúc nhập ta đã yêu cầu thời gian bắt đầu phải >=1
batdau[0] = 0;
ketthuc[0] =0;
batdau[n+1] = 32767; // max của kiểu số int trong C
ketthuc[n+1] = 32767;
L[n+1] = 1;


// phần chương trình chính
for(i=n;i>=0;i--)
{
jmax = n+1;
for (j=i+1;j<=n+1;j++)
{
// chỉ thay đổi Jmax khi tìm được cuộc họp i thỏa mãn ĐK dưới.
if (ketthuc[i] <= batdau[j] && L[j] > L[jmax])
{

jmax =j;
}
}
L[i] = L[jmax]+1;
// lưu lại vị trí jmax bằng mảng vị trí
VT[i] = jmax;
}
/*--------------- Phần hiển thị kế quả ra màn hình----------------*/
// Hiển thị số cuộc họp
printf("Do dai Max :=%4d",L[0]-2);
// Hiển thị các cuộc họp được chọn
printf("\nDanh sach cuoc hop can tim la:=");
i = VT[0];
printf("{");
while (i!=n+1)
{
printf(" [%d,%d] ",batdau[i],ketthuc[i]);
i=VT[i];
}
printf("}");
getch();
}


2. Chương trình cải tiến.
a. Mô tả.
-

Đầu vào : File Input.txt ( hoặc Input1.txt kết quả thực nghiệm)


-

Chương trình:

-

-



Thuật toán sắp xếp nhanh. Phức tạp O(NlogN)



Thuật toán cải tiến. Phức tạp O(NlogN)

Đầu ra:


File Output.txt



Hiển thị màn hình

File Source : Source2.c

b. Code
#include <stdio.h>
#include <conio.h>

#define swap(type, a, b) {type temp = a; a = b; b = temp; } // hàm hoan vi
// Hàm phụ trợ sắp xếp nhanh.
void quickSort(int *a,int *b, int l, int r)
{
int key = b[(l+r)/2];
int i = l, j = r;
while(i <= j)
{
while(b[i] < key) i++;
while(b[j] > key) j--;

// tim phan tu ben trai ma >=key
// tim phan tu ben trai ma <=key

if(i <= j)
{
if (i < j)
{
swap(int, b[i], b[j]);
swap(int, a[i], a[j]);
}
i++;
j--;
}
}


//bay gio ta co 1 mang : a[l]....a[j]..a[i]...a[r]
if (l < j) quickSort(a,b, l, j); // lam lai voi mang a[l]....a[j]
if (i < r) quickSort(a,b, i, r); // lam lai voi mang a[i]....a[r]

}
// tính vị trí max
int Tinh(int pChiSo,int pRight,int *mang,int *pStart,int *pEnd)
{
int left,right,mid,j;
left=1;
right = pRight+1;
do
{
mid = (left+right)/2;
j = mang[mid];
if (pStart[j]>= pEnd[pChiSo])
left = mid;
else
right = mid;
}while (right != left+1);
return mang[left];
}
// Phần chương trình
int main(int argc, char* argv[])
{
// khai bao bien
FILE *fInp;
FILE *fOutp;
int n; // Số n, số cuộc họp
int batdau[1001]; // Mảng lưu thời gian bắt đầu của các cuộc họp
int ketthuc[1001]; // Mảng lưu thời gian kết thúc của các cuộc họp
int L[1001];// Lưu lại số lượng cuộc họp bố trí tại cuôc họp thứ i, i=1,n



int VT[1001]; // Lưu lại vị trí mà L[i] đạt max
int ST[1001];
int m;
int i;// Chỉ số duyệt dùng để duyệt mảng
int j;
int k;
/*-------------------- Phần nhập dữ liệu đầu vào -----------------------*/
// Nhập số lượng cuộc họp tu file
n=0;
// fInp = fopen ("Input1.txt", "r");
fInp = fopen ("Input.txt", "r");
while (!feof(fInp)) {
n++;
fscanf(fInp, "%d %d", &batdau[n], &ketthuc[n]);
}
fclose(fInp);
/*---------- Phần thuật toán xử lý chương trình--------------------*/
// Sử dụng hàm phụ trợ xắp xếp nhanh
quickSort(batdau,ketthuc,1,n);
// Khởi tạo
batdau[0] = 0;
ketthuc[0] =0;
batdau[n+1] = 32767; // max của kiểu số nguyên trong C
ketthuc[n+1] = 32767;
// Chương trình
for (i=0;i<=n+1;i++)
{
L[i]=1;
ST[i]=0;
}

m=1;
ST[1] = n+1;


for(i=n;i>=0;i--)
{
j = Tinh(i,m,ST,batdau,ketthuc);
k=L[j]+1;
if(k>m)
{
m=k;
ST[k] =i;
}
else
{
if(batdau[ST[k]]{
ST[k]= i;
}
}
L[i]=k;
// lưu lại vị trí jmax
VT[i] = j;
}
/*------------------- Phần hiển thị kết quả -------------------*/
// Hiển thị số cuộc họp
printf("Du lieu ket qua duoc ghi ra file, Hay mo file OutPut.txt de xem ket qua");
fOutp = fopen("OutPut.txt","w");
fprintf(fOutp,"Do dai Max :=%4d",L[0]-2);
// Luu ket qua ra file

printf("Du lieu ket qua duoc ghi ra file, Hay mo file OutPut.txt de xem ket qua");
fOutp = fopen("OutPut.txt","w");
fprintf(fOutp,"Do dai Max :=%4d",L[0]-2);
fprintf(fOutp,"\nDanh sach cuoc hop can tim la:={");
i = VT[0];
while (i!=n+1)
{
fprintf(fOutp," [%d,%d] ",batdau[i],ketthuc[i]);
i=VT[i];
}


fprintf(fOutp,"}");
fclose(fOutp);
// hien thi ket qua ra man hinh
printf("\nDo dai Max :=%4d",L[0]-2);
printf("\nDanh sach cuoc hop can tim la:=");
i = VT[0];
printf("{");
while (i!=n+1)
{
printf(" [%d,%d] ",batdau[i],ketthuc[i]);
i=VT[i];
}
printf("}");
getch();
}


Tài liệu tham khảo

[1]. Quy hoạch động – wiki.
[2]. Dynamic Programing – Phân tích và đánh giá thuật toán – Đào Thanh
Tĩnh – HV Kỹ Thuật Quân sự.
[3]. Cấu trúc dữ liệu và thuật giải – Tạ Thúc Nhu – Đại học Lạc Hồng.
[4]. Lý thuyết quy hoạch động và áp dụng – Nguyễn Khắc Nho.
[5]. Giáo trình lập trình C – Đại học FPT.



×