.c
om
an
co
ng
THUẬT TỐN ỨNG DỤNG
cu
u
du
o
ng
th
ĐỆ QUY QUAY LUI
Phạm Quang Dũng
Bộ mơn KHMT
1
CuuDuongThanCong.com
/>
NộI dung
th
an
co
ng
Tổng quan đệ quy quay lui
Bài toán liệt kê xâu nhị phân
Bài toán liệt kê nghiệm nguyên dương phương trình tuyến tính
Bài tốn liệt kê TSP
Bài tốn liệt kê hành trình taxi
Bài tốn liệt kê CBUS
Bài tốn liệt kê BCA
Bài toán liệt kê CVRP
ng
.c
om
Đệ quy quay lui
u
Tổng quan nhánh và cận
Bài toán tối ưu TSP
Bài toán tối ưu hành trình taxi
Bài tốn tối ưu CBUS
Bài tốn tối ưu BCA
Bài toán tối ưu CVRP
cu
du
o
Thuật toán nhánh và cận
2
CuuDuongThanCong.com
/>
Đệ quy quay lui
như giải bài toán tối ưu tổ hợp
.c
om
Phương pháp dùng để liệt kê các cấu hình tổ hợp cũng
ng
Liệt kê: liệt kê tất cả các bộ x = (x1,x2,…, xN) trong đó xi
du
o
ng
th
an
co
Ai - tập rời rạc, đồng thời (x1,x2,..., xN) thỏa mãn các ràng
buộc C cho trước
Tối ưu tổ hợp: trong số các bộ (phương án) x = (x1,x2,…,
xN) trong đó xi Ai - tập rời rạc, đồng thời (x1,x2,..., xN)
thỏa mãn các ràng buộc C cho trước, cần tìm phương án
có f(x) → min(max)
cu
u
Thử lần lượt từng giá trị cho mỗi biến
Chiến lược chọn biến, ví dụ x1, x2, x3,…, xN
Chiến lược chọn giá trị cho biến, ví dụ từ nhỏ đến lớn
hoặc ngược lại
3
CuuDuongThanCong.com
/>
.c
om
Đệ quy quay lui
x1 = v1
x1 = vk
co
x1 = v2
ng
()
. . . .
. . . .
cu
u
du
o
(v1,uq)
x3 = w1
. . . .
th
x2 = uq
ng
x2 = u1
an
(v1)
x3 = wh
. . . .
(v1,uq, wh)
. . . .
4
CuuDuongThanCong.com
/>
.c
om
Đệ quy quay lui
Tại mỗi thời điểm, ta có phương án bộ phận (x1 = v1, x2 = v2,
ng
…, xk-1 = vk-1) → cần thử duyệt tiếp các khả năng cho xk ?
cu
u
du
o
ng
th
an
co
try(k){// thử giá trị cho xk
forall v Ak do{
if(check(v,k)) then{// kiểm tra ràng buộc C của bài toán
xk = v;
[cập nhật các cấu trúc dữ liệu liên quan]
if(k = N) then solution();
else try(k+1);
[khôi phục trạng thái các cấu trúc dữ liệu khi quay lui]
}
}
}
. . . .
5
CuuDuongThanCong.com
/>
.c
om
Liệt kê xâu nhị phân độ dài N
#include <iostream>
using namespace std;
ng
#define MAX 100
int N;
an
co
int x[MAX];// bieu dien loi phuong an cua bai toan
th
bool check(int v, int k){
return true;
du
o
void solution(){
ng
}
cu
}
u
for(int i = 1; i <= N; i++) cout << x[i] << " "; cout << endl;
. . . .
6
CuuDuongThanCong.com
/>
.c
om
Liệt kê xâu nhị phân độ dài N
void TRY(int k){
for(int v = 0; v <= 1; v++){
ng
if(check(v,k)){
x[k] = v;
co
if(k == N) solution();
an
else TRY(k+1);
th
}
}
N = 3;
du
o
int main(){
ng
}
cu
}
u
TRY(1);// bat dau thu gia tri cho x[1]
. . . .
7
CuuDuongThanCong.com
/>
.c
om
Liệt kê nghiệm ngun dương của
phương trình tuyến tính
co
ng
X1 + X 2 + . . . + Xn = M
Phương án bộ phận (X1, …, Xk-1) có tổng bộ phận là T
Khởi tạo
an
Phương án bộ phận rỗng: (), T = 0
th
Thử giá trị cho Xk
ng
X1 + X2 + … + Xk-1 + Xk + Xk+ 1 + . . . + Xn = M
du
o
Xk = M – T – (Xk+1 + Xk+2 + … + Xn)
cu
u
1 ≤ Xk ≤ M – T – (n - k)
8
CuuDuongThanCong.com
/>
.c
om
Liệt kê nghiệm ngun dương của
phương trình tuyến tính
X1 + X 2 + . . . + Xn = M
ng
#include <stdio.h>
co
#define MAX 100
an
int n,M;
th
int X[MAX];
int check(int v, int k){
cu
return T + v == M;
u
if(k < n) return 1;
du
o
ng
int T;// accumulated sum
}
void solution(){
for(int i = 1; i <= n; i++) printf("%d ",X[i]); printf("\n");
. . . .
}
9
CuuDuongThanCong.com
/>
.c
om
Liệt kê nghiệm ngun dương của
phương trình tuyến tính
void TRY(int k){
for(int
v = 1; v <= M-T - n+k; v++){
ng
if(check(v,k)){
X[k] = v;
co
T = T + X[k];// update incrementally
an
if(k == n) solution();
th
else TRY(k+1);
T = T - X[k];// recover when backtracking
n = 6; M = 15;
T = 0;
du
o
int main(){
u
}
cu
}
ng
}
TRY(1);
. . . .
}
10
CuuDuongThanCong.com
/>
.c
om
Liệt kê hành trình giao hàng
Một shipper nhận hàng từ cửa hàng (điểm 0) và phải đi
cu
u
du
o
ng
th
an
co
ng
qua tất cả N khách hàng 1, 2, 3, . . ., N (mỗi khách
hàng đi qua đúng 1 lần) để giao hàng. Hãy liệt kê tất
cả các phương án cho shipper
11
CuuDuongThanCong.com
/>
.c
om
Liệt kê hành trình giao hàng
#include <bits/stdc++.h>
#define MAX 100
int N;
an
int X[MAX];// permutation 1,2,...,N
co
ng
using namespace std;
th
int appear[MAX];// appear[v] = 1 indicates that v has appeared
ng
void solution(){
}
du
o
for(int i = 1; i <= N; i++) cout << X[i] << " "; cout << endl;
u
bool check(int v, int k){
}
cu
return appear[v] == 0;
12
CuuDuongThanCong.com
/>
.c
om
Liệt kê hành trình giao hàng
void TRY(int k){// thu gia tri cho X[k]
for(int v = 1; v <= N; v++){
ng
if(check(v,k)){
appear[v] = 1;// update
an
if(k == N) solution();
co
X[k] = v;
th
else TRY(k+1);
appear[v] = 0;// recover
N = 3;
du
o
int main(){
u
}
cu
}
ng
}
for(int v = 1; v <= N; v++) appear[v] = 0;
TRY(1);
}
13
CuuDuongThanCong.com
/>
.c
om
Liệt kê hành trình đón trả khách cho taxi
Một taxi xuất phát từ điểm 0 và cần phục vụ đón trả N
th
an
co
ng
khách 1, 2, …, N. Khách thứ i có điểm đón là i và điểm
trả là N+i. Hãy liệt kê tất cả các phương án đón trả cho
taxi.
ng
Giải pháp
du
o
Đưa về bài toán liệt kê hoán vị
u
Do tính chất vận chuyển taxi nên điểm i sẽ nằm ngay
cu
trước điểm i+N trên mỗi hoán vị của 1, 2, …, 2N
→ mỗi hoán vị của 1, 2, …, N, chèn thêm i+N vào ngay sau
giá trị i (với mọi i = 1, 2, …, N)
14
CuuDuongThanCong.com
/>
.c
om
Liệt kê hành trình đón trả khách cho taxi
#include <bits/stdc++.h>
#define MAX 100
int N;
an
int X[MAX];// permutation 1,2,...,N
co
ng
using namespace std;
th
int appear[MAX];// appear[v] = 1 indicates that v has appeared
ng
void solution(){
du
o
for(int i = 1; i <= N; i++)
}
cu
cout << endl;
";
u
cout << X[i] << " " << X[i] + N << "
bool check(int v, int k){
return appear[v] == 0;
}
15
CuuDuongThanCong.com
/>
.c
om
Liệt kê hành trình đón trả khách cho taxi
void TRY(int k){// thu gia tri cho X[k]
for(int v = 1; v <= N; v++){
ng
if(check(v,k)){
appear[v] = 1;// update
an
if(k == N) solution();
co
X[k] = v;
th
else TRY(k+1);
appear[v] = 0;// recover
N = 3;
du
o
int main(){
u
}
cu
}
ng
}
for(int v = 1; v <= N; v++) appear[v] = 0;
TRY(1);
}
16
CuuDuongThanCong.com
/>
.c
om
Liệt kê hành trình đón trả khách cho bus
Một xe bus xuất phát từ điểm 0 và cần phục vụ đón trả
cu
u
du
o
ng
th
an
co
ng
N khách 1, 2, …, N. Khách thứ i có điểm đón là i và
điểm trả là N+i. Xe bus chở được tối đa Q khách cùng
một lúc. Hãy liệt kê tất cả các phương án đón trả cho
xe bus.
17
CuuDuongThanCong.com
/>
.c
om
Liệt kê hành trình đón trả khách cho bus
Một xe bus xuất phát từ điểm 0 và cần phục vụ đón trả
du
o
Thiết kế giải pháp
ng
th
an
co
ng
N khách 1, 2, …, N. Khách thứ i có điểm đón là i và
điểm trả là N+i. Xe bus chở được tối đa Q khách cùng
một lúc. Hãy liệt kê tất cả các phương án đón trả cho
xe bus.
u
Kiểm sốt số hành khách trên xe bằng biến q: số khách
cu
đang có mặt trên xe
Mỗi khi hành trình đi qua 1 điểm đón thì tăng q lên 1
Mỗi khi hành trình đi qua 1 điểm trả thì giảm q đi 1 đơn vị
18
CuuDuongThanCong.com
/>
Liệt kê hành trình đón trả khách cho bus
.c
om
#include <bits/stdc++.h>
using namespace std;
#define MAX_N 100
ng
int N;// so khach
co
int Q;// so cho tren bus cho hanh khach
int X[2*MAX_N + 1];// bieu dien phuong an lo trinh X[1], X[2], . . . X[2N]
an
int q;// so khach thuc su dang co tren xe ung voi phuong an bo phan hien tai
th
bool appear[2*MAX_N+1];
ng
bool check(int v, int k){
du
o
if(appear[v]) return false;
if(v <= N){// v is pickup
if(q >= Q) return false;
cu
u
}else{// v > N means drop-off
if(!appear[v-N]) return false;
}
return true;
}
19
CuuDuongThanCong.com
/>
Liệt kê hành trình đón trả khách cho bus
.c
om
void solution(){
for(int i = 1; i <= 2*N; i++) cout << X[i] << " "; cout << endl;
}
ng
void TRY(int k){// thu gia tri cho X[k]
co
for(int v = 1; v <= 2*N; v++){
if(check(v,k)){
an
X[k] = v;
th
appear[v] = true;
ng
if(v <= N) q++; else q--;// update q incrementally
du
o
if(k == 2*N) solution();
else TRY(k+1);
appear[v] = false;
}
cu
u
if(v <= N) q--; else q++;// recover status q
}
}
20
CuuDuongThanCong.com
/>
Liệt kê hành trình đón trả khách cho bus
.c
om
int main(){
N = 3; Q = 2;
q = 0;
ng
for(int v = 1; v <= 2*N; v++) appear[v] = false;
co
TRY(1);
cu
u
du
o
ng
th
an
}
21
CuuDuongThanCong.com
/>
.c
om
DIGITS
Write C program that reads an integer value N from
stdout
24
cu
u
1234
du
o
stdin
ng
th
an
co
ng
stdin, prints to stdout the number Q ways to assign
values 1, 2, …, 9 to characters I, C, T, H, U, S, K
(characters are assigned with different values)
ICT – K62 + HUST = N
22
CuuDuongThanCong.com
/>
DIGITS
.c
om
#include <stdio.h>
int X[7];// X[0] = I, X[1] = C, X[2] = T, X[4] = H, X[5] = U, X[6] = S, X[3] = K
ng
int appeared[10];
co
int ans,N;
an
void solution(){
th
int T = X[0]*100 + X[1]*10 + X[2] - X[3]*100 - 62 +
X[4]*1000 + X[5]*100 + X[6]*10 + X[2];
du
o
ans++;
ng
if(T == N){
//printf("%d%d%d - %d62 + %d%d%d%d\n",X[0],X[1],X[2],X[3],X[4],X[5],X[6],X[2]);
}
void init(){
cu
u
}
for(int v = 1; v <= 9; v++) appeared[v] = 0;
}
23
CuuDuongThanCong.com
/>
DIGITS
.c
om
void TRY(int k){
for(int v = 1; v <= 9; v++){
if(appeared[v] == 0){
ng
X[k] = v;
co
appeared[v] = 1;
if(k == 6){
an
solution();
th
}else{
ng
TRY(k+1);
du
o
}
}
}
cu
}
u
appeared[v] = 0;
24
CuuDuongThanCong.com
/>
DIGITS
.c
om
void solve(){
scanf("%d",&N);
init();
ng
ans = 0;
co
TRY(0);
printf("%d",ans);
an
}
th
int main(){
ng
solve();
cu
u
du
o
}
25
CuuDuongThanCong.com
/>