Tài liệu tham khảo...12 Phục lục Lời mở đầu: Trong bối cảnh công nghệ thông tin ngày càng phát triển và đóng vai trò quan trọng trong hầu hết cuộc sống của chúng ta,việc nghiên cứu và áp
Trang 1TRƯỜNG ĐẠI HỌC GIAO THÔNG VẬN TẢI TP HỒ CHÍ MINH
KHOA CÔNG NGHỆ THÔNG TIN
BÁO CÁO CUỐI KỲ
MÔN CÔNG NGHỆ PHẦN MỀM
Ngành: Công nghệ thông tin
Chuyên ngành: Công nghệ thông tin
Giảng viên hướng dẫn : Huỳnh Thanh Việt
Sinh viên thực hiện : Nguyễn Thanh Tuyền
MSSV : 089305002161
Lớp : CN2303CLCB
Trang 2Mục Lục
Mục lục 2
Nhận xét của giảng viên hướng dẫn 2
Lời mở đầu 3
Phần I: 3
1 Bài số 5 3
1.1 Yêu cầu đề bài 3
1.2 Hướng đi 4
1.3 Code 4
1.4 Kết quả in ra màn hình 5
2 Bài số 18 5
2.1 Yêu cầu đề bài 6
2.2 Hướng đi 7
2.3 Code 7
2.4 Kết quả in ra màn hình 7
3 Bài số 2 8
3.1 Yêu cầu đề bài 8
3.2 Hướng đi 8
3.3 Code 8
3.4 Kết quả in màn hình 9
4 Bài số 18 9
4.1 Yêu cầu đề bài 9
4.2 Hướng đi 10
4.3 Code 10
4.4 Kết quả in ra màn hình 10
Phần II: 11
II.1 Đánh giá chung 11
II.2 Kết luận 11
Trang 3Tài liệu tham khảo 12 Phục lục
Lời mở đầu:
Trong bối cảnh công nghệ thông tin ngày càng phát triển và đóng vai trò quan trọng trong hầu hết cuộc sống của chúng ta,việc nghiên cứu và áp dụng các giải thuật hiệu quả trở nên vô cùng thiết yếu Môn học “Phân tích và Thiết kế Giải thuật” không chỉ cung cấp kiến thức nền tảng về các giải thuật quan trọng, mà còn giúp sinh viên rèn luyện khả năng tư duy, phân tích và tối ưu hóa các giải pháp lập trình Thông qua việc nghiên cứu các phương pháp như chia để trị, quy hoạch động, đệ quy, quay lui, chúng ta có thể hiểu rõ hơn về cách xây dựng và đánh giá hiệu quả của giải thuật, từ đó ứng dụng vào việc giải quyết các bài toán phức tạp trong thực tiễn
Trong bài báo cáo này, em sẽ đi sâu vào phân tích và minh họa các giải thuật đã học, đồng thời trình bày những ứng dụng thực tế của chúng trong các tình huống cụ thể Qua đó, em mong muốn cung cấp cái nhìn toàn diện về cách các giải thuật có thể giúp tối ưu hóa quy trình giải quyết vấn
đề, cũng như nâng cao hiệu suất hệ thống trong nhiều môi trường khác nhau
Phần I:
1 Bài 5:
1.1 Yêu cầu đề bài:
Sử dụng chiến lược quay lui thực hiện bài toán sau:
Cho một số nguyên dương A và 1 số nguyên dương N Yêu cầu bài toán
là tạo ra số lớn nhất bằng cách đổi chỗ N lần các chữ số bên trong số A
Ví dụ: Giả sử A = 13579 và N = 2 thì kết quả mong muốn là 97531 Chúng ta vừa thực hiện đổi chỗ 2 lần bao gồm đổi chỗ 1 và 9, 3 và 5
Trang 41.2 Hướng đi :
-Mục tiêu: Tạo ra số lớn nhất bằng cách đổi chỗ N lần các chữ số bên trong số A
-Ý tưởng:
+Chuyển số nguyên thành chuỗi để dễ dàng hoán đổi các chữ số Sử dụng thuật toán quay lui để thử mọi cách đổi chỗ hai chữ số, với giới hạn tối đa
là N lần
+Cập nhật và lưu lại kết quả lớn nhất trong suốt quá trình thực hiện +Quay lui sau mỗi bước hoán đổi để đảm bảo thử hết các khả năng
-Các bước thực hiện:
+Nhập A và N từ người dùng
+Chuyển A thành chuỗi và khởi tạo kết quả lớn nhất ban đầu
+Thực hiện thuật toán quay lui, thử tất cả các cách đổi chỗ tối đa N lần +Tại mỗi bước đổi chỗ, đệ quy gọi lại hàm để tiếp tục kiểm tra
+Khi đạt đến N lần đổi chỗ, cập nhật kết quả lớn nhất nếu cần
+Sau mỗi lần đệ quy, hoàn tác đổi chỗ (quay lui) để thử các cách hoán đổi khác
+Sau khi kết thúc thuật toán, in ra số lớn nhất tìm được
1.3 Code:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
// Hàm cập nhật kết quả lớn nhất
void updateMax(string &maxResult, const string ¤tResult) {
if (currentResult > maxResult) {
maxResult = currentResult;
}
}
// Hàm quay lui tìm số lớn nhất
void findMaxNumber(string A, int N, string &maxResult, int currentStep
= 0) {
if (currentStep == N) {
updateMax(maxResult, A);
return;
}
int length = A.length();
for (int i = 0; i < length; i++) {
Trang 5for (int j = i + 1; j < length; j++) {
// Đổi chỗ 2 chữ số tại vị trí i và j
swap(A[i], A[j]);
// Gọi đệ quy để tìm kết quả sau khi đổi chỗ
findMaxNumber(A, N, maxResult, currentStep + 1);
// Hoàn tác đổi chỗ để thử với trường hợp khác
swap(A[i], A[j]);
}
}
}
int main() {
int A, N;
cout << "Nhập số nguyên dương A: ";
cin >> A;
cout << "Nhập số nguyên dương N: ";
cin >> N;
// Chuyển số A thành chuỗi để dễ xử lý
string A_str = to_string(A);
string maxResult = A_str;
// Gọi hàm quay lui để tìm số lớn nhất
findMaxNumber(A_str, N, maxResult);
cout << "Số lớn nhất có thể tạo ra sau " << N << " lần đổi chỗ là: " << maxResult << endl;
return 0;
}
1.4 Kết quả in ra màn hình:
2 Bài 18:
2.1 Yêu cầu đề bài:
Viết chương trình sử dụng thuật toán quy hoạch động:
Nhập vào một mảng A có N phần tử Tìm dãy con dài nhất có tổng chia hết cho một số k được nhập từ bàn phím(Yêu cầu xuất ra tổng và dãy số tương ứng với tổng đó)
Trang 62.2 Hướng đi:
-Mục tiêu: Tìm dãy con dài nhất trong mảng có tổng chia hết cho k.Xuất
ra tổng và dãy con tương ứng
-Ý tưởng chính:
+Sử dụng quy hoạch động với mảng lưu tổng lớn nhất có thể có với từng
dư khi chia cho k
+Cập nhật dãy con dựa trên tổng hiện tại và phần tử mới
-Các bước thực hiện:
+Khởi tạo mảng tong[] lưu tổng lớn nhất với từng dư
+Khởi tạo mảng len[] để lưu độ dài của dãy con tương ứng
+Với mỗi phần tử, duyệt qua tất cả các tổng hiện tại, thử cộng thêm phần
tử này vào và cập nhật tổng và độ dài mới
+Xuất ra kết quả khi tổng có dư bằng 0 với độ dài dài nhất
2.3 Code:
#include <iostream>
#include <vector
using namespace std;
void timDayConDaiNhatChiaHetChoK(vector<int>& A, int N, int k) { vector<int> tong(k, 0);
// tong[i] lưu tổng lớn nhất có dư là i khi chia cho k vector<vector<int>> dayCon(k); // lưu dãy con tương ứng
// Duyệt qua từng phần tử của mảng for (int i = 0; i < N; i++)
{ vector<int> tam = tong;
// Mảng tạm để lưu trạng thái trước khi cập nhật vector<vector<int>> dayTam = dayCon;
// Mảng tạm lưu dãy con trước khi cập nhật
// Cập nhật dãy con cho mỗi phần tử for (int j = 0; j < k; j++) { int tongMoi = tong[j] + A[i]; // Tổng mới sau khi thêm A[i] int duMoi = tongMoi % k;
// Dư mới khi chia cho k
if (tongMoi > tam[duMoi]) { tam[duMoi] = tongMoi;
// Cập nhật tổng lớn hơn dayTam[duMoi] = dayCon[j];
Trang 7// Cập nhật dãy con tương ứng dayTam[duMoi].push_back(A[i]); } } // Thêm phần tử hiện tại vào dãy contong = tam;
// Cập nhật lại tong sau khi duyệt hết các dãy con dayCon = dayTam;} // Cập nhật lại dãy con sau khi duyệt hết các dãy con
// Xuất ra kết quả if (tong[0] == 0) { cout << "Khong tim duoc day con nao chia het cho " << k << endl; }
else { cout << "Tong lon nhat chia het cho " << k << ": " << tong[0] << endl;
cout << "Day con tuong ung: ";
for (int num : dayCon[0]) { cout << num << " "; } cout << endl; } } int main() { int N, k; cout << "Nhap so luong phan tu cua mang:”; cin >> N; vector<int> A(N);
cout << "Nhap cac phan tu cua mang: ";
for (int i = 0; i < N; i++) { cin >> A[i]; } cout << "Nhap so k: "; cin >> k; timDayConDaiNhatChiaHetChoK(A, N, k);
return 0;
}
2.4 Kết quả in ra màn hình:
3 Bài 2:
Trang 83.1 Yêu cầu đề bài:
Viết chương trình dùng chiến lược đệ quy và quay lui cho bài toán xếp quân hậu lên bàn cờ 8x8 sao cho cho các quân hậu không cùng nằm trên đường thẳng hoặc đường chéo
3.2 Hướng đi:
3.3 Code:
#include <iostream>
using namespace std;
const int N = 8;
int X[N + 1], cot[N + 1], d1[2 * N + 1], d2[2 * N + 1];
void inketqua() {
for (int i = 1; i <= N; i++) {
cout << "Con hau o hang thu " << i << " nam o cot " << X[i] << endl;
}
cout << endl;
}
void Try(int i) {
for (int j = 1; j <= N; j++) {
// Kiểm tra xem vị trí có thể đặt quân hậu không
if (cot[j] == 0 && d1[i - j + N] == 0 && d2[i + j - 1] == 0) { X[i] = j;
cot[j] = d1[i - j + N] = d2[i + j - 1] = 1; // Đánh dấu vị trí đã đặt quân hậu
if (i == N) {
inketqua();
} else {
Try(i + 1);
}
// Backtrack
cot[j] = d1[i - j + N] = d2[i + j - 1] = 0; // Bỏ đánh dấu khi quay lui
}
}
}
Trang 9int main() {
// Khởi tạo các mảng kiểm tra
for (int i = 1; i <= 2 * N; i++) {
d1[i] = d2[i] = 0;
}
for (int i = 1; i <= N; i++) {
cot[i] = 0;
}
Try(1);
return 0;
}
3.4 Kết quả in ra:
4 Bài 15:
4.1 Yêu cầu đề bài:
Một xâu gọi là xâu đối xứng (palindrome) nếu xâu đó đọc từ trái sang phải hay từ phải sang trái đều như nhau Cho một xâu S, hãy tìm số kí tự
ít nhất cần thêm vào S để S trở thành xâu đối xứng
4.2 Hướng đi:
4.3 Code:
#include <iostream>
#include <string>
using namespace std;
int minAdditionsToPalindrome(string str) {
Trang 10int n = str.length();
string rev_str = str;
reverse(rev_str.begin(), rev_str.end()); // Đảo ngược xâu
// Duyệt qua xâu để tìm phần đối xứng dài nhất
for (int i = 0; i < n; i++) {
// So sánh phần của xâu gốc với phần của xâu đảo ngược
if (str.substr(i) == rev_str.substr(0, n - i)) {
return i; // Số ký tự cần thêm vào là phần còn lại từ vị trí i }
}
return n - 1;
}
int main() {
string str;
cout << "Nhap vao chuoi: ";
cin >> str;
int result = minAdditionsToPalindrome(str); // Tính số ký tự cần thêm cout << "So ki tu can them vao de xau thanh doi xung: " << result << endl;
return 0;
}
4.4 Kết quả in ra màn hình:
Trang 11Phần II:
II.1 Đánh giá chung:
Sử dụng các thuật toán để xử lý cái bài tập trêm giúp chúng ta hiểu rộng ra.Tăng tư duy logic giải quyết các bài toán tương tự
II.2 Kết luận:
Ở báo cáo này,em đã trình bày các nội dung bao gồm yêu cầu đề,hướng đi,code,kết quả in ra.Các kiến thức về học phần “Công nghệ phần mềm”
đã được vận dụng để tạo ra một bài thuyết trình chất lượng,giúp em và các thành viên trong nhóm hiểu rõ hơn về các thuật toán.Góp phần hỗ trợ chúng em có nguồn kiến thức hữu íchvận dụng trong hành trình sắp tới Qua quá trình thực hiện, chúng em rút ra được nhiều bài học quý giá trong việc trao đổi,xây dựng code,hiểu thêm.Tuy nhiên,trong quá trình thảo luận có nhiều bất đồng về quan điểm.Nhưng không vì vậy mà chúng
em dừng bước trên hành trình tìm kiếm tri thức cho mình
Bài báo cáo này minh chứng cho một quá trình học tập của em và các bạn trong nhóm.Đánh dấu việc tụi em trải qua một thời gian học không dài nhưng tiếp thu và ôn lại các lý thuyết còn hỏng
Thời gian tới chúng em cos thể qua học phâfn này mà sáng tạo không ngừng.Dựa trên nguồn thộng tin có sẵn từ Giảng viên để có thể tạo ra nhiều sản phẩm bài học hay hơn nữa
Tài liệu tham khảo:
-Visual studio code
-C++ online compiler