Nhận viết luận văn Đại học , thạc sĩ - Zalo: 0917.193.864
Tham khảo bảng giá dịch vụ viết bài tại: vietbaocaothuctap.net
Download luận văn thạc sĩ ngành toán ứng dụng với đề tài: Giải số phương trình vi phân đại số bằng phương pháp đa bước, cho các bạn làm luận văn tham khảo
Nhận viết luận văn đại học, thạc sĩ trọn gói, chất lượng, LH ZALO=>0909232620
Tham khảo dịch vụ, bảng giá tại: https://vietbaitotnghiep.com/dich-vu-viet-thue-luan-van
Download luận văn thạc sĩ ngành toán giải tích với đề tài: Quy hoạch toàn phương, cho các bạn có thể làm luận văn tham khảo
Nhận viết luận văn Đại học , thạc sĩ - Zalo: 0917.193.864
Tham khảo bảng giá dịch vụ viết bài tại: vietbaocaothuctap.net
Download luận văn thạc sĩ ngành toán ứng dụng với đề tài: Giải số phương trình vi phân đại số bằng phương pháp đa bước, cho các bạn làm luận văn tham khảo
Nhận viết luận văn đại học, thạc sĩ trọn gói, chất lượng, LH ZALO=>0909232620
Tham khảo dịch vụ, bảng giá tại: https://vietbaitotnghiep.com/dich-vu-viet-thue-luan-van
Download luận văn thạc sĩ ngành toán giải tích với đề tài: Quy hoạch toàn phương, cho các bạn có thể làm luận văn tham khảo
Nhận viết luận văn đại học, thạc sĩ trọn gói, chất lượng, LH ZALO=>0909232620
Tham khảo dịch vụ, bảng giá tại: https://vietbaitotnghiep.com/dich-vu-viet-thue-luan-van
Download luận văn thạc sĩ ngành toán giải tích với đề tài: Bài toán ổn định hóa hệ phương trình điều khiển phi tuyến, cho các bạn làm luận văn tham khảo
Nhận viết luận văn Đại học , thạc sĩ - Zalo: 0917.193.864
Tham khảo bảng giá dịch vụ viết bài tại: vietbaocaothuctap.net
Download luận văn thạc sĩ ngành kĩ thuật xây dựng với đề tài: Xác định nội lực và chuyển vị của dầm hữu hạn trên nền đàn hồi, cho các bạn làm luận văn tham khảo
Download luận văn thạc sĩ ngành toán giải tích với đề tài: Sự ổn định của phương trình vi phân tuyến tính và phương trình vi phân tuyến tính có nhiễu trong không gian HILBERT, cho các bạn làm luận văn tham khảo
Nhận viết luận văn đại học, thạc sĩ trọn gói, chất lượng, LH ZALO=>0909232620
Tham khảo dịch vụ, bảng giá tại: https://vietbaitotnghiep.com/dich-vu-viet-thue-luan-van
Download luận văn thạc sĩ ngành toán học với đề tài: Một số phương pháp giải hệ phương trình trong chương trình toán Trung học phổ thông, cho các bạn có thể làm luận văn tham khảo
Download luận văn thạc sĩ ngành toán giải tích với đề tài: Sử dụng phương pháp lyapunov để nghiên cứu tính chất nghiệm của phương trình vi phân tuyến tính bị nhiễu, cho các bạn làm luận văn tham khảo
Nhận viết luận văn đại học, thạc sĩ trọn gói, chất lượng, LH ZALO=>0909232620
Tham khảo dịch vụ, bảng giá tại: https://vietbaitotnghiep.com/dich-vu-viet-thue-luan-van
Download luận văn thạc sĩ ngành toán giải tích với đề tài: Bài toán ổn định hóa hệ phương trình điều khiển phi tuyến, cho các bạn làm luận văn tham khảo
Nhận viết luận văn Đại học , thạc sĩ - Zalo: 0917.193.864
Tham khảo bảng giá dịch vụ viết bài tại: vietbaocaothuctap.net
Download luận văn thạc sĩ ngành kĩ thuật xây dựng với đề tài: Xác định nội lực và chuyển vị của dầm hữu hạn trên nền đàn hồi, cho các bạn làm luận văn tham khảo
Download luận văn thạc sĩ ngành toán giải tích với đề tài: Sự ổn định của phương trình vi phân tuyến tính và phương trình vi phân tuyến tính có nhiễu trong không gian HILBERT, cho các bạn làm luận văn tham khảo
Nhận viết luận văn đại học, thạc sĩ trọn gói, chất lượng, LH ZALO=>0909232620
Tham khảo dịch vụ, bảng giá tại: https://vietbaitotnghiep.com/dich-vu-viet-thue-luan-van
Download luận văn thạc sĩ ngành toán học với đề tài: Một số phương pháp giải hệ phương trình trong chương trình toán Trung học phổ thông, cho các bạn có thể làm luận văn tham khảo
Download luận văn thạc sĩ ngành toán giải tích với đề tài: Sử dụng phương pháp lyapunov để nghiên cứu tính chất nghiệm của phương trình vi phân tuyến tính bị nhiễu, cho các bạn làm luận văn tham khảo
Nhận viết luận văn đại học, thạc sĩ trọn gói, chất lượng, LH ZALO=>0909232620
Tham khảo dịch vụ, bảng giá tại: https://vietbaitotnghiep.com/dich-vu-viet-thue-luan-van
Download luận văn thạc sĩ ngành toán học với đề tài: Một số phương pháp giải hệ phương trình trong chương trình toán trung học phổ thông, cho các bạn tham khảo
Diophantine equations Phương trình diophantBui Loi
Đây là một trong các dạng câu khó của diophant , một dạng câu trong môn số học dành cho chuyên ngành toán học, Đhsp
facebook tui, fb.com/starheaven.2110
This document provides details for designing the production process for a men's pants order, including:
- The order is for 4,000 pants in sizes S, M, L and black or gray color.
- The product is described along with specifications and diagrams.
- Raw material requirements and quality standards are defined.
- The document analyzes the product structure and establishes linkages between parts.
- Process flow charts and operations are outlined to produce the pants within the required time frame.
kl_HOÀN THIỆN CÔNG TÁC ĐÁNH GIÁ THỰC HIỆN CÔNG VIỆC TẠI CÔNG TY CỔ PHẦN ĐẦU T...Luận Văn Uy Tín
Luận Văn Uy Tín cung cấp dịch vụ viết thuê luận văn thạc sĩ, tốt nghiệp, báo cáo thực tập, hoàn tiền 100% nếu bài bị đánh rớt, bảo mật thông tin, giao bài đúng hạn.
Tuyển tập 9 chuyên đề bồi dưỡng Toán lớp 5 cơ bản và nâng cao ôn thi vào lớp ...Bồi Dưỡng HSG Toán Lớp 3
Tuyển tập 9 chuyên đề bồi dưỡng Toán lớp 5 cơ bản và nâng cao ôn thi vào lớp 6 trường chuyên. Đăng ký mua tài liệu Toán 5 vui lòng liên hệ: 0948.228.325 (Zalo - Cô Trang Toán IQ).
Hành vi tình dục không an toàn và các yếu tố liên quan trong nhóm nam quan hệ...Man_Ebook
Hành vi tình dục không an toàn và các yếu tố liên quan trong nhóm nam quan hệ tình dục đồng giới tại Hà Nội năm 2009-2010
Liên hệ tài tài liệu (Free): https://www.facebook.com/man.trl/
Từ ngữ về con người và chiến tranh trong Nhật ký Đặng Thùy Trâm.pdf
Tai lieu boi duong doi tuyen quoc gia 2013 3
1. Page 0 of 84
Võ Văn Trị - CQB | Confidential
MỤC LỤC
Phương pháp duyệt
Chuyên đề 1. Duyệt vét cạn..................................................................................................................1
Chuyên đề 2. Duyệt nhánh cạnh..................................................................................................... 12
Chuyên đề 3. Duyệt ưu tiên............................................................................................................... 24
Tìm kiếm nhị phân
Chuyên đề 4. Tìm kiếm nhị phân và ứng dụng......................................................................... 27
Xử lý bít
Chuyên đề 5. Xử lý bit.......................................................................................................................... 30
Quy hoạch động
Chuyên đề 6. Quy hoạch động cơ bản .......................................................................................... 36
Chuyên đề 7. Quy hoạch động trạng thái.................................................................................... 49
Đồ thị
Chuyên đề 8. Tìm kiếm theo chiều rộng ..................................................................................... 58
Chuyên đề 9. Tìm kiếm theo chiều sâu........................................................................................ 69
2. Võ Văn Trị - CQB | Confidential
PHƯƠNG PHÁP DUYỆT
Chuyên đề 1. Duyệt vét cạn - Backtracking
Quay lui, vét cạn, thử sai, duyệt… là một số tên gọi tuy không đồng nghĩa nhưng
cùng chỉ một phương pháp trong tin học: tìm nghiệm của một bài toán bằng cách
xem xét tất cả các phương án có thể. Đối với con người phương pháp này thường
không khả thi vì số phương án cần kiểm tra lớn. Tuy nhiên đối với máy tính, nhờ
tốc độ xử lý nhanh, máy tính có thể giải rất nhiều bài toán bằng phương pháp
quay lui vét cạn. Người đầu tiên đề ra chiến lược này là nhà toán học người Mỹ
Derrick Henry Lehmer (1905 – 1991) vào những năm 1950.
Ưu điểm của phương pháp quay lui, vét cạn là luôn bảo đảm tìm ra nghiệm đúng,
chính xác. Tuy nhiên, hạn chế của phương pháp này là thời gian thực thi lâu, độ
phức tạp lớn.
Về bản chất, tư tưởng của phương pháp này là thử từng khả năng cho đến khi tìm
thấy lời giải đúng. Đó là một quá trình tìm kiếm theo độ sâu trong một tập các lời
giải. Trong quá trình tìm kiếm, nếu gặp một hướng lựa chọn không thỏa mãn, ta
quay lui, về điểm lựa chọn có các hướng khác và thử hướng lựa chọn tiếp theo.
Khi đã thử hết tất cả các hướng lựa chọn xuất phát từ một điểm, ta quay lại điểm
lựa chọn kế trước. Quá trình tìm kiếm kết thúc khi không còn hướng lựa chọn nào
để thử.
Chiến lược quay lui tương tự với tìm kiếm theo độ sâu nhưng tốn ít không gian
nhớ hơn, thời gian tìm kiếm lại nhanh hơn.
Mô hình thuật toán Backtracking:
procedure try(i:integer);
begin
for <mọi giá trị t có thể gán cho xi> do
begin
<Thử cho xi := t>;
if <thành công> then <thông báo kết quả>
else
begin
<Ghi nhận việc xi nhận giá trị t>;
<try(i+1)>; {th bước đi tiếp theo}
<Hủy bước đi thứ i (nếu cần)>;
end;
end;
end;
1. Bài tập 1: Liệt kê tất cả các dãy nhị phân có độ dài n.
3. Page 2 of 84
Võ Văn Trị - CQB | Confidential
Phân tích:
Dãy nhị phân có độ dài n có dạng (x1, x2, …, xn) với xi ∈ {0, 1}, 1 ≤ ≤ . Như vậy,
tại bước thứ i, ta tìm cách chọn giá trị cho biến xi.
{Chuong trinh cai dat thuat toan de quy}
{Liet ke tat ca cac cau hinh nhi phan co do dai n}
Program BackTracking_ListsOfBinaryPermutations;
Const
n=3;
var
i,k:byte;
h:array[1..20] of byte;
Procedure Try(i:byte);
var j:byte;
begin
for j:=0 to 1 do
begin
h[i]:=j;
if i=n then
begin
for k:=1 to n do write(h[k]);
writeln;
end
else
Try(i+1);
end;
end;
begin
try(1);
end.
2. Bài tập 2: Liệt kê tất cả các hoán vị của tập {1, 2, …, n}
Phân tích:
Các hoán vị của tập {1, 2, …, n} có dạng (x1, x2, …, xn) với xi ∈ {1, 2, … , }, 1 ≤ ≤
và xi # xj với mọi i, j.
- Như vậy, việc xây dựng mỗi hoán vị được thực hiện qua n bước.
- Bước thứ i ta chọn một số trong tập {1, 2, …, n} để đặt vào vị trí thứ i
của hoán vị.
- Tuy nhiên, ta chỉ chọn được số x i khi nó chưa được chọn cho các vị trí
trước đó.
Ta sử dụng mảng đánh dấu như sau:
KT False True True …. … … …
1 2 3 n
Với ý nghĩa:
- KT[i] = True nếu i chưa được chọn
4. Võ Văn Trị - CQB | Confidential
- KT[i] = False nếu i đã được chọn
{Chuong trinh cai dat thuat toan de quy}
{Liet ke tat ca cac hoan vi cua tap (1,2,...,n)}
Program BackTracking_PermutationLists;
Uses crt;
Const
n=3;
var
i,k:byte;
kt:array[1..20] of boolean;
h:array[1..20] of byte;
Procedure Try(i:byte);
var j:byte;
begin
for j:=1 to n do
if kt[j] then
begin
h[i]:=j;
kt[j]:=false;
if i=n then
begin
for k:=1 to n do write(h[k],' ');
writeln;
end
else
Try(i+1);
kt[j]:=true;
end;
end;
begin
clrscr;
fillchar(kt[1],n,true);
try(1);
end.
3. Bài tập 3: Tổ hợp
Một tổ hợp chập k của n là một tập con k phần tử của n phần tử.
Chẳng hạn tập {1, 2, 3, 4} có các tổ hợp chập 2 là:
{1, 2}, {1, 3}, {1, 4}, {2, 3}, {2, 4}, {3, 4}
Vì trong tập hợp các phần tử không phân biệt thứ tự nên tập {1, 2} cũng là tập
hợp {2, 1}, do đó ta coi chúng chỉ là một tổ hợp.
Yêu cầu: Hãy xác định tất cả các tổ hợp chập k của tập n phần tử.
Phân tích:
5. Page 4 of 84
Võ Văn Trị - CQB | Confidential
Mỗi tổ hợp chập k của n phần tử có dạng (x1, x2, …, xk) trong đó:
- xi là một giá trị nằm trong tập {1, 2, …, n}.
- vì tập hợp không phân biệt thứ tự nên ta sắp xếp các phần tử theo thứ tự
tăng dần, vì vậy ràng buộc x i < xi+1 với mọi giá trị i từ 1 đến k-1.
- ứng cử viên xi được chọn từ tập giá trị {xi-1 + 1, ...., n – (k-i)}
- nguyên tắc chọn trên giúp ta khỏi cần phải dánh dấu, bởi vì việc chọn giá
trị tiếp theo phần tử đã được chọn trước đó nên sẽ không bị lặp lại.
Chương trình
{chuong trinh de quy quay lui}
{liet ke tat ca cac to hop chap k cua tap n phan tu}
program BackTracking_PermutationLists;
const
n=4;
k=3;
var
h:array[1..20] of byte;
i:byte;
procedure ghinghiem;
var j:byte;
begin
write('{');
for j:=1 to k do write(h[j],' ');
writeln('}');
end;
procedure try(i:byte);
var j:byte;
begin
for j:= h[i-1]+1 to n-(k-i) do
begin
h[i]:=j;
if i=k then ghinghiem
else try(i+1);
end;
end;
begin
try(1);
readln;
end.
4. Bài tập 4: Chỉnh hợp lặp
Chỉnh hợp lặp chập k của n phần tử là một dãy gồm k thành phần, mỗi thành phần
là một phần tử của tập n phần tử, không yêu cầu các thành phần là khác nhau và
có phân biệt thứ tự của các cấu hình.
Ví dụ, một dãy nhị phân có độ dài 3 là một chỉnh hợp lặp chập 3 của tập 2 phần tử
{0, 1}. Các dãy nhị phân có độ dài 3:
000, 001, 010, 011, 100, 101, 111
6. Võ Văn Trị - CQB | Confidential
Vì có phân biệt thứ tự nên cấu hình 001 khác với 010.
Như vậy, cách tìm nghiệm của bài toán chỉnh hợp lặp như sau:
- Mỗi chỉnh hợp lặp chập k của tập n phần tử có dạng (x1, x2, …, xk).
- xi là một giá trị lấy trong tập {1, 2, …, n}.
- không có ràng buộc nào giữa các thành phần.
{chuong trinh de quy quay lui}
{liet ke tat ca cac chinh hop lap chap k cua n}
program Backtracking_chinhhoplap;
const
n=2;
k=3;
var
h:array[1..20] of byte;
i:byte;
procedure ghinghiem;
var j:byte;
begin
for j:=1 to k do write(h[j],' ');
writeln
end;
procedure chinhhoplap(i:byte);
var j:byte;
begin
for j:=1 to n do
begin
h[i]:=j;
if i=k then ghinghiem
else chinhhoplap(i+1);
end;
end;
begin
chinhhoplap(1);
readln
end.
5. Bài tập 5: Chỉnh hợp không lặp
Đối với chỉnh hợp lặp, các thành phần được phép lặp lại. Đối với chỉnh hợp không
lặp chập k của n phần tử, các thành phần không được phép lặp lại. Ví dụ, có n
người, một cách chọn ra k người để xếp thành 1 hàng là một chỉnh hợp không lặp
chập k của n phần tử.
Một trường hợp đặc biệt của chỉnh hợp không lặp là hoán vị. Hoán vị của một tập
n phần tử là chỉnh hợp không lặp chập n của n.
Như vậy, cách tìm nghiệm của bài toán như sau:
- Mỗi nghiệm của bài toán là một dãy gồm k thành phần (x 1, x2, …, xk)
7. Page 6 of 84
Võ Văn Trị - CQB | Confidential
- Mỗi thành phần xi là một giá trị lấy trong tập {1, 2, …, n}
- Các giá trị đôi một khác nhau, để kiểm soát ràng buộc này, ta sử dụng mảng đánh
dấu ok với ý nghĩa như sau:
Ok[j] = true có nghĩa rằng j sẽ chọn được
Ok[j] = false thì không chọn được, vì đã chọn j cho các vị trí trước đó.
* Chương trình như sau:
{Chuong trinh de quy quay lui
liet ke tat ca cac chinh hop ko lap}
program Backtracking_chinhhopkolap;
const
n=2;
k=2;
var
ok:array[1..20] of boolean;
h:array[1..20] of byte;
i:byte;
procedure ghinghiem;
var j:byte;
begin
for j:=1 to k do write(h[j],' ');
writeln;
end;
procedure Chinhhopkolap(i:byte);
var j:byte;
begin
for j:=1 to n do
if ok[j] then
begin
h[i]:=j;
ok[j]:=false;
if i=k then ghinghiem
else chinhhopkolap(i+1);
ok[j]:=true;
end;
end;
begin
fillchar(ok[1],n,true);
chinhhopkolap(1);
readln;
end.
6. Bài tập 6: Bài toán xếp tám quân hậu
Một bàn cờ quốc tế là một bảng hình vuông gồm 8 hàng, 8 cột. Quân hậu là một
quân cờ có thể ăn được bất kỳ quân nào trên cùng một hàng, cùng một cột hay
một đường chéo. Hãy xếp tám quân hậu trên bàn cờ sao cho không có quân hậu
nào có thể ăn được quân hậu nào.
Giải:
8. Võ Văn Trị - CQB | Confidential
- Theo bài toán, trên mỗi cột (j=1..8) của bàn cờ sẽ được đặt 1 quân hậu.
- Như vậy với mỗi cột ta phải tìm dòng thứ i nào đấy để đặt quân hậu vào. Có
8 phương án chọn dòng i: i=1, 2, …, 8
- Ta có thể đặt quân hậu vào ô [i,j] khi:
- Dòng i chưa có hậu
- Đường chéo song song với đường chéo chính đi qua ô [i,j] chưa có
hậu
- Đường chéo song song với đường chéo phụ đi qua ô [i,j] chưa có hậu
- Khi đó, thủ tục try(j) thực hiện nhiệm vụ chọn dòng thứ i nào đấy để đặt
quân hậu thứ j vào ô [i,j]
- Ta có thể minh họa một bàn cờ như sau:
- Nhìn vào bàn cờ, ta có thể thấy:
- Các ô nằm trên đường chéo // với đường chéo chính thì hiệu của chỉ
số dòng và chỉ số cột là không đổi;
- Các ô nằm trên đường chéo // với đường chéo phụ thì tổng của chỉ
số cột và chỉ số dòng là không đổi;
- Vì thế, ta có thể đánh dấu trạng thái của bàn cờ như sau:
- Đánh dấu trạng thái dòng
- Đánh dấu trạng thái các đường chéo // với đường chéo chính
9. Page 8 of 84
Võ Văn Trị - CQB | Confidential
- Đánh dấu trạng thái các đường chéo // với đường chéo phụ
- Để lưu giữ kết quả, ta sử dụng mảng một chiều x
{Chuong trinh de quy quay lui
liet ke moi nghiem cua bai toan 8 quan hau}
program eightQueen;
const
fo='equeen.out';
var
{danh dau trang thai dong}
a:array[1..8] of boolean;
{danh dau trang thai duong cheo // cheo chinh}
b:array[-7..7] of boolean;
{danh dau trang thai duong cheo // cheo phu}
c:array[2..16] of boolean;
x:array[1..8] of byte;
j:byte; f:text;
procedure ghinghiem;
var i:byte;
begin
for i:=1 to 8 do write(f,x[i], ' ');
writeln(f);
end;
procedure equeen(j:byte);
var i:byte;
begin
for i:=1 to 8 do
if a[i] and b[i-j] and c[i+j] then
10. Võ Văn Trị - CQB | Confidential
begin
x[j]:=i;
a[i]:=false;
b[i-j]:=false;
c[i+j]:=false;
if j=8 then ghinghiem
else equeen(j+1);
a[i]:=true;
b[i-j]:=true;
c[i+j]:=true;
end;
end;
begin
fillchar(a[1],8,true);
fillchar(b[-7],15,true);
fillchar(c[2],15,true);
assign(f,fo);
rewrite(f);
equeen(1);
close(f);
end.
7. Bài tập 7: Bài toán máy rút tiền tự động ATM
Một máy ATM hiện có n ( ≤ 20) tờ tiền có giá t1, t2, …, tn. Hãy đưa ra một cách trả
với số tiền đúng bằng s.
Input: tệp ATM.INP có dạng:
- Dòng 1: ghi hai số n và S;
- Dòng 2: ghi n số t1, t2, …, tn
Output: ghi ra tệp ATM.OUT có dạng: Nếu có thể trả đúng S thì đưa ra cách trả,
nếu không ghi -1.
ATM.INP ATM.OUT
10 390
200 10 20 20 50 50 50
50 100 100
20 20 50 50 100 100
Nghiệm của bài toán là một dãy nhị phân độ dài n, trong đó thành phần thứ i bằng
1 nếu tờ tiền thứ i được sử dụng, bằng 0 trong trường hợp ngược lại. (x1, x2, …, xn)
là nghiệm nếu 1 1 + 2 2 + ⋯ + .
* Chương trình:
{Chuong trinh de quy quay lui
giai bai toan may rut tien tu dong ATM}
Program AtmSolution;
const
fi='atm.inp';
11. Page 10 of 84
Võ Văn Trị - CQB | Confidential
fo='atm.out';
var
{mang t bieu dien menh gia cua cac to tien}
t:array[1..20] of integer;
{mang x ghi nhan ket qua}
x:array[1..20] of byte;
n:integer; i:byte; sum,s:longint;
ok:boolean; f:text;
procedure docdl;
var j:byte;
begin
assign(f,fi); reset(f);
readln(f,n,s);
for j:=1 to n do read(f,t[j]);
close(f);
end;
procedure ghinghiem;
var j:byte;
begin
ok:=true;
for j:=1 to n do
if x[j]=1 then write(f,t[j],' ');
writeln(f);
end;
procedure atm(i:integer);
var j:byte;
begin
for j:=0 to 1 do
begin
sum:=sum+j*t[i];
x[i]:=j;
if sum = s then ghinghiem;
if (sum<s)and(i<n) then atm(i+1);
if ok=true then exit;
sum:=sum-j*t[i];
end;
end;
begin
docdl;
ok:=false; sum:=0;
fillchar(x[1],n,0);
assign(f,fo); rewrite(f);
atm(1);
if ok=false then writeln(f,-1);
close(f);
end.
Bài tập luyện tập
1.1 Bài toán mã đi tuần (nguồn bài: Tài liệu giáo khoa chuyên tin Q1)
12. Võ Văn Trị - CQB | Confidential
Cho bàn cờ n x n ô, tìm cách di chuyển một quân mã (mã di chuyển theo luật cờ
vua) trên bàn cờ xuất phát từ ô (1, 1) đi qua tất cả các ô, mỗi ô qua đúng 1 lần.
Ví dụ với n = 5:
1 24 13 18 7
14 19 8 25 12
9 2 23 6 17
20 15 4 11 22
3 10 21 16 5
1.2 Số siêu nguyên tố (nguồn bài: Tài liệu giáo khoa chuyên tin Q1)
Số siêu nguyên tố là số nguyên tố mà khi bỏ bớt một số tùy ý các chữ số bên phải
của nó thì phần còn lại vẫn là một số nguyên tố.
Ví dụ 2333 là một số siêu nguyên tố có 4 chữ số vì 233, 23, 2 cũng là các số
nguyên tố. Cho số nguyên dương N (0 < < 10), đưa ra các số siêu nguyên tố có
N chữ số cùng số các số đó.
Ví dụ với N = 4 có 16 số:
2333, 2339, 2393, 2399, 2939, 3119, 3137, 3733, 3739, 3793, 3797, 5939, 7193,
7331, 7333, 7393
1.3 Chèn phép toán (nguồn bài: Tài liệu giáo khoa chuyên tin Q1)
Cho một xâu S chỉ gồm các ký tự từ ‘0’ đến ‘9’, độ dài nhỏ hơn 10 và số nguyên m,
hãy đưa ra một cách chèn vào S các dấu ‘+’ hoặc ‘ -‘ để thu được số m cho trước
(nếu có thể).
Ví dụ, M=8, S = ‘123456789’ thì một cách chèn là: ‘ -1+2-3+4+5-6+7-8+9’
1.4 Phân tích số (nguồn bài: Tài liệu giáo khoa chuyên tin Q1)
Cho n số nguyên dương a1, a2, …, an ( ≤ 10, ≤ 109
). Tìm số nguyên dương m
nhỏ nhất sao cho m không phân tích được dưới dạng tổng của một số các số
thuộc n số trên (mỗi số sử dụng không quá một lần).
Dữ liệu vào Kết quả
n = 4
dãy số:
1, 2, 3, 6
13
13. Page 12 of 84
Võ Văn Trị - CQB | Confidential
Chuyên đề 2. Duyệt nhánh cận
Trong thực tế, có nhiều bài toán yêu cầu tìm ra một phương án thỏa mãn một số
điều kiện nào đó, và phương án đó là tốt nhất theo một tiêu chí cụ thể. Các bài
toán như vậy được gọi là bài toán tối ưu. Có nhiều bài toán tối ưu không có thuật
toán nào thực sự hữu hiệu để giải quyết, mà cho đến nay vẫn phải dựa trên mô
hình xem xét toàn bộ các phương án, rồi đánh giá để chọn ra phương án tốt nhất.
Phương pháp nhánh và cận là một dạng cải tiến của phương pháp quay lui, được
áp dụng để tìm nghiệm của bài toán tối ưu.
Giả sử nghiệm của bài toán có thể biểu diễn dưới dạng một véctơ (x1, x2, …, xn),
mỗi thành phần xi (i = 1, 2, …, n) được chọn ra từ tập Si. Mỗi nghiệm của bài toán X
= (x1, x2, …, xn) được xác định độ tốt bằng một hàm f(X) và mục tiêu cần tìm
nghiệm X để f(X) đạt giá trị nhỏ nhất (hoặc lớn nhất).
Tư tưởng của phương pháp nhánh và cận như sau: Giả sử đã xây dựng được k
thành phần của nghiệm (x1, x2, …, xk) và khi mở rộng nghiệm (x1, x2, …, xk+1), nếu
biết rằng tất cả các nghiệm mở rộng của nó (x1, x2, …, xk+1, …) đều không tốt bằng
nghiệm tốt nhất đã biết ở thời điểm trước đó, thì ta không cần mở rộng từ (x1, x2,
…, xk) nữa. Như vậy, với phương pháp nhánh và cận, ta không phải duyệt toàn bộ
các phương án để tìm ra nghiệm tốt nhất mà bằng cách đánh giá các nghiệm mở
rộng, ta có thể cắt bỏ những nhánh không cần thiết, do đó việc tìm nghiệm tối ưu
sẽ nhanh hơn. Cái khó nhất trong việc áp dụng phương pháp nhánh và cận là
đánh giá các nghiệm mở rộng, nếu đánh giá được tốt sẽ giúp bỏ qua được nhiều
phương án không cần thiết, khi đó thuật toán nhánh cận sẽ chạy nhanh hơn nhiều
so với thuật toán vét cạn.
Thuật toán nhánh và cận có thể mô tả bằng mô hình đệ quy sau:
Procedure BranchBound(i); {xây dựng thành phần thứ i}
Begin
<đánh giá các nghiệm mở rộng>;
If <các nghiệm mở rộng đều không tốt hon BestSolution>
Then exit;
<xác định Si: tập các phương án có thể chọn cho xi>;
For xi Si do
Begin
<ghi nhận thành phần thứ i>;
If i=n then <cập nhật lại BestSolution>
Else BranchBound(i+1);
<loai bo thành phần thứ i>;
End;
End;
Trong đó, BestSolution là nghiệm tốt nhất đã biết ở thời điểm đó. Thủ tục < cập
nhật lại BestSolution> sẽ xác định “độ tốt” của nghiệm mới tìm thấy, nếu nghiệm
14. Võ Văn Trị - CQB | Confidential
mới tìm thấy tốt hơn BestSolution thì BestSolution sẽ được cập nhật lại là nghiệm
mới tìm được.
1. Bài toán máy rút tiền tự động ATM
Bài toán
Một máy ATM hiện có n ( ≤ 20) tờ tiền có giá t1, t2, …, tn. Hãy tìm cách trả ít tờ
nhất với số tiền đúng bằng S.
Input: Tệp ATM.INP có dạng:
- Dòng đầu là hai số n và S.
- Dòng thứ hai gồm n số t1, t2, …, tn.
Output: Tệp ATM.OUT có dạng: Nếu có thể trả tiền đúng bằng S thì đưa ra số tờ ít
nhất cần trả và đưa ra cách trả, nếu không ghi -1.
ATM.INP ATM.OUT
10 390
200 10 20 20 50 50 50 50 100 100
5
20 20 50 100 200
Giải:
Như đã biết, nghiệm của bài toán là một dãy nhị phân có độ dài n, giả sử đã xây
dựng được k thành phần (x 1, x2, …,xk), đã trả được sum và sử dụng c tờ tiền. Để
đánh giá các nghiệm mở rộng của (x1, x2, …,xk) ta nhận thấy:
- Còn phải trả S – sum;
- Gọi tmax[k] là giá cao nhất trong các tờ tiền còn lại (tmax[k] = max{tk+1, …, tn})
- Thì ít nhất cần sử dụng thêm [
−
[ ]
] tờ nữa
Do đó, nếu c +
−
[ ]
mà lớn hơn hoặc bằng số tờ của cách trả tốt nhất hiện có thì
không cần mở rộng các nghiệm của (x1, x2, …, xk) nữa.
Chương trình:
{Giai bai toan ATM bang phuong phap nhanh can}
Program ATM_BranchandBound;
const
fi = 'atm.inp';
fo = 'atm.out';
nm = 20;
var
x, xbest:array[1..nm] of byte;
t, tmax:array[1..nm] of longint;
c, cbest:longint; n,s,sum:longint;
procedure docdl;
var j:byte; f:text;
15. Page 14 of 84
Võ Văn Trị - CQB | Confidential
begin
assign(f,fi); reset(f);
readln(f,n,s);
for j:=1 to n do read(f,t[j]);
close(f);
end;
procedure init;
var j:byte;
begin
tmax[n]:=t[n];
for j:=n-1 downto 1 do
begin
tmax[j]:=tmax[j+1];
if tmax[j]<t[j] then tmax[j]:=t[j];
end;
sum:=0; c:=0;
cbest:=n+1;
end;
procedure update;
begin
if (sum = s) and (c<cbest) then
begin
xbest:=x; cbest:=c;
end;
end;
procedure BranchBound(i:byte);
var j:byte;
begin
if c + (s - sum)/tmax[i] >=cbest then exit;
for j:=0 to 1 do
begin
x[i]:=j;
sum:=sum+x[i]*t[i];
c:=c+j;
if i=n then update
else
if sum<s then branchbound(i+1);
sum:=sum-x[i]*t[i];
c:=c-j;
end;
end;
procedure ghinghiem;
var j:byte; f:text;
begin
assign(f,fo);
rewrite(f);
if cbest<n+1 then
begin
writeln(f,cbest);
for j:=1 to n do
16. Võ Văn Trị - CQB | Confidential
if xbest[j]=1 then write(f,t[j],' ');
end
else writeln(f,-1);
close(f);
end;
begin
docdl;
init;
branchbound(1);
ghinghiem;
end.
2. Bài toán người du lịch
Bài toán: Cho n thành phố được đánh số từ 1 đến n và các tuyến đường giao
thông hai chiều giữa chúng, mạng lưới giao thông này được cho bởi mảng C[1..n,
1..n], ở đây Cịj = Cji là chi phí đi đoạn đường trực tiếp từ thành phố i đến thành
phố j (hoặc ngược lại).
Một người du lịch xuất phát từ thành phố 1, muốn đi thăm tất cả các thành phố
còn lại mỗi thành phố đúng 1 lần và cuối cùng quay lại thành phố 1. Hãy chỉ ra cho
người đó hành trình với chi phí ít nhất. Bài toán được gọi là bài toán người du lịch
hay bài toán người chào hàng (Travelling Salesman Problem – TSP).
Input: Tệp TSP.INP có dạng:
- Dòng đầu chứa số n (1 ≤ ≤ 20), là số thành phố;
- n dòng tiếp theo, mỗi dòng n số mô tả mảng C.
Output: Tệp TSP.OUT có dạng:
- Dòng đầu là chi phí ít nhất;
- Dòng thứ hai mô tả hành trình
Ví dụ 1
TSP.INP TSP.OUT Hình ảnh minh họa
4
0 20 35 42
20 0 34 30
35 34 0 12
42 30 12 0
97
1->2->4->3->1
Ví dụ 2
17. Page 16 of 84
Võ Văn Trị - CQB | Confidential
TSP.INP TSP.OUT Hình ảnh minh họa
4
0 20 35 10
20 0 90 50
35 90 0 12
10 50 12 0
117
1->2->4->3->1
Giải
1) Hành trình cần tìm có dạng (x1 = 1, x2, …, xn, xn+1 = 1), ở đây giữa xi và xi+1:
hai thành phố liên tiếp trong hành trình phải có đường đi trực tiếp; trừ
thành phố 1, không thành phố nào được lặp lại hai lần, có nghĩa là dãy (x 1,
x2, …, xn) lập thành một hoán vị của (1, 2, …, n).
2) Duyệt quay lui: x2 có thể chọn một trong các thành phố mà x 1 có đường đi
trực tiếp tới, với mỗi cách thử chọn x2 như vậy thì x3 có thể chọn một trong
các thành phố mà x2 có đường đi tới (ngoài x1). Tổng quát: xi có thể chọn 1
trong các thành phố chưa đi qua mà xi-1 có đường đi trực tiếp tới
(2 ≤ ≤ ).
3) Nhánh cận: Khởi tạo cấu hình BestSolution có chi phí bằng +∞. Với mỗi
bước thử chọn xi xem chi phí đường đi cho tới lúc đó có nhỏ hơn chi phí
của cấu hình BestSolution không? Nếu không nhỏ hơn thì thứ giá trị khác
ngay bởi có đi tiếp cũng chỉ tốn thêm. Khi thử được một giá trị xn ta kiểm
tra xem xn có đường đi trực tiếp về 1 hay không? Nếu có đánh giá chi phí đi
từ thành phố 1 đến thành phố x n cộng với chi phí từ xn trực tiếp về 1, nếu
nhỏ hơn BestSolution thì cập nhật lại BestSolution bằng cách đi mới.
Chương trình
{Giai bai toan nguoi du lich bang phuong phap nhanh can}
program TSP;
const
fi='tsp.inp';
fo='tsp.out';
nm=20;
oo=1000000;
var
c:array[1..nm,1..nm] of longint;
x,xbest:array[1..nm] of byte;
ok:array[1..nm] of boolean;
sum,best:longint; n:byte;
procedure docdl;
var i,j:byte;
18. Võ Văn Trị - CQB | Confidential
f:text;
begin
assign(f,fi); reset(f);
readln(f,n);
for i:=1 to n do
for j:=1 to n do read(f,c[i,j]);
close(f);
end;
procedure update;
begin
if sum+c[x[n],x[1]]<best then
begin
best:=sum+c[x[n],x[1]];
xbest:=x;
end;
end;
procedure init;
begin
fillchar(ok[1],n,true);
ok[1]:=false;
x[1]:=1;
best:=oo;
end;
procedure branchbound(i:byte);
var j:byte;
begin
if sum>best then exit;
for j:=1 to n do
if ok[j] and (c[x[i-1],j]<>0) then
begin
x[i]:=j;
ok[j]:=false;
sum:=sum+c[x[i-1],j];
if i=n then update
else branchbound(i+1);
sum:=sum-c[x[i-1],j];
ok[j]:=true;
end;
end;
procedure ghinghiem;
var f:text; i:byte;
begin
assign(f,fo); rewrite(f);
writeln(f,best);
for i:=1 to n do write(f,xbest[i],'->');
writeln(f,xbest[1]);
close(f);
end;
19. Page 18 of 84
Võ Văn Trị - CQB | Confidential
begin
docdl;
init;
branchbound(2);
ghinghiem;
end.
Bài tập luyện tập
2.1 Bài tập 4.15 (nguồn bài: Tài liệu giáo khoa chuyên tin Q1)
Lời giải bài toán người du lịch ở trên là một giải pháp nhánh cận rất thô sơ. Nếu
chạy chương trình với trường hợp: số thành phố n=20, khoảng cách giữa các
thành phố bằng 1 (nghĩa là c[i, j]=1 với i<>j). Khi đó chương trình không cho ra
được kết quả vì độ phức tạp rất lớn 20!, không thể chạy trong thời gian cho phép.
Ta nên cải tiến cách đánh giá như sau:
Để đi qua tất cả các thành phố, sau đó quay lại thành phố 1 ta phải đi qua n tuyến
đường (qua tổng cộng n+1 điểm, vì thành phố 1 được tính 2 lần). Giả sử ta đã xây
dựng hành trình đi qua i thành phố với tổng chi phí là sum, ta gọi min là chi phí
của cạnh nhỏ nhất trong các cạnh chưa đi qua. Nếu như sum + (n -i+1)*min
>=best thì ta không nên xây dựng tiếp hành trình từ thành xi nữa mà nên quay lui
để chọn hướng đi khác để hi vọng có được hành trình tốt hơn.
Để dễ dàng khi tìm min trong các cạnh chưa xét, ta xây dựng danh sách cạnh gồm
½ số cạnh nằm phía trên đường chéo chính (i<j) và sắp xếp theo thứ tự tăng dần.
2.2 Bài tập 4.16 (nguồn bài: Tài liệu giáo khoa chuyên tin Q1)
Cho bàn cờ quốc tế 8 x 8 ô, mỗi ô ghi một số nguyên dương không vượt quá
32000. Hãy xếp 8 quân hậu lên bàn cờ sao cho không có quân nào khống chế
được quân nào và tổng các số ghi trên các ô mà quân hậu đứng là lớn nhất.
Input: tệp gồm 8 dòng, mỗi dòng ghi 8 số nguyên dương, giữa các số cách nhau
một dấu cách.
Output: tệp có một số duy nhất là đáp số của bài toán.
Dữ liệu vào Kết quả ra
1 2 4 9 3 2 1 4
6 9 5 4 2 3 1 4
3 6 2 3 4 1 8 3
2 3 7 3 2 1 4 2
1 2 3 2 3 9 2 1
2 1 3 4 2 4 2 8
2 1 3 2 8 4 2 1
8 2 3 4 2 3 1 8
66
Giải
20. Võ Văn Trị - CQB | Confidential
Như đã biết, trên mỗi cột của bàn cờ chỉ đặt được một quân hậu. Để tìm nghiệm
bài toán, ta phải duyệt quay lui:
- Tại bước thứ i, ta chọn một dòng j nào đấy để đặt quân hậu thứ i vào (với điều
kiện dòng j, đường chéo // với đường chéo chính, đường chéo // với đường
chéo phụ đi qua ô đó chưa được đặt một quân hậu nào).
- Tuy nhiên, nếu duyệt tất cả các phương án sau đó tìm cách đặt tốt nhất trong
92 cách đặt thì không khả thi vì chươn g trình sẽ không đảm bảo về mặt thời
gian.
- Giả sử tới bước thứ i, ta đã đặt được i quân hậu với tổng giá trị là sum. Gọi
max[k] là giá trị lớn nhất của các ô chưa bị kiểm soát trên các cột còn lại:
max[k] = max{dk+1, …, dn}
với dh là giá trị lớn nhất của các ô chưa bị kiểm soát trên cột h.
- Khi đó, nếu mở rộng nghiệm theo phương án này thì giá trị lớn nhất có thể đạt
sum + max[k] * (n-i);
- Do vậy, nếu sum + max[k]*(n-i)<= BestSolution thì không cần mở rộng nghiệm
theo hướng này nữa.
2.3 Xếp valy (nguồn bài: spoj)
Một va ly có thể chứa tối đa W đơn vị trọng lượng. Có N loại đồ vật, số lượng
mỗi loại không hạn chế. Loại đồ vật thứ i có trọng lượng Ai và có giá trị Ci. Hỏi
nên chọn những loại đồ vật nào và số lượng bao nhiêu để xếp vào va ly sao cho:
- Tổng trọng lượng của các vật không vượt quá giới hạn W của valy;
- Tổng giá trị của các vật là lớn nhất.
Giải: Với mỗi loại đồ vật i, gọi Ti là giá trị riêng của nó: Ti = Ci / Ai. Sau đó sắp các
loại đồ vật theo thứ tự giảm dần của Ti.
Phương pháp duyệt nhánh cận tại mỗi bước duyệt loại đồ vật i, ta lấy k đồ vật
loạinày, khi đó điều kiện để duyệt tiếp loại đồ vật i+1 (điều kiện nhánh cận) là:
- k*Ai <= w
- s(i) + k*Ci + (w - k*Ai)*Ti+1 > smax
Trong đó:
- w là trọng lượng mà valy có thể chứa thêm sau bước duyệt loại đồ vật i-1;
- s(i) là tổng giá trị hiện đang có của valy sau bước duyệt loại đồ vật i-1;
- smax là tổng giá trị valy của một các xếp đã tìm được nhưng chưa tối ưu. Có
thể khởi tạo smax ban đầu bằng 0.
2. 4 Xâu ABC
Tìm một xâu chỉ gồm các ký tự A,B,C sao cho
21. Page 20 of 84
Võ Văn Trị - CQB | Confidential
- Có độ dài N cho trước (N<=1000)
- Hai đọan con bất kì liên nhau đều khác nhau (đoạn con là một dãy các ký tự
liên tiếp của xâu).
- Có ít ký tự C nhất
Giải (thầy Lê Minh Hoàng):
Thuật toán 1: Ước lượng hàm cận
Ta sẽ dùng thuật toán quay lui để liệt kê các dãy n ký tự mà mỗi phần tử của dãy
được chọn trong tập {A, B, C}. Giả sử cấu hình cần liệt kê có dạng x[1..n] thì:
Nếu dãy x[1..n] thoả mãn 2 đoạn con bất kỳ liền nhau đều khác nhau, thì trong 4 ký
tự liên tiếp bất kỳ bao giờ cũng phải có ít nhất một ký tự ‘C’. Như vậy với một đoạn
gồm k ký tự liên tiếp của dãy x[1..n] thì số ký tự ‘C’ trong đoạn đó luôn ≥ [
4
].
Sau khi thử chọn ∈ { , , , }, nếu ta đã có ký tự ‘C’ trong đoạn x[1..i], thì cho
dù các bước chọn tiếp sau làm tốt như thế nào chăng nữa, số ký tự ‘C’ phải chọn
thêm không bao giờ ít hơn [
−
4
]. Tức là nếu theo phương án chọn như thế này thì
số ký tự ‘C’ trong dãy kết quả (khi chọn đến ) không thể ít hơn + [
−
4
]. Ta dùng
con số này để đánh giá nhánh cận, nếu nó nhiều hơn số ký tự ‘C’ trong cấu hình tốt
nhất đang cho tới thời điểm hiện tại thì chắc chắn có làm tiếp cũng chỉ được một
cấu hình tồi tệ hơn, ta bỏ qua ngay cách chọn này và thử phương án khác.
Thuật toán này hoạt động khá nhanh với ≤ 100, tuy nhiên với những giá trị n lớn
thì thời gian thực hiện vẫn tương đối lâu. Dưới đây là một thuật toán tốt hơn, đi đôi
với nó là một chiến lược chọn hàm cận hiệu quả hơn.
Thuật toán 2: Lấy ngắn nuôi dài
Với mỗi độ dài m, ta gọi f[m] là số ký tự ‘C’ trong dãy thỏa hai đoạn con bất kỳ liền
nhau đều khác nhau và có ít ký tự C nhất. Rõ ràng f[0] = 0, ta lập trình tính các f[m]
khác với điều kiện là f[0..m-1] đã biết.
Tương tự như thuật toán 1, ta giả sử cấu hình cần tìm có dạng x[1..m] thì sau khi
thử chọn xi, nếu ta đã có ti ký tự ‘C’ trong đoạn x[1..i] thì dù cho các bước tiếp sau có
làm tốt thế nào đi chăng nữa, số ký tự ‘C’ chọn thêm sẽ không ít hơn f[m-i], tức là
nếu chọn tiếp thì số ký tự ‘C’ sẽ không ít hơn + [ − ]. Ta dùng cận này kết hợp
với thuật toán quay lui để tìm xâu tốiưu độ dài m.
2.5 Tour du lịch rẻ nhất (TOUR)
Một khu thắng cảnh gồm n điểm đánh số từ 1
tới n (n ≤ 100) và m đường đi hai chiều giữa
các cặp địa điểm đó, chi phí đi trên các đường
đi là biết trước ( ≤ 10000). Một Tour du lịch là
một hành trình xuất phát từ một địa điểm đi
thăm ≥ 2 địa điểm khác và quay trở về điểm
xuất phát, ngoại trừ địa điểm xuất phát, không
địa điểm nào bị thăm tới hai lần. Chi phí của một
22. Võ Văn Trị - CQB | Confidential
Tour du lịch là tổng chi phí các quãng đường đi qua.
Yêu cầu: Hãy tìm Tour du lịch có chi phí rẻ nhất.
Dữ liệu: TOUR.INP
- Dòng 1: Ghi hai số nguyên dương n, m
- m dòng tiếp theo mỗi dòng có dạng x y c. Cho biết có đường đi trực tiếp nối
địa điểm x với địa điểm y và chi phí đi quãng đường đó là c.
Kết quả: TOUR.OUT
- Dòng 1: Ghi số 1 nếu như tồn tại hành trình theo yêu cầu, ghi số 0 nếu không
tồn tại hành trình.
Nếu dòng đầu tiên ghi số 1:
- Dòng thứ 2 ghi chi phí của tour tìm được
- Dòng thứ 3 ghi số k là số địa điểm tới thăm
- Dòng thứ 4 gồm k số, số thứ i là địa điểm tới thăm thứ i trong tour, quy ước
địa điểm thăm đầu tiên là địa điểm xuất phát, địa điểm thăm thứ k (địa
điểm cuối cùng) là địa điểm mà từ đó quay trở lại điểm xuất phát để kết thúc
hành trình.
Các số trên một dòng của Input/Output File được ghi cách nhau ít nhất một dấu
cách.
Ví dụ:
Tour.inp Tour.out
5 10
1 2 10
1 3 2
1 4 2
1 5 9
2 3 9
2 4 2
2 5 2
3 4 10
3 5 2
4 5 8
1
10
5
3 5 2 4 1
2.6 Robot cứu hỏa - VOI 2007 (QBROBOT)
Trên một mạng lưới giao thông có n nút, các nút được đánh số từ 1 đến n và giữa
hai nút bất kỳ có không quá một đường nối trực tiếp (đường nối trực tiếp là một
đường hai chiều). Ta gọi đường đi từ nút s đến nút t là một dãy các nút và các
đường nối trực tiếp có dạng:
s = u1, e1, u2,..., ui, ei, ui+1, ..., uk-1, ek-1, uk = t,
trong đó u1, u2, …, uk là các nút trong mạng lưới giao thông, ei là đường nối trực
tiếp giữa nút ui và ui+1 (không có nút uj nào xuất hiện nhiều hơn một lần trong dãy
trên, j = 1, 2, …, k).
23. Page 22 of 84
Võ Văn Trị - CQB | Confidential
Biết rằng mạng lưới giao thông được xét luôn có ít nhất một đường đi từ nút 1
đến nút n.
Một robot chứa đầy bình với w đơn vị năng lượng, cần đi từ trạm cứu hoả đặt tại
nút 1 đến nơi xảy ra hoả hoạn ở nút n, trong thời gian ít nhất có thể. Thời gian và
chi phí năng lượng để robot đi trên đường nối trực tiếp từ nút i đến nút j tương
ứng là tij và cij (1 ≤ i, j ≤ n). Robot chỉ có thể đi được trên đường nối trực tiếp từ
nút i đến nút j nếu năng lượng còn lại trong bình chứa không ít hơn cij (1 ≤ i, j ≤
n). Nếu robot đi đến một nút có trạm tiếp năng lượng (một nút có thể có hoặc
không có trạm tiếp năng lượng) thì nó tự động được nạp đầy năng lượng vào bình
chứa với thời gian nạp coi như không đáng kể.
Yêu cầu: Hãy xác định giá trị w nhỏ nhất để robot đi được trên một đường đi từ
nút 1 đến nút n trong thời gian ít nhất.
Input
- Dòng đầu tiên chứa một số nguyên dương n (2 ≤ n ≤ 500);
- Dòng thứ hai chứa n số, trong đó số thứ j bằng 1 hoặc 0 tương ứng ở nút j
có hoặc không có trạm tiếp năng lượng (j = 1, 2, …, n);
- Dòng thứ ba chứa số nguyên dương m (m ≤ 30000) là số đường nối trực
tiếp có trong mạng lưới giao thông;
- Dòng thứ k trong số m dòng tiếp theo chứa 4 số nguyên dương i, j, tij, cij (tij,
cij ≤ 10000) mô tả đường nối trực tiếp từ nút i đến nút j, thời gian và chi
phí năng lượng tương ứng.
Hai số liên tiếp trên một dòng trong file dữ liệu cách nhau ít nhất một dấu
cách.
Output
- Ghi ra số nguyên dương w tìm được.
Example
Input: Output:
4
0 1 1 0
5
1 2 5 4
1 3 4 3
1 4 9 4
2 4 4 1
3 4 5 2
3
2. 7 ROADS (nguồn bài: spoj)
Có N thành phố 1..N nối bởi các con đường một chiều. Mỗi con đường có hai giá
trị: độ dài và chi phí phải trả để đi qua. Bob ở thành phố 1. Bạn hãy giúp Bob tìm
24. Võ Văn Trị - CQB | Confidential
đường đi ngắn nhất đến thành phố N, biết rằng Bob chỉ có số tiền có hạn là K mà
thôi.
Dữ liệu
Dòng đầu tiên ghi t là số test. Với mỗi test, dòng đầu ghi K (0 ≤ K ≤ 10000). Dòng
2 ghi N, 2 ≤ N ≤ 100. Dòng 3 ghi R, 1 ≤ R ≤ 10000 là số đường nối. Mỗi dòng trong
N dòng sau ghi 4 số nguyên S, D, L, T mô tả một con đường nối giữa S và D với độ
dài L ( 1 ≤ L ≤ 100) và chi phí T (0 ≤ T ≤ 100). Lưu ý có thể có nhiều con đường
nối giữa hai thành phố.
Kết quả
Với mỗi test, in ra độ dài đường đi ngắn nhất từ 1 đến N mà tổng chi phí không
quá K. Nếu không tồn tại, in ra -1.
Ví dụ
Input: Output:
2
5
6
7
1 2 2 3
2 4 3 3
3 4 2 4
1 3 4 1
4 6 2 1
3 5 2 0
5 4 3 2
0
4
4
1 4 5 2
1 2 1 0
2 3 1 1
3 4 1 0
11
-1
25. Page 24 of 84
Võ Văn Trị - CQB | Confidential
Chuyên đề 3. Duyệt ưu tiên
1. Mã đi tuần
Cho bàn cờ tổng quát nxn và một quân mã (n ≤100). Hãy chỉ ra một hành trình
của mã xuất phát từ ô (x,y), đi qua tất cả các ô còn lại của bàn cờ, mỗi ô đúng
một lần (luật đi của mã như luật cờ vua).
Gợi ý: Nếu xem mỗi ô của bàn cờ là một đỉnh của đồ thị thì bài toán này tương
đương với bài toán tìm đường đi Haminton (đường đi qua tât cả các đỉnh và
qua mỗi đỉnh đúng một lần). Thuật toán duy nhất cho bài toán này là duyệt đệ quy
quaylui.
Tại mỗi bước duyệt, giả sử ta đang ở đỉnh u, từ đỉnh u ta ưu tiên đi sang đỉnh
v có cạnh nối với u mà bậc của v là nhỏ nhất (định nghĩa bậc của một đỉnh v là số
đỉnh nối với đỉnh v đó mà chưa được thăm).
Xét ví dụ trên hình, con mã đang đã đi được 4 bước và đang ở ô (7,G). Từ ô
này con mã có thể nhảy đến 1 trong 3 ô tiếp theo là (6,E) - có bậc là 6; ô (5,F) -
có bậc là 7; hoặc ô (5,H) - có bậc là 3. Con mã sẽ ưu tiên nhảy ô có bậc nhỏ hơn
trước - là ô (5,H).
Sự ưu tiên trong phương pháp duyệt trên giúp chương trình chạy nhanh
hơn rất nhiều so với khi duyệt đơn thuần. Tuy nhiên với trường hợp bài toán
vô nghiệm (không có đường đi Haminton) thì chương trình cũng chạy rất lâu vì
phải duyệt qua hết toàn bộ không gian dữ liệu. Do đó cần dùng thêm biến chặn thời
gian để xử lý trường hợp này.
2. Cặp điểm gần nhất
Trên mặp phẳng tạo độ cho N điểm phân biệt (N≤20000). Tìm 2 điểm mà
khoảng cách giữa chúng là ngắn nhất.
Gợi ý: Nếu duyệt thông thường, thuật toán mất O(N2) và chạy rất lâu với N lớn.
Sự ưu tiên trong phép duyệt sau đây giúp thuật toán chạy trong thời gian cho
phép và cho kết quả chính xác với phần lớn các test.
Ta sắp xếp lại các điểm theo một tiêu chí nào đó có liên quan đến khỏang
Page 24 of 84
Võ Văn Trị - CQB | Confidential
Chuyên đề 3. Duyệt ưu tiên
1. Mã đi tuần
Cho bàn cờ tổng quát nxn và một quân mã (n ≤100). Hãy chỉ ra một hành trình
của mã xuất phát từ ô (x,y), đi qua tất cả các ô còn lại của bàn cờ, mỗi ô đúng
một lần (luật đi của mã như luật cờ vua).
Gợi ý: Nếu xem mỗi ô của bàn cờ là một đỉnh của đồ thị thì bài toán này tương
đương với bài toán tìm đường đi Haminton (đường đi qua tât cả các đỉnh và
qua mỗi đỉnh đúng một lần). Thuật toán duy nhất cho bài toán này là duyệt đệ quy
quaylui.
Tại mỗi bước duyệt, giả sử ta đang ở đỉnh u, từ đỉnh u ta ưu tiên đi sang đỉnh
v có cạnh nối với u mà bậc của v là nhỏ nhất (định nghĩa bậc của một đỉnh v là số
đỉnh nối với đỉnh v đó mà chưa được thăm).
Xét ví dụ trên hình, con mã đang đã đi được 4 bước và đang ở ô (7,G). Từ ô
này con mã có thể nhảy đến 1 trong 3 ô tiếp theo là (6,E) - có bậc là 6; ô (5,F) -
có bậc là 7; hoặc ô (5,H) - có bậc là 3. Con mã sẽ ưu tiên nhảy ô có bậc nhỏ hơn
trước - là ô (5,H).
Sự ưu tiên trong phương pháp duyệt trên giúp chương trình chạy nhanh
hơn rất nhiều so với khi duyệt đơn thuần. Tuy nhiên với trường hợp bài toán
vô nghiệm (không có đường đi Haminton) thì chương trình cũng chạy rất lâu vì
phải duyệt qua hết toàn bộ không gian dữ liệu. Do đó cần dùng thêm biến chặn thời
gian để xử lý trường hợp này.
2. Cặp điểm gần nhất
Trên mặp phẳng tạo độ cho N điểm phân biệt (N≤20000). Tìm 2 điểm mà
khoảng cách giữa chúng là ngắn nhất.
Gợi ý: Nếu duyệt thông thường, thuật toán mất O(N2) và chạy rất lâu với N lớn.
Sự ưu tiên trong phép duyệt sau đây giúp thuật toán chạy trong thời gian cho
phép và cho kết quả chính xác với phần lớn các test.
Ta sắp xếp lại các điểm theo một tiêu chí nào đó có liên quan đến khỏang
Page 24 of 84
Võ Văn Trị - CQB | Confidential
Chuyên đề 3. Duyệt ưu tiên
1. Mã đi tuần
Cho bàn cờ tổng quát nxn và một quân mã (n ≤100). Hãy chỉ ra một hành trình
của mã xuất phát từ ô (x,y), đi qua tất cả các ô còn lại của bàn cờ, mỗi ô đúng
một lần (luật đi của mã như luật cờ vua).
Gợi ý: Nếu xem mỗi ô của bàn cờ là một đỉnh của đồ thị thì bài toán này tương
đương với bài toán tìm đường đi Haminton (đường đi qua tât cả các đỉnh và
qua mỗi đỉnh đúng một lần). Thuật toán duy nhất cho bài toán này là duyệt đệ quy
quaylui.
Tại mỗi bước duyệt, giả sử ta đang ở đỉnh u, từ đỉnh u ta ưu tiên đi sang đỉnh
v có cạnh nối với u mà bậc của v là nhỏ nhất (định nghĩa bậc của một đỉnh v là số
đỉnh nối với đỉnh v đó mà chưa được thăm).
Xét ví dụ trên hình, con mã đang đã đi được 4 bước và đang ở ô (7,G). Từ ô
này con mã có thể nhảy đến 1 trong 3 ô tiếp theo là (6,E) - có bậc là 6; ô (5,F) -
có bậc là 7; hoặc ô (5,H) - có bậc là 3. Con mã sẽ ưu tiên nhảy ô có bậc nhỏ hơn
trước - là ô (5,H).
Sự ưu tiên trong phương pháp duyệt trên giúp chương trình chạy nhanh
hơn rất nhiều so với khi duyệt đơn thuần. Tuy nhiên với trường hợp bài toán
vô nghiệm (không có đường đi Haminton) thì chương trình cũng chạy rất lâu vì
phải duyệt qua hết toàn bộ không gian dữ liệu. Do đó cần dùng thêm biến chặn thời
gian để xử lý trường hợp này.
2. Cặp điểm gần nhất
Trên mặp phẳng tạo độ cho N điểm phân biệt (N≤20000). Tìm 2 điểm mà
khoảng cách giữa chúng là ngắn nhất.
Gợi ý: Nếu duyệt thông thường, thuật toán mất O(N2) và chạy rất lâu với N lớn.
Sự ưu tiên trong phép duyệt sau đây giúp thuật toán chạy trong thời gian cho
phép và cho kết quả chính xác với phần lớn các test.
Ta sắp xếp lại các điểm theo một tiêu chí nào đó có liên quan đến khỏang
26. Võ Văn Trị - CQB | Confidential
cách. Chẳng hạn lấy thêm một điểm bất kì nằm ngoài tập điểm và sắp lại N
điểm đã cho theo thứ tự tăng (giảm) dần khoảng cách đến điểm này. Hay
sắp tăng (giảm) N điểm theo hoành độ x. Hay sắp tăng (giảm) N điểm theo tung
độ y…
Sau khi sắp xếp như vậy, với mỗi điểm i, ta ưu tiên xét các điểm j trong không
gian lân cận với nó trước - tức là những điểm gần điểm i trong danh sách đã
sắp xếp. độ rộng của không gian lân cận (có thể gọi là không gian tìm kiếm) do
ta tự quy định, không gian xét càng rộng thì độ chính xác của chương trình càng
cao nhưngthời gian chạy càng lâu.
Ví dụ với N=20000. sau khi sắp xếp lại ta đươc dãy các điểm i1, i2, … , i20000.
với mỗi điểm ik, nếu ta quy định không gian tìm kiếm là 100 thì ta chỉ xét khoảng
cách của ik với các điểm ik+1, ik+2, …, ik+100.
Việc sắp xếp các điểm và chọn không gian tìm kiếm hợp lý sẽ giúp chương trình có
độ tin cậy cao và chạy trong thời gian cho phép.
Chú ý: Bài toán trên còn có thuật giải độ phức tạp NlogN tuy nhiên khá
phức tạp và không được nói ở đây.
Bài tập luyện tập
3.1 Phòng cháy (FIRE)
Để đối phó với tình hình biến động của giá xăng dầu, nước X quyết định xây
dựng một kho dự trữ dầu với quy mô cực lớn. Kho chứa dầu sẽ bao gồm N bể
chứa dầu hình trụ tròn mà ta sẽ biểu diễn trên bản đồ bằng N hình tròn, hình
tròn thứ i có tọa độ là (Xi, Yi) và bán kính Ri, các hình tròn không có điểm chung
trong với nhau (nhưng có thể tiếp xúc).
Để đảm bảo an toàn phòng cháy chữa cháy, người ta cần xác định 2 bể chứa dầu
gần nhau nhất để tăng cường cách ly khi xảy ra hỏa hoạn.
Biết rằng khoảng cách giữa 2 bể chứa dầu thứ i và thứ j chính bằng khoảng cách
giữa 2 đường tròn tương ứng và bằng Dij - Ri - Rj, trong đó Dij là khoảng cách
giữa 2 điểm (Xi, Yi) và (Xj, Yj).
Bạn hãy giúp những người quản lý tìm ra 2 bể chứa dầu này.
Dữ liệu: FIRE.INP
- Dòng thứ nhất ghi số nguyên dương N là số bể chứa dầu.
- Dòng thứ i trong N dòng tiếp theo ghi 3 số nguyên Xi, Yi, Ri là tọa độ và bán
kính bể chứa dầu thứ i.
Kết quả: FIRE.OUT
- Gồm 1 dòng duy nhất là khoảng cách của 2 bể chứa dầu bé nhất tìm được.
Giới hạn:
27. Page 26 of 84
Võ Văn Trị - CQB | Confidential
- 2 ≤ N ≤ 10000.
- |Xi|, |Yi| ≤ 106.
- 0 < Ri ≤ 106.
- Kết quả ghi chính xác đến 4 chữ số sau dấu phẩy.
Ví dụ:
Fire.inp Fire.out
3
0 0 1
4 0 2
5 5 3
0.0990
28. Võ Văn Trị - CQB | Confidential
Chuyên đề 4. Tìm kiếm nhị phân
1. Dãy con tăng dài nhất (bản khó) - Mã bài: LIS
(Giống bài LIQ) Cho một dãy gồm N số nguyên (1 ≤ N ≤ 30000). Hãy tìm dãy con
tăng dài nhất trong dãy đó. In ra số lượng phần tử của dãy con. Các số trong phạm
vi longint.
Input
- Dòng đầu tiên gồm số nguyên N.
- Dòng thứ hai gồm N số mô tả dãy.
Output
- Gồm một số nguyên duy nhất là đáp số của bài toán
Example
Input Output
5
2 1 4 3 5
3
2. Phân công hoàn thành sớm nhất - Mã bài: ASSIGN1
Có n người, n việc (1 < n ≤ 200). Người thứ i thực hiện công viêc j mất C[i,j] đơn vị
thời gian. Giả sử tất cả bắt đầu vào thời điểm 0, hãy tìm cách bố trí mỗi công việc
cho mỗi người sao cho thời điểm hoàn thành công việc là sớm nhất có thể.
Input
- Dòng đầu: N
- Tiếp theo là ma trận C[i,j]. (thuộc kiểu Integer)
Output
- Ghi thời điểm sớm nhất hoàn thành.
Example
Input Output
4
10 10 10 2
10 10 3 10
4 10 10 10
10 5 10 10
5
3. Yugi-Oh - Problem code: YUGI
29. Page 28 of 84
Võ Văn Trị - CQB | Confidential
Các bạn đã đọc bộ truyện tranh Nhật Bản Yugi-oh chắc hẳn ai cũng cực kì yêu
thích trò chơi bài Magic. Bộ bài và chiến thuật chơi quyết định đến sự thắng thua
của đối thủ(mà sự thắng thua thì còn liên quan đến cả tính mạng >_<). Vì thế tầm
quan trọng của bộ bài là rất lớn. Một bộ bài tốt không chỉ bao gồm các quân bài
mạnh mà còn phụ thuộc vào sự hỗ trợ tương tác giữa các quân bài. Bộ bài của
Yugi là một bộ bài có sự bổ sung, hỗ trợ cho nhau rất tốt, điều này là 1 trong các
nguyên nhân khiến Kaiba luôn là kẻ chiến bại.
Tình cờ Kaiba đã tìm được 1 quân bài ma thuật mà chức năng của nó là chia bộ
bài hiện có của đối thủ ra làm K phần, mỗi phần có ít nhất 1 quân bài (điều này
làm giảm sức mạnh của đối thủ). Kaiba quyết định áp dụng chiến thuật này với
Yugi. Hiện tại Yugi có trong tay N quân bài, 2 quân bài i, j có sức mạnh tương tác
a(i,j) (a(i,j) = a(j,i)). Kaiba muốn chia các quân bài thành K phần theo quy tắc sau:
Giả sử K phần là P1, P2, ..., Pk thì độ giảm sức mạnh giữa 2 phần u,v là
b(u,v) = min(a(i,j) với i thuộc Pu, j thuộc Pv).
Độ giảm sức mạnh của bộ bài là S = min(b(u,v) với 1 ≤ u, v ≤ K).
Kaiba muốn chia K phần sao cho S lớn nhất
Input
- Dòng đầu là 2 số N,K(2 ≤ K ≤ N ≤ 200)
- N dòng tiếp theo mỗi dòng là N số a(i,j) (a(i,j) ≤ 32767; nếu i = j thì a(i,j) =
0)
Output
- Gồm 1 dòng duy nhất là S lớn nhất
Example
Input Output
4 3
0 1 2 3
1 0 2 3
2 2 0 3
3 3 3 0
2
4. Mountain Walking - Mã bài: MTWALK
Cho một bản đồ kích thước NxN (2 <= N <= 100), mỗi ô mang giá trị là độ cao của
ô đó (0 <= độ cao <= 110). Bác John và bò Bessie đang ở ô trên trái (dòng 1, cột 1)
và muốn đi đến cabin (dòng N, cột N). Họ có thể đi sang phải, trái, lên trên và
xuống dưới nhưng không thể đi theo đường chéo. Hãy giúp bác John và bò Bessie
tìm đường đi sao cho chênh lệch giữa điểm cao nhất và thấp nhất trên đường đi là
nhỏ nhất.
Dữ liệu
- Dòng 1: N
- Dòng 2..N+1: Mỗi dòng chứa N số nguyên, mỗi số cho biết cao độ của một ô.
30. Võ Văn Trị - CQB | Confidential
Kết quả
- Một số nguyên là chênh lệch cao độ nhỏ nhất.
Ví dụ
Input Output
5
1 1 3 6 8
1 2 2 5 5
4 4 0 3 3
8 0 2 3 4
4 3 0 2 1
2
31. Page 30 of 84
Võ Văn Trị - CQB | Confidential
Chuyên đề 5. Xử lý bit
I. Cơ sở lý thuyết
Trong máy tính, các số nguyên được biểu diễn bởi một dãy k bit, được đánh số từ phải
sang trái, bắt đầu từ 0. Ví dụ, một số kiểu byte được thể hiện bởi 8 bit như sau:
0 0 0 0 1 0 1 0
7 6 5 4 3 2 1 0
Ví dụ trên thể hiện số 10 của kiểu byte. Đối với số nguyên có dấu (integer,
longint) bit cao nhất dùng làm bit dấu (bit dấu = 0 là số dương, bit dấu =1
là số âm), các bit còn lại ghi nhận giá trị. Ví dụ, số 12 trong kiểu integer được
thể hiện bởi 16 bit như sau:
0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Tuy nhiên, có điều đặc biệt đối với số âm. Bit cao nhất vẫn là bit dấu, các bit còn lại
không phải ghi nhận |a| mà ghi nhận giá trị 32768 - |n| (đối với kiểu integer). Do
đó số -12 trong kiểu integer được thể hiện bởi 16 bit như sau:
1 1 1 1 1 1 1 1 1 1 1 1 0 1 0 0
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Ta có thể so sánh với 32768-12=32756:
0 1 1 1 1 1 1 1 1 1 1 1 0 1 0 0
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Đối với kiểu nguyên, bên cạnh các phép toán số học, ta còn có các phép toán logic
(and, or, not, xor) và phép dịch chuyển bit (shl – dịch sang trái, shr – dịch
sang phải).
1. Các phép toán logic
Với 2 biến nguyên cùng kiểu a, b được thể hiện bởi dãy k bit:
: . ..
: . ..
a. Phép đảo bit (not): đảo tất cả các bit từ 0 thành 1, 1 thành 0.
not(a) -> ta sẽ được số : . .. với ci = 0 nếu ai = 1, ci = 1 nếu ai = 0.
Ví dụ: not(10) = 245 (11110101);
Theo cách biểu diễn của số âm, ta có thể nhận thấy not(a) = -(a+1);
Ví dụ: not(-12) = 11 (1011)
b. Phép cộng logic (or): thực hiện trên từng cặp bit của 2 số, kết quả bằng 0 khi cả 2
bit đều bằng 0, còn lại bằng 1:
bit ai bit bi ai or bi
32. Võ Văn Trị - CQB | Confidential
0 0 0
0 1 1
1 0 1
1 1 1
c. Phép nhân logic (and): thực hiện trên từng cặp bit của 2 số, kết quả bằng 1 khi cả 2
bit đều bằng 1, còn lại bằng 0:
bit ai bit bi ai and bi
0 0 0
0 1 0
1 0 0
1 1 1
d. Phép xor (xor): thực hiện trên từng cặp bit của 2 số, kết quả bằng 1 khi cả 2 bit
bằng nhau, còn lại bằng 0:
bit ai bit bi ai xor bi
0 0 1
0 1 0
1 0 0
1 1 1
2. Phép dịch chuyển bit
a) Phép dịch trái (shl – shift left):
Ý nghĩa: dịch dãy bit biểu diễn số nguyên a sang trái k vị trí, các vị trí bị dịch đi được
thay bằng bit 0, các bit ra khỏi phạm vi xem như không xuất hiện trong dãy mới.
b) Phép dịch phải (shr – shift right):
Ý nghĩa: dịch dãy bit biểu diễn số nguyên a sang phải k vị trí, các vị trí bị dịch đi được
thay bằng bit 0, các bit ra khỏi phạm vi xem như không xuất hiện trong dãy mới.
3. Một số thao tác xử lý bit
a. Hàm cho ra bit thứ i của số nguyên n
b. Hàm cho ra số nguyên m tạo ra bằng cách lấy k bit, bit thứ i đến bít thứ j của số
nguyên n
function getbit(n:int; i:byte):byte;
begin
getbit := (n shr i) and 1;
end;
33. Page 32 of 84
Võ Văn Trị - CQB | Confidential
c. Thủ tục bật bit thứ i của số nguyên n (gán giá trị 1 cho bit thứ i):
d. Thủ tục tắt bit thứ i của số nguyên n (gán giá trị 0 cho bit thứ i):
II. Bài tập
1. Số đặc biệt (SNUM)
Cho dãy N số tự nhiên có giá trị trong đoạn [0,65535] (N<=1000000). Trong đó
chỉ có một số xuất hiện 1 lần - gọi là số đặc biệt, các số còn lại có số lần xuất hiện
là một số chẵn. Yêu cầu tìm ra số đặc biệt này.
Dữ liệu: SNUM.INP
- Dòng đầu tiên ghi giá trị N
- N dòng tiếp theo, mỗi dòng ghi một số trong dãy N số
Kết quả: SNUM.OUT
- Số đặc biệt tìm được
Ví dụ:
Snum.inp Snum.out
procedure tatbit(var n:int; i:byte);
var m:int;
begin
m := 1;
m := not(m shl i);
n:= n and m;
end;
procedure batbit(var n:int; i:byte);
var m:int;
begin
m := 1;
m := m shl i;
n:= n or m;
end;
function getnum(n:int; i,j:byte):int;
begin
n := n shl (sizeof(n)*8-(j+1));
getnum := n shr (sizeof(n)*8-(j+1)+i);
end;
34. Võ Văn Trị - CQB | Confidential
12345
9876
12345
145
9876
145
Giải:
* Cách 1:
Xếp N số tự nhiên này lên N và dồn các số này về phía bên phải:
1 2 3 4 5
9 8 7 6
1 2 3 4 5
1 4 5
9 8 7 6
Bây giờ ta xét theo từng cột của bảng số và bỏ đi những chữ số có số lần xuất hiện
là số chẵn: Cột 1 bỏ chữ số 1, Cột 2 bỏ chữ số 2 và 9, …Sau khi bỏ, các cột còn lại
chữ số có số lần xuất hiện là một số lẻ chính là số đặc biệt cần tìm.
Cụ thể, ta sử dụng một mảng 2 chiều có kích thước 6 × 10 để ghi số lần xuất hiện
của các chữ số trên mỗi cột:
0 1 2 3 4 5 6 7 8 9
Cột 1 0 0 0 0 0 3 2 0 0 0
Cột 2 0 0 0 0 3 0 0 2 0 0
Cột 3 0 1 0 2 0 0 0 0 2 0
Cột 4 0 0 2 0 0 0 0 0 0 2
Cột 5 0 2 0 0 0 0 0 0 0 0
Cột 6 0 0 0 0 0 0 0 0 0 0
Cách làm này khá hay, độ phức tạp là O(6xn), chương trình sẽ chạy chậm với n
lớn.
* Cách 2:
35. Page 34 of 84
Võ Văn Trị - CQB | Confidential
Ta cũng sử dụng tư tưởng trên nhưng không tách riêng các số ra. Ta biết rằng mọi
số kiểu word đều sử dụng 16 bit để biểu diễn. Ta sử dụng phép XOR để loại trừ
những bit có số lần xuất hiện là số chẵn. Những bit còn lại là của số đặc biệt cần
tìm.
2. Bàn cờ thế (CHESSCBG)
Một bàn cờ thế là một bảng gồm 4 dòng, 4 cột. Mỗi thế cờ là một cách sắp xếp
8 quân cờ, hai quân khác nhau ở hai ô khác nhau. Bài toán đặt ra là cho hai thế
cờ 1 và 2, hãy tìm một số ít nhất bước di chuyển quân để chuyển từ thế 1 sang
thế 2; một bước di chuyển quân là một lần chuyển quân cờ sang ô trống kề cạnh với
ô quân cờ đang đứng.
Dữ liệu: CHESSCBG.INP
- Gồm 8 dòng, mỗi dòng là một xâu nhị phân độ dài 4 mà số 1/0 tương ứng
với vị trí có hoặc khôngcó quân cờ.
- Bốn dòng đầu là thế cờ 1
- Bốn dòng sau là thế cờ 2.
Kết quả: CHESSCBG.OUT
- Gồm 1 dòng duy nhất là số bước chuyển quân ít nhất
Ví dụ:
Chesscbg.inp Chesscbg.out
1111
0000
1110
0010
1010
0101
1010
0101
Giải: Mã hóa mỗi trạng thái bàn cờ bằng 1 dãy nhị phân 16 bit tương ứng.
Sử dụng phương pháp loang để tìm đường đi ngắn nhất từ trạng thái đầu về trạng
thái cuối.
Bài tập luyện tập
5.1 Mê cung (MECUNG)
Một mê cung hình chữ nhật gồm M dòng và N cột ô vuông, M,N <= 100. Các dòng
(cột) đánh số từ 1 đên M ( từ 1 đến N) từ trên xuống (từ trái qua phải). Một
robot đứng ở ô (X,Y). Từ một ô bất kì, robot có thể di chuyển đến 1 trong 4 ô
kề cạnh. Mỗi ô của mê cung ứng với 1 số trong phạm vi 0..15 với ý nghĩa quy
định những hướng robot có thể di chuyển đến. Mỗi hướng được quy định bởi
1 số hiệu: Trên: 1; Dưới: 2; Phải: 4; Trái: 8. Giá trị của ô bằng tổng các số hiệu các
hướng mà robot có thể di chuyển đến. VD ô (2,3) có giá trị 13 = 1 + 4 + 8 có nghĩa
36. Võ Văn Trị - CQB | Confidential
là từ ô (2,3) có thể di chuyển theo hướng trên, phải hay trái để sang ô kề cạnh tiếp
theo.
Yêu cầu: Tìm đường đi ngắn nhất để robot có thể thoát ra được mê cung.
Dữ liệu: MECUNG.INP
- Dòng đầu tiên ghi 4 số M,N,X,Y
- Tiếp theo ma trận số M dòng, mỗi dòng N cột biểu diễn thông tin về mê cung.
Kết quả: MECUNG.OUT
- Số bước di chuyển ít nhất để robot thoát ra khỏi mê cung
5.2 Chuyến du lịch (TRIP)
Trong kì nghỉ hè năm nay sherry được bố thưởng cho 1 tour du lịch quanh N
đất nước tươi đẹp với nhiều thắng cảnh nổi tiếng (vì sherry rất ngoan). Tất
nhiên sherry sẽ đi bằng máy bay.
Giá vé máy bay từ đất nước i đến đất nước j là Cij (dĩ nhiên Cij có thể khác
Cji). Tuy được bố thưởng cho nhiều tiền để đi du lịch nhưng sherry cũng muốn
tìm cho mình 1 hành trình với chi phí rẻ nhất có thể để dành tiền mua quà
về tặng mọi người (Các chuyến bay của sherry đều được đảm bảo an toàn tuyệt
đối ).
Bạn hãy giúp sherry tìm 1 hành trình đi qua tất cả các nước, mỗi nước đúng 1
lần sao cho chi phí là bé nhất nhé.
Dữ liệu: TRIP.INP
- Dòng 1: N (5 < N < 16)
- Dòng thứ i trong N dòng tiếp theo: Gồm N số nguyên, số thứ j là Cij (0 <
Cij <10001)
Kết quả: TRIP.OUT gồm 1 dòng duy nhất ghi chi phí bé nhất tìm được
Ví dụ:
Trip.inp Trip.out
6
0 1 2 1 3 4
5 0 3 2 3 4
4 1 0 2 1 2
4 2 5 0 4 3
2 5 3 5 0 2
5 4 3 3 1 0
8
Gợi ý: Gọi F[i,x] là chi phí ngắn nhất khi đang ở đất nước i và các đất nước đã
đi qua được đánh dấu bằng dãy bit của biến x. Sử dụng tư tưởng quy hoạch động
giải quyết.
37. Page 36 of 84
Võ Văn Trị - CQB | Confidential
QUY HOẠCH ĐỘNG
Phương pháp quy hoạch động cùng nguyên lý tối ưu được nhà toán học Mỹ
Richard Ernest Bellman (26/8/1920 – 19/3/1984) đề xuất ra vào những năm 50
của thế kỉ 20. Phương pháp này được sử dụng để giải hàng loạt bài toán thực tế
trong kỹ thuật, sản xuất, kinh tế…
Tư tưởng của phương pháp quy hoạch động là sử dụng một bảng để lưu giữ
lời giải của các bài toán con đã được giải. Khi giải một bài toán cần đến
nghiệm của bài toán con nhỏ hơn, ta chỉ cần lấy lời giải ở bảng mà không cần
phải giải lại. Quy hoạch động tránh tính toán lại mọi thứ hai lần chính vì thế mà
các thuật toán được thiết kế bằng quy hoạch động sẽ rất hiệu quả.
Để giải một bài toán bằng phương pháp quy hoạch động, chúng ta cần tiến hành
những công việc sau:
- Tìm nghiệm của bài toán con nhỏ nhất.
- Tìm ra công thức xây dựng nghiệm của bài toán lớn thông qua nghiệm của
các bài toán con nhỏ hơn.
- Tạo ra một bảng lưu giữ các nghiệm của các bài toán con.
- Từ các bài toán con đã giải ta tìm nghiệm của bài toán tổng quát.
KL: Quy hoạch động bắt đầu với những trường hợp con nhỏ nhất (thường là đơn
giản và giải được ngay ). Bằng cách tổ hợp các kết quả đã có (không phải tính lại)
của các trường hợp con, sẽ đạt tới kết quả của trường hợp có kích thước lớn hơn
và tổng quát hơn, cho đến khi đạt được kết quả cuối cùng ( lời giải).
Chuyên đề 6. Quy hoạch động cơ bản
1. Cửa hàng bán hoa (IOI 1999)
Bạn muốn sắp đặt cửa sổ hiệu bán hoa của mình sao cho hấp dẫn nhất. Bạn có f
bó hoa, mỗi bó một loại khác nhau và số bó hoa không nhiều hơn số bình hoa sắp
sẵn thành một hàng trên cửa sổ. Các bình hoa được gắn cố định và được đánh số
liên tục từ 1 đến V, trong đó V là số bình, theo thứ tự từ trái sang phải sao cho
bình 1 là bên trái nhất còn bình V là bên phải nhất. Mỗi bó hoa được cắm gán một
số nguyên duy nhất có giá trị trong khoảng từ 1 đến f và có thể cắm vào các bình
khác nhau. Số hiệu của bó hoa có ý nghĩa như sau: bó hoa i phải nằm bên trái bó
hoa j trong dãy các bình hoa nếu i<j. Ví dụ, ta có một bó hoa đỗ quyên (có số hiệu
là 1), một bó hoa thu hải đường (có số hiệu là 2) và một bó hoa cẩm chướng (có
số hiệu 3). Bây giờ, tất cả các bó hoa phải được cắm vào dãy các bình hoa sao cho
bảo đảm ràng buộc về thứ tự số hiệu. Bó hoa đỗ quyên phải được cắm vào bình
phía bên trái bó hoa thu hải đường, bó hoa thu hải đường phải được cắm vào bên
trái của bình hoa cẩm chướng. Nếu số bình hoa nhiều hơn số bó hoa thì những
bình không dùng tới sẽ để trống. Mỗi bình chỉ được cắm một bó hoa.
38. Võ Văn Trị - CQB | Confidential
Mỗi bình hoa có đặc điểm khác nhau. Vì vậy, khi một bó hoa được cắm vào
bình sẽ có một giá trị thẩm mĩ nhất định, được biểu diễn bởi một số nguyên. Các
giá trị thẩm mĩ được cho trong bảng dưới đây:
Hoa
Bình hoa
1 2 3 4 5
1 – Đỗ quyên 7 23 -5 -24 6
2 – Thu hải đường 5 21 -4 10 23
3 – Cẩm chướng -21 5 -4 -20 20
Để nhận được hiệu quả thẩm mĩ tốt nhất, bạn phải tìm cách cắm các bó hoa
vào bình tuân theo ràng buộc thứ tự sao cho tổng các giá trị thẩm mĩ là lớn nhất.
Nếu có nhiều cách cắm có cùng giá trị thẩm mĩ thì chỉ cần nếu một cách cắm (và
chỉ đúng một cách mà thôi).
Giả thiết:
- 1 <= f <= 100, trong đó f là số bó hoa;
- f <= v <= 100, trong đó v là số bình hoa;
- -50 <= aij <= 50, trong đó là giá trị thẩm mĩ đạt được khi cắm bó hoa i vào
bình j.
Dữ liệu: từ tệp văn bản FLOWER.INP có cấu trúc:
- Dòng 1: ghi hai số nguyên f và v;
- f dòng tiếp theo: mỗi dòng chứa v số nguyên sao cho aij là số thứ j trên dòng
thứ i+1.
Kết quả: ghi vào tệp văn bản FLOWER.OUT có cấu trúc:
- Dòng 1: ghi tổng giá trị thẩm mĩ của phương án cắm hoa tối ưu;
- Dòng 2: biểu diễn cách cắm là danh sách f số, sao cho số ở vị trí thứ k trong
danh sách này cho biết số hiệu bình hoa.
Ví dụ:
FLOWER.INP FLOWER.OUT
3 5
7 23 -5 -24 16
4 21 -4 10 23
-21 5 -4 -20 20
53
2 4 5
Tải bản FULL (84 trang): bit.ly/2Ywib4t
39. Page 38 of 84
Võ Văn Trị - CQB | Confidential
Giải: Gọi S[i, j] là tổng giá trị thẩm mĩ khi cắm i bó hoa (1..i) vào j bình (1..j):
− Nếu i > j (số bó hoa nhiều hơn số bình): không có cách cắm => s[i, j] = 0;
− Nếu i = j (số bó hoa = số bình): chỉ có một cách cắm duy nhất, bó hoa có số
hiệu nào cắm vào bình có số hiệu ấy => s[i, j] = ∑a[i, j];
− Nếu i < j (số bó hoa ít hơn số bình): ta xét hai trường hợp, bình cuối cùng j có
thể được cắm bó hoa cuối cùng i hoặc không.
+ Nếu bó hoa i cắm bình j thì s[i, j] = s[i-1, j-1] + a[i, j];
+ Nếu bó hoa i không cắm vào bình j thì s[i, j] = s[i, j-1];
=> Nếu i < j: s[i, j] = max{ s[i-1, j-1] + a[i, j], s[i, j-1] }
2. Mua vé tàu hoả - Mã bài: QBTICKET
Tuyến đường sắt từ thành phố A đến thành phố B đi qua một số nhà ga. Tuyến
đường có thể biểu diễn bởi một đoạn thẳng, các nhà ga là các điểm trên đó. Tuyến
đường bắt đầu từ A và kết thúc ở B, vì thế các nhà ga sẽ được đánh số bắt đầu từ
A (có số hiệu là 1) và B là nhà ga cuối cùng.
Giá vé đi lại giữa hai nhà ga chỉ phụ thuộc vào khoảng cách giữa chúng. Cách tính
giá vé như sau:
Khoảng cách giữa hai nhà ga (X)
Khoảng cách 0 < X <= L1 -> Giá vé C1
Khoảng cách 0 < X <= L2 -> Giá vé C2
Khoảng cách 0 < X <= L3 -> Giá vé C3
Nghĩa là với các giá vé C1, C2, C3 tương ứng bạn sẽ đi quảng đường tối đa là L1,
L2, L3.
Vé để đi thẳng từ nhà ga này đến nhà ga khác chỉ có thể đặt mua nếu khoảng cách
giữa chúng không vượt quá L3. Vì thế nhiều khi để đi từ nhà ga này đến nhà ga
khác ta phải đặt mua một số vé. Hơn thế nữa, nhân viên đường sắt yêu cầu hành
khách chỉ được giữ đúng một vé khi đi trên tàu và vé đó sẽ bị huỷ khi hành khách
xuống tàu.
Yêu cầu: Tìm cách đặt mua vé để đi lại giữa hai nhà ga cho trước với chi phí mua
vé là nhỏ nhất
Input
- Dòng đầu tiên ghi các số nguyên L1, L2, L3, C1, C2, C3 (1 <= L1 <= L2 <= L3 <=
109; 1 <= C1 <= C2 <= C3 <= 109) theo đúng thứ tự liệt kê ở trên.
- Dòng thứ hai chứa số lượng nhà ga N ( 2 <= N <= 100000 )
40. Võ Văn Trị - CQB | Confidential
- Dòng thứ ba ghi hai số nguyên s, f là các chỉ số của hai nhà ga cần tìm cách đặt
mua vé với chi phí nhỏ nhất để đi lại giữa chúng.
- Dòng thứ i trong số N - 1 dòng tiếp theo ghi số nguyên là khoảng cách từ nhà
ga A (ga 1) đến nhà ga thứ i + 1.
Output
- Gồm 1 dòng duy nhất ghi chi phí nhỏ nhất tìm được
Example
Input Output
3 6 8 20 30 40
7
2 6
3
7
8
13
15
23
70
Giải:
- Tổ chức dữ liệu:
o Mảng [1. . ]: [ ] lưu khoảng cách từ ga A (đánh số 1) đến ga i (ga
B đánh số n).
o Mảng [1. .3]: lưu 3 khoảng cách L1, L2, L3.
o Mảng [1. .3]: lưu 3 loại giá vé c1, c2, c3.
- Gọi [ ] là chi phí tốt nhất để đi từ ga s tới ga i => kết quả của bài toán là
[ ].
- Ta có F[s] = 0;
- [ ] = min { [ ] + : [ ] − [ ] ≤ [3]}
Trong đó: =
[1] [ ] − [ ] ≤ [1]
[2] [1] < [ ] − [ ] ≤ [2]
[3] [2] < [ ] − [ ] ≤ [3]
- Ví dụ:
1 2 3 4 5 6 7
d 0 3 7 8 13 15 23
1 2 3 1 2 3
L 3 6 8 C 20 30 40
41. Page 40 of 84
Võ Văn Trị - CQB | Confidential
S = 2; ft = 6
Ta có mảng f như sau:
1 2 3 4 5 6 7
F 0 0 30 30 60 70
Vậy đáp án cần tìm là 70.
3. Tách Từ - Mã bài: NKH
Hệ điều hành XP cho phép điều khiển cùng một lúc hai bàn phím. Hai anh em
Tuấn và Nam vừa được thưởng một máy tính mới nên rất muốn thử tính năng
này của XP. Tuấn và Nam, mỗi người dùng một bàn phím và đồng thời gõ vào một
chuỗi ký tự đang nghĩ trong đầu tương ứng là S1 và S2. Do gõ đồng thời và tốc độ
gõ khác nhau nên kết quả là trên màn hình hiện ra một chuỗi ký tự S là kết hợp
của các ký tự trong S1 và S2. Các ký tự này đan xen nhau theo một trình tự nào đó
khiến Tuấn và Nam không còn nhận ra ký tự nào mình đã gõ.
Yêu cầu: Hãy giúp Tuấn và Nam xác định những ký tự nào có thể là của mình theo
nghĩa nếu tách những ký tự đó ra và ghép lại theo đúng thứ tự thì ta nhận được
đúng từ mà Tuấn và Nam đã gõ.
Dữ liệu: Dữ liệu vào từ file văn bản TACHTU.INP gồm 3 dòng, trong đó:
- Dòng đầu tiên chứa từ S1 do Tuấn đã gõ.
- Dòng thứ hai chứa từ S2 do Nam đã gõ.
- Dòng cuối cùng chứa chuỗi S.
S1 và S2 chỉ chứa các chữ cái Latin thường (a, b, c …. z) và số lượng ký tự trong
mỗi chuỗi không vượt quá 125.
Kết quả: Kết quả ghi ra file văn bản TACHTU.OUT chỉ có một dòng duy nhất chứa
chuỗi ký tự có chiều dài bằng chiều dài chuỗi S, trong đó ký tự thứ I sẽ bằng ký tự
‘1’ nếu ký tự tương ứng S[1] do Tuấn gõ và bằng ‘2’ nếu S[1] do Nam gõ. Trong
trường hợp có nhiều hơn một khả năng chỉ cần ghi một trong các khả năng đó.
Ví dụ:
TACHTU.INP TACHTU.OUT
papa
mama
mpapamaa
21112212
Giải: Bài toán này thực chất là bài toán dãy con chung lớn nhất.
- Đặt k = length(s1), h = length(s).
- Ta xây dựng bảng B[i,j] là xâu con lớn nhất giữa 2 xâu S1[1..i] và S[1..j] (i = 1..k;
j = 1..h).
- Ta nhận thấy rằng nếu B[k, j] = k với j = k..h thì ta luôn có phương án để tách
từ. Bằng phương pháp duyệt dựa trên bảng lưu trạng thái qua quá trình quy
hoạch, ta xét xem những vị trí còn lại trong xâu S(chưa thuộc S1) có tạo ra xâu
Tải bản FULL (84 trang): bit.ly/2Ywib4t
42. Võ Văn Trị - CQB | Confidential
S2 không. Nếu thoả mãn điều kiện này thì bài toán đã giải quyết xong. Lưu ý
rằng bài toán luôn có lời giải.
4. Cắt hình chữ nhật – Mã bài: VNCUT
Có một hình chữ nhật MxN ô, mỗi lần ta được phép cắt một hình chữ nhật thành
hai hình chữ nhật con theo chiều ngang hoặc chiều dọc và lại tiếp tục cắt các hình
chữ nhật con cho đến khi được hình vuông thi dừng.
Yêu cầu: Tìm cách cắt hình chữ nhật MxN thành ít hình vuông nhất.
Input
- Gồm một dòng chứa hai số M, N (1≤M,N≤500)
Output
- Gồm một dòng là kết quả số lượng hình vuông ít nhất.
hcn.inp hcn.out
10 2 5
5 6 5
Giải (thầy Đỗ Đức Đông):
- Dễ nhận thấy bài toán có thể mô tả bằng hai tham số , trong đó là chiều
thứ nhất, là chiều thứ hai của hình chữ nhật, ( , ) là số hình vuông ít nhất
được cắt từ hình chữ nhật kích thước × ( ∈ [1. . ], ∈ [1. . ]). Khi đó,
dùng bảng F[1..500,1..500] để lưu lại các giá trị ( , ).
- Các bài toán con nhỏ nhất (cơ bản) có = , khi đó ( , ) = 1.
- Công thức tính: ( , ) =
( 1, ) + ( 2, ) ớ 1 + 2 =
( , 1) + ( , 2) ớ 1 + 2 =
- Như vậy, có × bài toán con và chi phí chuyển mất ( + ), do đó độ
phức tạp của thuật toán là: ( × × ( + )).
5. Chuỗi đối xứng – Mã bài: NKPALIN
Dãy ký tự s được gọi là đối xứng (palindrome) nếu các phần tử cách đều đầu và
cuối giống nhau. Cho dãy s được tạo bởi n ký tự gồm chữ cái hoa, chữ cái thường
và chữ số.
Yêu cầu: tìm một chuỗi con đối xứng dài nhất của một chuỗi s cho trước. Chuỗi
con là chuỗi thu được khi xóa đi một số ký tự từ chuỗi ban đầu.
Dữ liệu: từ tệp văn bản PALIN.INP gồm gồm 1 dòng duy nhất chứa chuỗi s, chỉ
gồm những chữ cái in thường.
Kết quả: ghi vào tệp văn bản PALIN.OUT số lượng ký tự cần xóa.
Tải bản FULL (84 trang): bit.ly/2Ywib4t
43. Page 42 of 84
Võ Văn Trị - CQB | Confidential
Ví dụ:
PALIN.INP PALIN.OUT
Lmevxeyzl level
Bài tập luyện tập
6.1 Thang máy vũ trụ - Mã bài: ELEVATOR
Những con bò muốn đi vào vũ trụ! Chúng muốn đến được quỹ đạo bằng cách xây
một kiểu thang máy: một cái tháp khổng lồ làm bằng các khối chồng lên nhau.
Chúng có K (1 ≤ K ≤ 400) loại khối có thể xây tháp. Mỗi khối loại i có chiều cao h_i
(1 ≤ h_i ≤ 100) và c ó số lượng c_i (1 ≤ c_i ≤ 10). Do khả năng bị phá hủy bởi các tia
vũ trụ, không có phần nào của khối loại i có thể vượt qua độ cao a_i (1 ≤ a_i ≤
40000).
Giúp những con bò xây thang máy cao nhất có thể bằng cách chồng các khối lên
nhau theo luật trên.
Input
- Dòng 1: Một số nguyên: K
- Dòng 2..K+1: Mỗi dòng chứa 3 số nguyên được phân cách bởi khoảng
trắng: h_i, a_i, và c_i, miêu tả loại khối i.
Output
- Dòng 1: Một số nguyên H, chỉ độ cao lớn nhất của tháp có thể xây được.
Example
Input Output
3
7 40 3
5 23 8
2 52 6
48
GIẢI THÍCH:
Từ dưới lên: 3 khối loại 2, 3 khối loại 1, 6 khối loại 3. Chồng 4 khối loại 2 & 3 loại
1 không hợp lệ vì đỉnh của khối loại 1 vượt quá độ cao 40.
6. 2 Rải sỏi -Mã bài: STONE1
Xét trò chơi rải sỏi với một người chơi như sau:
Cho cây T và một đống sỏi gồm K viên. Ở mỗi bước người ta lấy 1 viên sỏi từ đống
sỏi và đặt vào một nút lá tuỳ ý. Nếu nút p có r nút lá và tất cả các nút lá đều đã có
sỏi thì người ta gom tất cả các viên sỏi ở các nút lá lại, đặt 1 viên ở nút p, xoá các
3957256