Professional Documents
Culture Documents
ĐỀ THI CUỐI KỲ
Tên học phần: TOÁN RỜI RẠC
Mã học phần: …………………… Số tín chỉ: 3
Phương pháp đánh giá (*): tự luận có giám sát Thời gian làm bài: 90 phút
Đề số: Đ0001
☐ Sinh viên được sử dụng tài liệu khi làm bài
----------------------------------------------------------------------------------------------------------------------------------
Họ tên: …………Nguyễn Hùng Phi…………… Lớp:………22T_DT2………MSSV:
………102220119……………...
Sinh viên làm bài trực tiếp trên tệp này, lưu tệp với định dạng MSSV_HọTên.pdf và nộp bài thông
qua MSTeam:
Câu 1 (3 điểm) Gọi Bn là số chuỗi độ dài n được hình thành từ các ký tự {A, B, C, 1, 2, 3, 4, 5, 6}.
a) Đếm số chuỗi Bn sao cho Bn chỉ chứa ký tự số.
# Trả lời: Trình bày và dán kết quả vào bên dưới:
Vì chuỗi B gồm n phần tử, mỗi phần tử là ký tự số => mỗi kí tự có 6 cách chọn =>
6^n
b) Lập hệ thức truy hồi để đếm số chuỗi Bn sao cho Bn không chứa hai ký tự số kề nhau.
# Trả lời: Trình bày cách xây dựng hệ thức truy hồi vào đây:
Gọi an số chuỗi Bn không chứa hai ký tự số kề nhau
-Trường hợp 1:bn {A,B,C}
-> bn có 3 khả năng xảy ra. Ứng với mỗi khả năng của bn thì số chuỗi Bn không chứa hai ký tự số kề
nhau bằng số chuỗi b1b2..bn-1 không chứa hai ký tự số kề nhau và bằng an-1.
Theo nguyên lý nhân thì số chuỗi Bn là: 3an-1
-Trường hợp 2: bn {1,2,3,4,5,6}: có 6 khả năng xảy ra cho bn
-> bn-1 {A,B,C} có 3 khả năng xảy ra cho bn-1-> có 6*3=18 khả năng xảy ra cho bn-1bn. Ứng với
mỗi khả năng của bn-1bn thì số chuỗi Bn không chưa hai ký tự số kề nhau bằng số chuỗi b1b2..bn-2 không
chứa hai ký tự số kề nhau và bằng an-2.
Theo nguyên lý nhân thì số chuỗi Bn là: 18an-2
Theo nguyên lý cộng ta có hệ thức truy hồi của an: an=3an-1+18an-2
#Trả lời: Xác định điều kiện ban đầu của hệ thức truy hồi vào đây:
Điều kiện ban đầu :
-Nếu n=1 thì: b1 có 9 khả năng xảy ra => a1=9
-Nếu n=2 thì:
+Nếu b2 {A,B,C} thì b1 có 9 khả năng xảy ra=> có 3*9=27 khả năng xảy ra của B2
+Nếu b2 {1,2,3,4,5,6} thì b1 có 3 khả năng xảy ra => có 6*3=18 khả năng xảy ra của B2
Theo nguyên lý cộng a2=27+18=45
Vậy a1=9,a2=45
c) Hãy giải hệ thức truy hồi trên câu b)
# Trả lời: Phương trình đặc trưng: x2=3x+18
# Trả lời: Nghiệm phương trình đặc trưng ( nếu có): x1 =6; x2 = -3
Vậy
void in();
int main()
{
int i,j;
printf("Nhap n>=k: ");
scanf("%d%d", &n, &k);
in();
while (1) {
i=k;
while (i>0 && S[i]==n-k+i)
i--;
if (i==0)
break;
S[i]+=1;
for (j=i+1;j<=k;j++)
S[j]=S[j-1]+1;
in();
}
return 0;
}
void in()
{
int i;
printf("\n%3d: ",++c);
for (i=1; i<=k; i++)
printf("%d ", S[i]);
}
# Trả lời: Dán kết quả thực thi vào đây:
# Trả lời: Giải thích chi tiết cấu hình đầu tiên, cấu hình kết thúc, thuật toán sinh vào đây
Cấu hình đầu tiên được đặt là tập con có k phần tử đầu tiên của tập X, tức là {1, 2, ..., k}.
Cấu hình kết thúc là tập con cuối cùng có k phần tử của tập X. Trong thuật toán sinh, cấu hình kết thúc
được đặt là tập con có k phần tử cuối cùng của tập X, tức là {n-k+1, n-k+2, ..., n}.
Thuật toán sinh được sử dụng để liệt kê tất cả các tập con k phần tử của tập X bằng cách sinh ra tất cả các
tập con k phần tử bắt đầu từ cấu hình đầu tiên và kết thúc với cấu hình kết thúc. Thuật toán sinh được thực
hiện theo các bước sau:
Bước 1: Khởi tạo cấu hình đầu tiên.
Bước 2: In ra cấu hình hiện tại.
Bước 3: Tìm vị trí j cuối cùng mà giá trị tại đó có thể được tăng lên.
Bước 4: Nếu không tìm thấy vị trí j nào, kết thúc thuật toán.
Bước 5: Tăng giá trị tại vị trí j lên một đơn vị.
Bước 6: Với mỗi vị trí i lớn hơn j, đặt giá trị tại i bằng giá trị tại j cộng với i-j.
Bước 7: Quay lại bước 2.
b) Viết chương trình liệt kê tất cả các tập con của X sử dụng kết quả ở câu a)
# Trả lời: Dán code vào đây:
#include <stdio.h>
#include <dos.h>
#include <conio.h>
#define MAX 20
int S[MAX],c,n, k;
void in();
main()
{
int i,j;
printf("nhap n:"); scanf("%d", &n);
for (k=1;k<=n;k++) {
c=0;
printf("\nTruong Hop K =%d:\n",k);
for (i=1; i<=k; i++)
S[i]=i;
in();
while (1){
i=k; while (i>0 && S[i]==n-k+i) i--;
if (i==0)
break;
S[i]+=1;
for (j=i+1;j<=k;j++)
S[j]=S[j-1]+1;
in();
}
}
}
void in()
{
int i;
printf("\n%3d: ",++c);
for (i=1; i<=k; i++) printf("%d ", S[i]);
}
# Trả lời: Dán kết quả vào đây với trường hợp n = 4:
B E
6
7
13 5
12
A G
3 D 14
5 2
16
15
C 25 F
a) Dùng thuật toán Dijkstra để tìm đường đi ngắn nhất từ đỉnh A đến đỉnh G.
# Trả lời: Trình bày cách giải bằng tay vào đây (yêu cầu trình bày dạng bảng):
1 A B C D E F G
2 0 , , , , , ,
3 * 12,A 5,A , , , ,
6 * * * * 12,D 22,D ,
7 * * * * * 22,D 19,E
8 * * * * * 22,D *
9 * * * * * * *
b) Viết chương trình sử dụng thuật Dijkstra để tìm đường đi ngắn nhất từ đỉnh A đến đỉnh G.
# Trả lời: Dán code ở đây:
# Trả lời: Dán kết quả thực thi với đầu vào đỉnh A, đỉnh G và ma trận trọng số:
c) Dùng thuật toán Kruskal để tìm cây khung nhỏ nhất của đồ thị.
# Trả lời: Trình bày cách làm bằng tay vào đây:
d) Viết chương trình sử dụng thuật Kruskal để tìm cây khung nhỏ nhất của đồ thị.
# Trả lời: Dán code ở đây:
#include <stdio.h>
#include <stdlib.h>
#define MAX 50
void Init(void) {
printf("Nhap so dinh va so canh cua do thi:\n");
scanf("%d%d", &n, &m);
printf("So dinh do thi: %d\n", n);
printf("So canh do thi: %d\n", m);
printf("Nhap danh sach cac canh va do dai cua chung:\n");
for (int i = 1; i <= m; i++) {
scanf("%d%d%d", &dau[i], &cuoi[i], &w[i]);
}
}
int tim(int i) {
int tro = i;
while (father[tro] > 0)
tro = father[tro];
return (tro);
}
void Kruskal(void) {
int last, u, v, r1, r2, ncanh, ndinh;
for (int i = 1; i <= n; i++)
father[i] = -1;
for (int i = m / 2; i > 0; i--)
Heap(i, m);
last = m;
ncanh = 0;
ndinh = 0;
minl = 0;
connect = 1;
while (ndinh < n - 1 && ncanh < m) {
ncanh = ncanh + 1;
u = dau[1];
v = cuoi[1];
r1 = tim(u);
r2 = tim(v);
if (r1 != r2) {
ndinh = ndinh + 1;
Union(r1, r2);
daut[ndinh] = u;
cuoit[ndinh] = v;
minl = minl + w[1];
}
dau[1] = dau[last];
cuoi[1] = cuoi[last];
w[1] = w[last];
last = last - 1;
Heap(1, last);
}
if (ndinh != n - 1)
connect = 0;
}
void Result(void) {
printf("Do dai cay khung nho nhat: %d\n", minl);
printf("Cac canh cua cay khung nho nhat:\n");
for (int i = 1; i < n; i++)
printf("%d %d\n", daut[i], cuoit[i]);
}
int main() {
Init();
Kruskal();
Result();
return 0;
}