You are on page 1of 56

PreVOI2022 Training

Bình Định

presented by Đỗ Phan Thuận


dophanthuan@gmail.com

Khoa Học Máy Tính


Đại học Bách Khoa Hà Nội

Ngày 15 tháng 10 năm 2022


Bài A. SQUARE

Bài B. THREEJUG

Bài C. WATCHING

Bài D. FARM

Bài G. TAXI

Bài H. BCA

Bài I. Binarylist

Bài K. HIST

Bài L. POSTMAN
Bài A. SQUARE

Bài B. THREEJUG

Bài C. WATCHING

Bài D. FARM

Bài G. TAXI

Bài H. BCA

Bài I. Binarylist

Bài K. HIST

Bài L. POSTMAN
SQUARE

Xét dãy số sau:


0, 0 + 1, 0 + 1 + 3, 0 + 1 + 3 + 5, . . . , 0 + 1 + 3 + . . . + (2n − 1), . . ..
Đây là dãy được tạo bởi tổng vài số tự nhiên lẻ đầu tiên và các số
hạng của dãy đều là số chính phương (tức là bình phương của một
số nguyên): 0, 1, 4, 9, . . . , n2 , . . ..
Tổng quát hóa dãy này bằng cách thay số 0 ở đầu bởi một số
nguyên k, như vậy ta được dãy:
k, k + 1, k + 1 + 3, k + 1 + 3 + 5, . . . , k + 1 + 3 + . . . + (2n − 1), . . ..
Tuy nhiên khác với trường hợp k = 0 ở trên, dãy này chỉ có một
vài số hạng là số chính phương.
Yêu cầu: Cho trước số nguyên k, cần tìm số nguyên không âm
nhỏ nhất sao cho bình phương của nó xuất hiện trong dãy số trên.
Thuật toán

Bài toán đưa về tìm x dương nhỏ nhất mà k = (x + y)(x - y)


Bài A. SQUARE

Bài B. THREEJUG

Bài C. WATCHING

Bài D. FARM

Bài G. TAXI

Bài H. BCA

Bài I. Binarylist

Bài K. HIST

Bài L. POSTMAN
THREEJUG

Có 3 bình dung tích A, B, C (lít) với lượng nước ban đầu tương
ứng là a, b, c (lít). Mỗi bước được phép đổ đúng d lít từ một bình
i sang một bình j khác với điều kiện lượng nước hiện có trong bình
i lớn hơn hoặc bằng d và sau khi đổ hết d lít từ bình i sang bình j
thì nước trong bình j không bị tràn ra ngoài. Hãy tìm dãy ít nhất
các bước đổ nước sao cho lượng nước còn lại ở 1 trong 3 bình
đúng bằng T .
Thuật toán 60 điểm

Đúng với A, B, C ≤ 1000.


Sử dụng phương pháp tìm kiếm theo chiều rộng BFS loang các
trạng thái đổ có thể từ 3 bình. Do A, B, C đủ nhỏ nên có thể lưu
hết được các trạng thái trong hàng đợi.
Thuật toán 100 điểm

0 ≤ A, B, C , a, b, c, d, T ≤ 105 .
Bài toán đưa về giải 3 phương trình riêng biệt và đưa ra nghiệm
nhỏ nhất trong 3 phương trình đó:
a + dx = T
b + dy = T
c + dz = T
Với mỗi phương trình, sử dụng phương pháp tham lam để thử đổ
xem có thoả mãn điều kiện đề bài không.
Bài A. SQUARE

Bài B. THREEJUG

Bài C. WATCHING

Bài D. FARM

Bài G. TAXI

Bài H. BCA

Bài I. Binarylist

Bài K. HIST

Bài L. POSTMAN
WATCHING

Vào thời điểm 0, Bờm sẽ bật TV và bắt đầu xem loạt phim
"Avengers" trên kênh A. Nếu bất cứ lúc nào trên kênh truyền hình
mà Bờm đang xem có quảng cáo bắt đầu, thì Bờm sẽ chuyển sang
kênh kia và xem kênh đó. Nếu Bờm chuyển kênh và cũng có một
quảng cáo đang diễn ra vào lúc này, thì anh ấy sẽ không chuyển
kênh với hy vọng rằng quảng cáo sẽ sớm kết thúc trên kênh này.
Vào thời điểm t, Bờm sẽ tắt TV và đi ngủ.
Cho biết lịch chiếu quảng cáo cụ thể và thời lượng của các quảng
cáo trên hai kênh, hãy xác định xem Bờm sẽ xem mỗi bộ phim bao
nhiêu đơn vị thời gian.
Thuật toán 40 điểm

Đúng với n ≤ 1000, k, t, ai , bj ≤ 106 .


Sử dụng 2 vòng lặp mỗi vòng trên một kênh và kiểm tra điều kiện
chuyển kênh để tính vào tổng thời gian xem mỗi kênh.
Độ phức tạp O(n2 ).
Thuật toán 100 điểm

n, m, t và k (1 ≤ n, m ≤ 105 , 1 ≤ t ≤ 1018 , 1 ≤ k ≤ 109 )


1. Sử dụng hai con trỏ chạy tịnh tiến từ trái sang phải trên hai
mảng lưu lịch chiếu của hai bộ phim. Độ phức tạp O(n).
2. Hoặc một vòng lặp trên một kênh và kênh còn lại tìm kiếm
nhị phân. Độ phức tạp O(n log n).
Bài A. SQUARE

Bài B. THREEJUG

Bài C. WATCHING

Bài D. FARM

Bài G. TAXI

Bài H. BCA

Bài I. Binarylist

Bài K. HIST

Bài L. POSTMAN
FARM

Một trang trại trồng và cung cấp rau sạch ra thị trường cần lập kế
hoạch sản xuất cho giai đoạn từ ngày 1 đến ngày n với tổng lượng
hạt giống có để gieo trồng là Q. Do đặc tính thời vụ, nên khi gieo
trồng 1 đơn vị hạt giống vào ngày i thì sẽ thu được một sản lượng
là ai . Kế hoạch sản xuất sẽ bao gồm các đợt gieo trồng, mỗi đợt
sẽ cần tính toán gieo trồng một lượng hạt giống là bao nhiêu và
vào ngày nào. Do đặc tính sinh trưởng và thu hoạch của rau nên 2
đợt trồng liên tiếp cách nhau ít nhất K ngày: cụ thể nếu đợt thứ
nhất bắt đầu gieo trồng vào ngày thứ i thì đợt gieo trồng tiếp theo
sẽ chỉ có thể thực hiện từ ngày i + K trở đi. Ngoài ra, số đơn vị
hạt giống gieo trồng trong mỗi đợt không vượt quá hằng số P cho
trước.
Hãy tính toán kế hoạch sản xuất sao cho tổng sản lượng rau thu
được là lớn nhất.
Thuật toán 50 điểm

n, Q, P ≤ 100.
Độ phức tạp O(n4 ).
Thuật toán 70 điểm

n, Q, P ≤ 1000.
Qui hoạch động 3 chiều theo n, Q, P. Độ phức tạp O(n3 ).
Thuật toán 100 điểm
1 ≤ n ≤ 104 , 1 ≤ K ≤ 10, 1 ≤ Q, P ≤ 104 ;
a1 , . . . , an (1 ≤ ai ≤ 103 )
I Bài toán có thể biến đổi thành tìm tập con có tối đa Q/P
phần tử với tổng lớn nhất. Do đó có thể giảm bớt một chiều
qui hoạch động theo chỉ số P.
I Gọi dp(i, j) là sản lượng lớn nhất làm đến ngày i và đến đợt j.
dp(i, j) = MAX (
dp(i − 1, j), nếu ngày i không trồng,
dp(i − k, j − 1) + a[i], nếu trồng ngày i thì phải cách ra K
ngày, 1 ≤ j ≤ R = Q/P là số đợt tối đa.
)
I Sau đó truy vết với sản lượng max thu được, đầy sản lượng
mỗi ngày được chọn vào mảng sắp xếp tăng dần, và chọn
tham lam từ sản lượng ngày lớn nhất trở về sao cho mỗi đợt
không quá P và tổng không quá Q.
Bài A. SQUARE

Bài B. THREEJUG

Bài C. WATCHING

Bài D. FARM

Bài G. TAXI

Bài H. BCA

Bài I. Binarylist

Bài K. HIST

Bài L. POSTMAN
TAXI

Một taxi tải phải phục vụ N yêu cầu 1, . . . , N trong đó yêu cầu i
có điểm đón i và điểm trả hàng i + N. Taxi xuất phát từ điểm 0,
phục vụ N yêu cầu trên và quay trở lại điểm 0. Khoảng cách giữa
các điểm được cho bởi một ma trận d(2N+1)×(2N+1) trong đó di,j
là khoảng cách từ điểm i tới điểm j (0 ≤ i, j ≤ 2N). Hãy tìm hành
trình của taxi không được lặp lại đỉnh trừ đỉnh xuất phát và có
tổng khoảng cách nhỏ nhất. Biết rằng giá trị này không vượt quá
109 .
Nếu mở rộng bài toán là cho phép lặp lại đỉnh, thì cần floyd tìm
đường đi ngắn nhất giữa hai đỉnh –> yêu cầu thêm truy vết!
Cách 1: Duyệt nhánh cận, floyd trước tính cận.
Cánh 2: Qui hoạch động giống bài toán người du lịch. Một hành
trình vẫn là một hoán vị của 2xn số.
Bài toán người du lịch: Công thức Qui hoạch động

I Không mất tính tổng quát giả sử chu trình bắt đầu và kết
thúc tại đỉnh 0

I Gọi TSP(i, S) là chi phí ít nhất để đi qua toàn bộ các đỉnh và


quay trở lại đỉnh 0, nếu như hiện tại hành trình đang ở tại
đỉnh i và người du lịch đã thăm tất cả các đỉnh trong tập S

I Bước cơ sở: TSP(i, tập mọi đỉnh) = Ci,0


I Bước chuyển qui nạp:
TSP(i, S) = min j6∈S { Ci,j + tsp(j, S ∪ {j}) }
Bài toán người du lịch: Cài đặt
1 const int N = 20;
2 const int INF = 100000000;
3 int C [ N ][ N ];
4 int iMem [ N ][1 < < N ];
5 memset ( iMem , -1 , sizeof ( iMem ));
6
7 int TSP ( int i , int S ) {
8 if ( S == ((1 << N ) - 1)) return C [ i ][0];
9 if ( iMem [ i ][ S ] != -1) return iMem [ i ][ S ];
10
11 int res = INF ;
12 for ( int j = 0; j < N ; j ++) {
13 if ( S & (1 << j ))
14 continue ;
15 res = min ( res , C [ i ][ j ] + TSP (j , S | (1 << j )));
16 }
17 iMem [ i ][ S ] = res ;
18 return res ;
19 }
Bài toán người du lịch: Cài đặt

I Kết quả tối ưu có thể được đưa ra như sau:

cout << TSP (0 , 1 < <0);


Bài toán người du lịch: Độ phức tạp tính toán

I Có n × 2n khả năng cho đầu vào input


I Mỗi input được tính trong thời gian O(n)
I Thời gian tính tổng cộng là O(n2 × 2n )
I Như vậy có thể tính nhanh được với n lên đến 20
Bài toán người du lịch: Độ phức tạp tính toán

I Có n × 2n khả năng cho đầu vào input


I Mỗi input được tính trong thời gian O(n)
I Thời gian tính tổng cộng là O(n2 × 2n )
I Như vậy có thể tính nhanh được với n lên đến 20

I Làm thế nào để đưa ra được chính xác hành trình của người
du lịch?
Bài A. SQUARE

Bài B. THREEJUG

Bài C. WATCHING

Bài D. FARM

Bài G. TAXI

Bài H. BCA

Bài I. Binarylist

Bài K. HIST

Bài L. POSTMAN
03. BCA

I Có n khóa học và m giáo viên, mỗi giáo viên có danh sách các
khóa có thể dạy.
I Có danh sách các khóa học không thể để cùng một giáo viên
dạy do trùng giờ.
I Load của một giáo viên là số khóa phải dạy của giáo viên đó.
I Yêu cầu: Tìm cách xếp lịch cho giáo viên sao cho Load tối đa
của các giáo viên là tối thiểu.
Thuật toán I

I Sử dụng thuật toán vét cạn, duyệt toàn bộ khóa học, xếp
giáo viên dạy khóa học đó.
I Sử dụng thuật toán nhánh cận:
I Chọn khóa học chưa có người dạy có số giáo viên dạy ít nhất
để phân công trước.
I Nếu phân công cho giáo viên A môn X, mọi môn học trùng
lịch với môn X không thể được dạy bởi giáo viên A sau này.
I Nếu maxLoad hiện tại lớn hơn minLoad tối ưu thu được trước
đó thì không duyệt nữa.
Code

1 void arrange ( int i ) {


2 if ( i > n ) {
3 // Check result ...
4 } else {
5 int courseID = -1;
6 int totalTeacher = 999;
7 // Find non - assigned course the least
8 // number of teachers to assign first .
9 // ...
10

11 if ( courseID == -1) return ;


12
13 int maxLoad = 0;
14 // Find current maxLoad ...
15 if ( maxLoad >= minLoad ) return ;
Code
19 sjList [ courseID ]. selected = true ;
20 for ( int j =1; j <= m ; j ++) {
21 if ( sjList [ courseID ]. teacher [ j ]) {
22 bool tmp [31];
23 for ( int k =1; k <= n ; k ++) {
24 tmp [ k ] = sjList [ k ]. teacher [ j ];
25 if ( conflict [ courseID ][ k ]) {
26 sjList [ k ]. teacher [ j ]= false ;
27 }
28 }
29 schedule [ j ][ courseID ] = true ;
30 arrange ( i +1);
31 schedule [ j ][ courseID ] = false ;
32 for ( int k =1; k <= n ; k ++)
33 sjList [ k ]. teacher [ j ]= tmp [ k ];
34 }
35 }
36 sjList [ courseID ]. selected = false ;
37 }
38 }
Bài A. SQUARE

Bài B. THREEJUG

Bài C. WATCHING

Bài D. FARM

Bài G. TAXI

Bài H. BCA

Bài I. Binarylist

Bài K. HIST

Bài L. POSTMAN
Liệt kê xâu nhị phân - Binarylist

Cho 1 số nguyên dương n. Đưa ra xâu nhị phân độ dài n thứ k


trong thứ tự từ điển mà không có i số 0 liên tiếp.
Dòng đầu ghi 3 số nguyên dương n, k, i ≤ 104 cách nhau bởi dấu
cách
Hướng dẫn giải

Tìm công thức truy hồi: số Fibonacci mở rộng bậc k. Gọi fn là số


dãy độ dài n thỏa mãn điều kiện đề bài.
I f (n) = f (n − 1) nếu số 1 đứng đầu,
I f (n) = f (n − 2) nếu 01 đứng đầu, ...,
I f (n) = f (n − i) nếu 0..01 đứng đầu.
Truy vết theo công thức
Bài A. SQUARE

Bài B. THREEJUG

Bài C. WATCHING

Bài D. FARM

Bài G. TAXI

Bài H. BCA

Bài I. Binarylist

Bài K. HIST

Bài L. POSTMAN
02. HIST

I Có N cột với độ cao l1 , l2 , ...


I Tìm diện tích hình chữ nhật lớn nhất nằm gọn trong N cột
này
Thuật toán

I Nhận xét: Một hình chữ nhật với hai biên là các cột thứ i và j
có diện tích là (j − i + 1) ∗ min(li , ..., lj )
I Dễ dàng nhận thấy thuật toán O(N 3 ): thử hết các cặp i và j
và tính min 1 đoạn trong O(N)
I Nhận xét min(li , ..., lj ) = min(min(li , ..., lj−1 ), lj )
I Vậy min đoạn i đến j có thể cập nhật trong O(1) khi i giữ
nguyên và j tăng lên 1, ta có thuật toán O(N 2 )
Thuật toán

I Góc nhìn khác: thay vì đi thử các bộ i và j, ta thử các chiều


cao của hình chữ nhật, tức là nhân tử min(li , ..., lj )
I Cụ thể: với mỗi cột i, ta xét xem nếu nó là cột có độ cao thấp
nhất của một hình chữ nhật nào đó, thì chiều rộng của hình
chữ nhật đó tối đa là bao nhiêu
I Ta đi tính các giá trị lefti và righti . Trong đó lefti là vị trí của
cột gần nhất bên trái i mà có độ cao nhỏ hơn cột i, tương tự
đối với righti nhưng là ở bên phải
I Kết quả bài toán là max của các giá trị (righti − lefti − 1) ∗ li
với mọi i
Thuật toán

I Vấn đề còn lại là làm sao tính nhanh được các giá trị lefti và
righti
I => Sử dụng stack
I Ví dụ với left, ta duyệt i tăng dần, luôn duy trì một stack
chứa vị trí trước i và có độ cao nhỏ hơn cột i, trong đó các vị
trí tăng dần và top của stack lưu vị trí lớn nhất. Như vậy lefti
chính là giá trị trên đỉnh stack khi ta duyệt đến i.
I Cập nhật stack: khi nào mà li <= lstacktop thì pop phần tử
đỉnh stack. Sau đó push i vào stack
I Độ phức tạp O(N), vì một phần tử chỉ vào và ra stack tối đa
1 lần.
Code

1 template < class RandomIt >


2 vector < int > calc_extend ( RandomIt first , RandomIt last ) {
3 vector < int > result ;
4 stack < RandomIt > s ;
5 for ( RandomIt it = first ; it != last ; ++ it ) {
6 while (! s . empty () && * s . top () >= * it ) s . pop ();
7 result . push_back ( it - ( s . empty () ? ( first - 1) : s . top ()));
8 s . push ( it );
9 }
10 return result ;
11 }
12
13 int main () {
14 int n ;
15 while (( cin >> n ) && n ) {
16 vector < int > height ( n );
17 for ( int i = 0; i < n ; ++ i ) cin >> height [ i ];
18 vector < int > L = calc_extend ( height . begin () , height . end ());
19 vector < int > R = calc_extend ( height . rbegin () , height . rend ());
20 long long result = 0;
21 for ( int i = 0; i < n ; ++ i ) {
22 result = max ( result , 1 LL * ( L [ i ] + R [ n - i - 1] - 1) * height [ i ]);
23 }
24 cout << result << endl ;
25 }
26 }
Bài A. SQUARE

Bài B. THREEJUG

Bài C. WATCHING

Bài D. FARM

Bài G. TAXI

Bài H. BCA

Bài I. Binarylist

Bài K. HIST

Bài L. POSTMAN
02. POSTMAN
I Một nhân viên giao hàng cần nhận các kiện hàng tại trụ sở
công ty ở vị trí x = 0, và chuyển phát hàng đến n khách
hàng, được đánh số từ 1 đến n.
I Người khách thứ i ở vị trí xi và cần nhận mi kiện hàng.
I Nhân viên giao hàng chỉ có thể mang theo tối đa k kiện hàng
mỗi lần.
I Nhân viên giao hàng xuất phát từ trụ sở, nhận một số kiện
hàng và di chuyển theo đại lộ để chuyển phát cho một số
khách hàng. Khi giao hết các kiện hàng mang theo, nhân viên
lại quay trở về trụ sở và lặp lại công việc nói trên cho đến khi
chuyển phát hết tất cả các kiện hàng.
I Sau khi giao xong, nhân viên cần quay lại công ty để nộp hóa
đơn của ngày hôm đó.
I Giả thiết là: tốc độ di chuyển là 1 đơn vị khoảng cách trên
một đơn vị thời gian. Thời gian nhận hàng ở trụ sở công ty và
thời gian bàn giao hàng cho khách được coi là bằng 0.
I Giả sử thời điểm nhân viên giao hàng bắt đầu công việc là 0.
I Tìm cách hoàn thành công việc tại thời điểm sớm nhất.
Thuật toán

I Nhận xét: Vì công ty nằm ở vị trí x = 0 và thời gian nhận


hàng ở công ty bằng 0 nên ta có thể chia khách hàng thành 2
tập: x < 0 và x > 0. Kết quả bằng tổng thời gian chuyển
trong 2 tập
I Thuật toán
1. Phân chia khách hàng thành 2 tập: x < 0 và x > 0.
2. Với mỗi tập khách hàng, ta sắp xếp các khách hàng theo
khoảng cách từ vị trí của họ đến trụ sở công ty.
3. Nhân viên giao hàng sẽ phát từ khách hàng xa nhất trong tập,
nếu còn dư số kiện hàng sẽ phát tiếp cho khách hàng liền kề
đó.
I Độ phức tạp: O(n)
Code
1 long long calSegment ( pair < int , int > p [] , int np )
2 {
3 long long res = 0;
4 int cur = 0;
5 for ( int i = 1; i <= np ; i ++) {
6 if ( p [ i ]. second > 0) {
7 if ( cur >= p [ i ]. second ){
8 // Du so kien de phat
9 cur -= p [ i ]. second ;
10 } else {
11 // Khong du so kien de phat
12 p [ i ]. second -= cur ;
13 int times = ( p [ i ]. second - 1)/ k + 1;
14 res += 2 ll * abs ( p [ i ]. first ) * times ;
15 cur = times * k - p [ i ]. second ;
16 }
17 }
18 }
19 return res ;
20 }
Code

22 const int N = 1002;


23 typedef pair < int , int > pii ;
24 int n , nn , np , k , x , m ;
25 long long ans = 0;
26 pii negCus [ N ] , posCus [ N ];
27
28 int main ()
29 {
30 cin >> n >> k ;
31 nn = np = 0;
32 for ( int i = 1; i <= n ; i ++) {
33 cin >> x >> m ;
34 // Chia thanh 2 tap khach hang
35 if ( x < 0) negCus [++ nn ] = make_pair (x , m );
36 else posCus [++ np ] = make_pair (x , m );
37 }
38 ...
Code

40 ...
41 // Sap xep khach hang trong tap theo khoang cach
42 sort ( negCus + 1 , negCus + nn + 1);
43 sort ( posCus + 1 , posCus + np + 1 , greater < pii >());
44
45 // Tinh khoang thoi gian nho nhat voi moi tap
46 long long negSeg = calSegment ( negCus , nn , k );
47 long long posSeg = calSegment ( posCus , np , k );
48 ans = negSeg + posSeg ;
49 cout << ans ;
50 return 0;
51 }
Tính đúng đắn

Gọi:
I S ∗ là lời giải tối ưu bất kỳ thoả mãn ràng buộc tất cả khách
được giao hết hàng.
I |S| là tổng thời gian di chuyển của lời giải S.
Tính đúng đắn (tiếp)

Bổ đề 1
Gọi S ∗ (X ) là lời giải tối ưu thu được trên tập khách hàng X . Ta
có:
|S ∗ ({xi |xi > 0})| + |S ∗ ({xi |xi > 0})| = |S ∗ |

Proof. Dễ thấy, với mỗi chuyến hàng đi qua điểm 0 trong lời giải
tối ưu, ta có thể chia thành hai chuyến hàng với một chuyến đi
sang chiều dương, một chuyến hàng qua chiều âm mà thời gian
không đổi (thời gian bốc hàng và dỡ hàng = 0).
Tính đúng đắn (tiếp)

Xét tập khách hàng chỉ ở một chiều (dương hoặc âm), ta chứng
minh tính đúng đắn của lời giải tham lam trên chiều dương
(xi > 0, ∀x).
Tính đúng đắn (tiếp)

Gọi:
I S là lời giải thu được từ thuật toán tham lam ở trên.
I c(S) là số chuyến xe phải đi của lời giải S.
Tính đúng đắn (tiếp)

Bổ đề 2
Số chuyến xe phải đi để giao hết hàng cho toàn bộ khách hàng của
lời giải tham lam S là ít nhất.

c(S) ≤ c(S ∗ ), ∀S ∗

Proof. Theo phép xây dựng lời giải của thuật tham lam, ta có:
 Pn 
1 mi
c(S) = ≤ c(S ∗ )
K
Tính đúng đắn (tiếp)
Gọi t(i, S) là tổng thời gian di chuyển của i chuyến xe đầu tiên.
Chú ý, không mất tính tổng quát, các chuyến xe được đánh số thứ
tự theo thời gian di chuyển giảm dần (chuyến xe đi xa nhất đi đầu
tiên).

I t(1, S) = 2x4
I t(2, S) = 2x4 + 2x3
I ...
Chú ý: các chuyến xe chỉ xét đến quãng đường phải di chuyển,
chưa quan tâm đến phải các điểm thả hàng của mỗi chuyến.
Tính đúng đắn (tiếp)
Bổ đề 3
S ∗ là lời giải tối ưu bất kỳ. Ta có:

t(i, S) ≤ t(i, S ∗ ), ∀i

Proof.
I t(1, S) = t(1, S ∗ ) = 2xn
I Giả sử t(i, S) ≤ t(i, S ∗ ), ta chứng minh:

t(i + 1, S) ≤ t(i + 1, S ∗ )

Có:
(
t(i + 1, S) = t(i, S) + 2xl
(1)
t(i + 1, S ∗ ) = t(i, S ∗ ) + 2xl ∗
Tính đúng đắn (tiếp)

Proof. (tiếp) Theo phép xây dựng lời giải của thuật tham lam, ta
có:
Xn
0
ml + mj = i × k, 0 ≤ ml0 ≤ ml (2)
l+1

Vì chuyến i + 1 là chuyến xa nhất phải di chuyển, do vậy chuyến


mọi khách hàng ở vị trí lớn hơn xl ∗ (với S ∗ ) đã được giao hết hàng.
n
X
mj ≤ i × k (3)
l ∗ +1

Từ 2, 3 ta có: l ≤ l ∗ ⇒ xl ≤ xl ∗ . Kết hợp với 1, bổ đề được chứng


minh.
Tính đúng đắn (tiếp)
Định lý 1
Lời giải của thuật toán tham lam là tối ưu.

|S| = |S ∗ |

Proof.
(⇒) Theo giả thiết S ∗ là tối ưu, ta có |S| ≥ |S ∗ |.
(⇐) Ta chứng minh |S| ≤ |S ∗ |:
I Theo bổ đề 2, ta có:

c(S) ≤ c(S ∗ )

I Theo bổ đề 3, ta có

|S| = t(c(S), S) ≤ t(c(S), S ∗ ) ≤ t(c(S ∗ ), S ∗ ) = |S ∗ |

You might also like