You are on page 1of 6

TRY YOUR BEST!

Một số bài toán đệ quy cơ bản C++


1. Giai thừa
long long Fact(int n)
{
if (n <= 1) return 1;
return Fact(n-1) * n;
}

2. Tính ab
long long Pow(int a, int b)
{
if (b == 0) return 1;
return Pow(a, b-1) * a;
}

3. Tổng các chữ số, tích các chữ số của một số


Không Đệ Quy Đệ Quy
int tongcs( int x) int tongcs(int x)
{ {
int tong = 0; if (x < 10) return x;
while (x > 0) return tongcs(x/10) + x % 10;
{ }
tong += x % 10; int tichcs(int x)
x /= 10; {
} if (x < 10) return x;
return tong; return tichcs(x/10) * (x % 10);
} }

4. Ước chung lớn nhất(greatest common divisor)


Không Đệ Quy Đệ Quy
int UCLN(int a, int b) int UCLN(int a, int b)
{ {
while (b != 0) if (b == 0) return a;
{ return UCLN(b, a%b);
int r = a % b; }
a = b;
b = r;
}
return a;
}

THPT CHUYÊN HƯNG YÊN Page 1


TRY YOUR BEST!

Duyệt Đệ Quy quay lui


Tham khảo sách Lê Minh Hoàng – page 12, 13, 14, …

5. Liệt kê tất cả các dãy nhị phân độ dài N


void Ghi()
{
for (int i = 1; i <= n; i++) cout << x[i];
cout << endl;
}

void duyet(int pos)


{
if (pos > n){
Ghi();
return;
}
for (int i = 0; i <= 1; i++)
{
x[pos] = i;
duyet(pos+1);
}
}

6. Liệt kê tất cả các tập con 𝑘 phần tử trong 𝑁 phần tử (tổ hợp chập 𝑘 của 𝑁).
void Ghi()
{
for (int i = 1; i <= k; i++) cout << x[i] << " ";
cout << endl;
}

void tohop(int pos)


{
if (pos > k){
Ghi();
return;
}
for (int i = x[pos-1] + 1; i <= n; i++)
{
x[pos] = i;
tohop(pos+1);
}
}

THPT CHUYÊN HƯNG YÊN Page 2


TRY YOUR BEST!

7. Liệt kê các chỉnh hợp không lặp chập 𝑘 của 𝑁.


void chinhhop(int pos)
{
if (pos > k){
Ghi(); // Giống thủ tục ghi bài tổ hợp trên
return;
}
for (int i = 1; i <= n; i++)
if (!mark[i])
{
a[pos] = i;
mark[i] = true;
chinhhop(pos+1);
mark[i] = false;
}
}

8. Cho một số nguyên dương N. Đưa ra tất cả các cách phân tích N thành tổng các số nguyên
dương khác.
Ví dụ: N = 5. N = 1 + 1 + 1 + 1 + 1 = 1 + 1 + 1 + 2 = 1 + 2 + 2 = 1 + 4 = 2 + 3 = 5
void Ghi(int num)
{
cout << n << " = ";
for (int i = 1; i < num; i++)
cout << x[i] << " + ";
cout << x[num] << endl;
}
void Try(int num, int S) // S là tổng còn lại
{
for (int i = x[num-1]; i + i <= S; i++)
{
x[num] = i;
Try(num+1, S-i);
}
x[num] = S;
Ghi(num);
}

int main()
{
cin >> n;
x[0] = 1;
Try(1, n);
return 0;
}

THPT CHUYÊN HƯNG YÊN Page 3


TRY YOUR BEST!

9. Bài toán xếp hậu

void Ghi_Hau()
{
for (int i = 1; i <= n; i++) cout << "(" << i << ", "<< x[i] << "); ";
cout << endl;
sl ++;
}

void XepHau(int k)
{
if (k > n){
Ghi_Hau();
return;
}
for (int i = 1; i <= n; i++)
if (cot[i] == 0 && tong[i+k] == 0 && hieu[i-k+n] == 0)
{
cot[i] = tong[i+k] = hieu[i-k+n] = 1;
x[k] = i;
XepHau(k+1);
cot[i] = tong[i+k] = hieu[i-k+n] = 0;
}
}

int main()
{
cin >> n;
memset(tong, 0, sizeof(tong));
memset(hieu, 0, sizeof(hieu));
XepHau(1);
cout << "So cach xep hau la " << sl;
}

Hàm memset gán toàn bộ giá trị mảng bằng 0, chú ý bên trên khai báo thêm
#include <cstring>
Tong[i+k]: đánh dấu đường chéo x+y = i+k đã có hậu đặt chưa.
Hieu[i-k+n]: đánh dấu đường chéo x-y = i-k đã đặt hậu hay chưa, cộng thêm n để tránh chỉ số
âm.
x[k] = i : là biểu thị đặt con hậu vào ô (k, i) hay ô (k, x[k]). Mỗi hàng chỉ đặt một hậu.

THPT CHUYÊN HƯNG YÊN Page 4


TRY YOUR BEST!

10. Bài toán trò chơi điền bảng số - SUDOKU

0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8
0 0 1 2 3 4 5 6 7 8 0
1 9 10 11 12 13 14 15 16 17 1 (0,0) (0,1) (0,2)
2 18 19 20 21 22 23 24 25 26 2
3 27 28 29 30 31 32 33 34 35 3
4 36 37 38 39 40 41 42 43 44 4 (1,0) (1,1) (1,2)
5 45 46 47 48 49 50 51 52 53 5
6 54 55 56 57 58 59 60 61 62 6
7 63 64 65 66 67 68 69 70 71 7 (2,0) (2,1) (2,2)
8 72 73 74 75 76 77 78 79 80 8

Thay vì đánh số các hàng cột từ 1 → 9, ta sẽ đánh số 0 → 8. Các ô đánh số như hình bên trái và
đánh số các hình vuông theo hình bên phải.
Ta dễ dàng thấy một ô có thứ tự là 𝑥 (0 ≤ 𝑥 ≤ 80) thì có tọa độ hàng là 𝑖 = 𝑥/9, tọa đô cột là
𝑗 = 𝑥%9, tọa độ hình vuông 3 × 3 chứa ô đó là [𝑖/3][𝑗/3].
Duyệt đệ quy, lần lượt thử đặt các giá trị từ 1 tới 9 vào các ô trống.
Dùng thêm mảng ℎ𝑎𝑛𝑔[𝑖][𝑥] 𝑥 ∈ [1,9] để đánh dấu đã có giá trị 𝑥 ở hàng 𝑖 hay chưa.
Tương tự với mảng cot[𝑗] [𝑥]𝑣à ℎ𝑣 [𝑢][𝑣 ][𝑥] để đánh dấu cho cột 𝑗 và hình vuông 3 × 3
[𝑢][𝑣](𝑢, 𝑣 = 0,1,2)
Đoạn code được thực hiện như sau:
#include <iostream>
#include <cstring>
#include <fstream>
#include <cstdlib> // khai báo để sử dụng lệnh exit(0)
using namespace std;
int hang[10][10], cot[10][10], hv[3][3][10], a[10][10];
void nhap()
{
char ch;
for (int i = 0; i <= 8; i++)
for (int j = 0; j <= 8; j++)
{
cin >> ch;
if (ch == '.') a[i][j] = 0;
else
{
int u = ch - 48; // lấy giá trị số, không để kiểu ký tự.
hang[i][u] = cot[j][u] = hv[i/3][j/3][u] = 1;
a[i][j] = u;

THPT CHUYÊN HƯNG YÊN Page 5


TRY YOUR BEST!

}
}
}

void ghikq()
{
for (int i = 0; i <= 8; i++)
{
for (int j = 0; j <= 8; j++) cout << a[i][j];
cout << endl;
}
exit(0); // chương trình dừng hẳn khi tìm thấy phương án điền số.//khai bao #include <cstdlib>
}

void duyet( int vt)


{
if (vt > 80) ghikq();
int u = vt / 9; // toa do hang
int v = vt % 9; // toa do cot
if (a[u][v] != 0) duyet(vt+1);
else
{
for (int x = 1; x <= 9; x++)
{
if (hang[u][x] || cot[v][x] || hv[u/3][v/3][x]) continue;
hang[u][x] = cot[v][x] = hv[u/3][v/3][x] = 1;
//danh dau da co gia tri x o hang u, cot v, va hinh vuong [u/3][v/3]
a[u][v] = x;
duyet(vt+1);
a[u][v] = 0;
hang[u][x] = cot[v][x] = hv[u/3][v/3][x] = 0; // tra de quy
}
}
}
int main()
{
freopen("sudoku.inp", "r", stdin);
freopen("sudoku.out", "w", stdout);
memset(hang,0,sizeof(hang));
memset(cot,0,sizeof(cot));
memset(hv,0,sizeof(hv));
nhap();
duyet(0);
cout << "IMPOSSIBLE"; // nếu không tìm được lời giải, phần ghikq không thực hiện, lệnh này sẽ
được thực hiện
}

THPT CHUYÊN HƯNG YÊN Page 6

You might also like