1. Trang chủ
  2. » Tất cả

Báo cáo kỹ thuật lập trình thực hành sử dụng các cấu dữ liệu cơ bản để giải quyết các bài toán cụ thể

37 4 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Báo cáo kỹ thuật lập trình thực hành sử dụng các cấu dữ liệu cơ bản để giải quyết các bài toán cụ thể
Tác giả Nguyễn Duy Khánh Linh
Người hướng dẫn Lê Thị Hoa
Trường học Trường Đại học Bách Khoa Hà Nội
Chuyên ngành Kỹ Thuật Lập Trình
Thể loại Báo cáo kỹ thuật
Năm xuất bản 2022
Thành phố Hà Nội
Định dạng
Số trang 37
Dung lượng 295,7 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Nguyễn Duy Khánh Linh – 20204839 TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI BÁO CÁO KỸ THUẬT LẬP TRÌNH Thực hành sử dụng các cấu dữ liệu cơ bản để giải quyết các bài toán cụ thể BUỔI 4 – TUẦN 41 NGUYỄN DUY KHÁNH[.]

Trang 1

TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI

BÁO CÁO

KỸ THUẬT LẬP TRÌNH

Thực hành sử dụng các cấu dữ liệu cơ bản để

giải quyết các bài toán cụ thể

Trang 2

MỤC LỤC

Bài thực hành 4 – tuần 41: Thực hành sử dụng các cấu trúc dữ liệu cơ bản để giải quyết các bài toán cụ thể

Phần 1 Bài tập thực hành 4

Bài tập 1: Đảo ngược một danh sách liên kết đơn 4

Hãy hoàn thiện các hàm thao tác trên một danh sách liên kết: Thêm một phần tử vào đầu danh sách liên kết; In danh sách; Đảo ngược danh sách liên kết (yêu cầu độ phức tạp thời gian O(N) và chi phí bộ nhớ dùng thêm O(1)) 4

Bài tập 2: Tính diện tích tam giác 6

Một điểm trong không gian 2 chiều được biểu diễn bằng pair Hãy viết hàm double area(Point a, Point b, Point c) tính diện tích tam giác theo tọa độ 3 đỉnh Trong đó, Point là kiểu được định nghĩa sẵn trong trình chấm như sau: using Point = pair; 6

Bài tập 3: Tính tích có hướng của 2 vector 7

Một vector trong không gian 3 chiều được biểu diễn bằng tuple Hãy viết hàm Vector cross_product(Vector a, Vector b) tính tích có hướng của 2 vector Trong đó Vector là kiểu dữ liệu được định nghĩa sẵn trong trình chấm như sau: using Vector = tuple; 7

Bài tập 4: Thao tác với vector 8

Cho hai vector, hãy xóa hết các phần tử chẵn, sắp xếp giảm dần các số trong cả 2 vector và trộn lại thành một vector cũng được sắp xếp giảm dần 8

Bài tập 5: 11

Viết hàm thực hiện thuật toán DFS không sử dụng đệ quy trên đồ thị biểu diễn bằng danh sách kề vector< list > Đồ thị có n đỉnh được đánh số từ 1 đến n Thuật toán DFS xuất phát từ đỉnh 1 Các đỉnh được thăm theo thứ tự ưu tiên từ trái sang phải trong danh sách kề Yêu cầu hàm trả ra thứ tự các đỉnh được thăm (những đỉnh không thể thăm từ đỉnh 1 thì không phải in ra) 11

Bài tập 6: 13

Viết hàm thực hiện thuật toán BFS không sử dụng đệ quy trên đồ thị biểu diễn bằng danh sách kề vector< list > Đồ thị có n đỉnh được đánh số từ 1 đến n Thuật toán BFS xuất phát từ đỉnh 1 Các đỉnh được thăm theo thứ tự ưu tiên từ trái sang phải trong danh sách kề Yêu cầu hàm trả ra thứ tự các đỉnh được thăm (những đỉnh không thể thăm từ đỉnh 1 thì không phải in ra) 13

Bài tập 7: 15

Viết các hàm thực hiện các phép giao và hợp của hai tập hợp được biểu diễn bằng set 15

Bài tập 8: 16 Viết các hàm thực hiện các phép giao và hợp của hai tập hợp mờ được biểu diễn bằng map Trong

đó mỗi phần tử được gán cho một số thực trong đoạn [0 1] biểu thị độ thuộc của phần tử trong tập hợp, với độ thuộc bằng 1 nghĩa là phần tử chắc chắn thuộc vào tập hợp và ngược lại độ thuộc bằng 0 nghĩa là phần tử chắc chắn không thuộc trong tập hợp Phép giao và hợp của 2 tập hợp

Trang 3

được thực hiện trên các cặp phần tử bằng nhau của 2 tập hợp, với độ thuộc mới được tính bằng

phép toán min và max của hai độ thuộc 16

Bài tập 9: 19

Cài đặt thuật toán Dijkstra trên đồ thị vô hướng được biểu diễn bằng danh sách kề sử dụng priority_queue Cụ thể, bạn cần cài đặt hàm vector dijkstra(const vector< vector< pair > >&adj) nhận đầu vào là danh sách kề chứa các cặp pair biểu diễn đỉnh kề và trọng số tương ứng của cạnh Đồ thị gồm n đỉnh được đánh số từ 0 tới n-1 Hàm cần trả vector chứa n phần tử lần lượt là khoảng cách đường đi ngắn nhất từ đỉnh 0 tới các đỉnh 0, 1, 2, , n-1 19

Phần 2: Bài tập về nhà 22

Bài tập 10: Search Engine 22

Xây dựng một máy tìm kiếm (search engine) đơn giản 22

Cho N văn bản và Q truy vấn Với mỗi truy vấn, cần trả về văn bản khớp với truy vấn đó nhất 22

Bài tập 11 Bảo vệ lâu đài 28

Bức tường bao quanh một lâu đài nọ được cấu thành từ nn đoạn tường được đánh số từ 1 đến nn Quân giặc lên kế hoạch tấn công lâu đài bằng cách gửi aiai tên giặc đánh vào đoạn tường thứ ii Để bảo vệ lâu đài có tất cả ss lính 28

Do các đoạn tường có chất lượng khác nhau nên khả năng bảo vệ tại các đoạn tường cũng khác nhau Cụ thể tại đoạn tường thứ ii, mỗi lính có thể đẩy lùi tấn công của kiki tên giặc 28

Giả sử đoạn tường thứ ii có xixi lính Khi đó nếu số tên giặc không vượt quá xi×kixi×ki thì không có tên giặc nào lọt vào được qua đoạn tường này Ngược lại sẽ có ai−xi×kiai−xi×ki tên giặc lọt vào lâu đài qua đoạn tường này 28

Yêu cầu hãy viết chương trình phân bố lính đứng ở các đoạn tường sao cho tổng số lính là ss và tổng số lượng tên giặc lọt vào lâu đài là nhỏ nhất 28

Bài tập 12: Lược đồ 31

Cho một lược đồ gồm nn cột chữ nhật liên tiếp nhau có chiều rộng bằng 1 và chiều cao lần lượt là các số nguyên không âm h1,h2,…,hnh1,h2,…,hn Hãy xác định hình chữ nhật có diện tích lớn nhất có thể tạo thành từ các cột liên tiếp 31

Dữ liệu vào: Dòng thứ nhất chứa số nguyên dương nn (1≤n≤1061≤n≤106) Dòng thứ hai chứa nn số nguyên không âm h1,h2,…,hnh1,h2,…,hn cách nhau bởi dấu cách (0≤hi≤109) 31

Kết quả: In ra số nguyên duy nhất là diện tích hình chữ nhật lớn nhất có thể tạo thành từ các cột liên tiếp của lược đồ 32

Bài tập 13: Đếm xâu con 34

Cho một xâu nhị phân độ dài nn Hãy viết chương trình đếm số lượng xâu con chứa số ký tự 0 và số ký tự 1 bằng nhau 34

Dữ liệu vào: Một dòng duy nhất chứa một xâu nhị phân độ dài nn (1≤n≤106) 34

Kết quả: Ghi ra một số nguyên duy nhất là số lượng xâu con có số ký tự 0 và số ký tự 1 bằng nhau 34

Trang 5

Bài thực hành 4: Thực hành sử dụng các cấu trúc dữ liệu cơ bản để giải quyết các bài toán cụ thể

Phần 1 Bài tập thực hành

Bài tập 1: Đảo ngược một danh sách liên kết đơn

Hãy hoàn thiện các hàm thao tác trên một danh sách liên kết: Thêm một phần tử vào đầu danh sách liên kết; In danh sách; Đảo ngược danh sách liên kết (yêu cầu độ phức tạp thời gian O(N) và chi phí bộ nhớ dùng thêm O(1))

// đẩy một phần tử mới lên đầu danh sách

Node* prepend(Node* head, int data) {

Node* tmp = new Node(data);

tmp->next = head;

return tmp;

}

// in ra noi dung tren mot dong

void print(Node* head) {

Node *tmp = head;

while(tmp != NULL){

Trang 6

//trả lại phần tử đứng đầu mới của danh sách đảo ngược

Node* reverse(Node* head) {

Node* prev = NULL;

Node* next = NULL;

Node* head = NULL;

for (int i = 0; i < n; ++i){

Trang 7

Bài tập 2: Tính diện tích tam giác

Một điểm trong không gian 2 chiều được biểu diễn bằng pair Hãy viết hàm double area(Point a, Point b, Point c) tính diện tích tam giác theo tọa độ 3 đỉnh Trong đó, Point là kiểu được định nghĩa sẵn trong trình chấm như sau: using Point = pair;

Bài làm #include <iostream>

using Point = pair<double, double>;

//hàm trả về diện tích tam giác

double area(Point a, Point b, Point c) {

double ab, bc, ca; // canh cua tam gia abc

//tính độ dài cạnh giữa các điểm

ab = sqrt(pow((a.first-b.first), 2) + pow((a.second-b.second), 2));

Trang 8

cout << "HO VA TEN: Nguyen Duy Khanh Linh\nMSSV: 20204839\n";

cout << setprecision(2) << fixed;

cout << area({1, 2}, {2.5, 10}, {15, -5.25}) << endl;

return 0;

}

Bài tập 3: Tính tích có hướng của 2 vector

Một vector trong không gian 3 chiều được biểu diễn bằng tuple Hãy viết hàm Vector

cross_product(Vector a, Vector b) tính tích có hướng của 2 vector Trong đó Vector là kiểu dữ liệu được định nghĩa sẵn trong trình chấm như sau: using Vector = tuple;

using Vector = tuple<double, double, double>;

//Hàm trả về tích có hướng của hai vector

Vector cross_product(Vector a, Vector b) {

Trang 9

//áp dụng công thức tính tích vô hướng

double x = get<1>(a) * get<2>(b) - get<1>(b) * get<2>(a);

double y = get<2>(a) * get<0>(b) - get<2>(b) * get<0>(a);

double z = get<0>(a) * get<1>(b) - get<0>(b) * get<1>(a);

return Vector (x, y, z);

}

int main() {

cout << "HO VA TEN: Nguyen Duy Khanh Linh\nMSSV: 20204839\n";

cout << setprecision(2) << fixed;

Bài tập 4: Thao tác với vector

Cho hai vector, hãy xóa hết các phần tử chẵn, sắp xếp giảm dần các số trong cả 2 vector và trộn lại thành một vector cũng được sắp xếp giảm dần.

Trang 10

//In ra vector

void print_vector(const vector<int> &a) {

for (int v : a) cout << v << ' ';

//hàm biến đổi vector chỉ còn phần tử lẻ

void delete_even(vector<int> &a) {

//sử dụng lệnh sort() để sắp xếp các phần tử trong vector

void sort_decrease(vector<int> &a) {

sort(a.begin(), a.end(), reduce);

}

//hàm trả về vector gồm các phần tử của vector a, b và đã được sắp xếp

vector<int> merge_vectors(const vector<int> &a, const vector<int> &b) {

Trang 12

cout << "Decreasingly sorted c: ";

Trang 13

//nếu đỉnh tmp chưa được thăm thì đánh dấu đã thăm và in ra màn hình

Trang 17

void print_set(const std::set<T> &a) {

for (const T &x : a) {

std::cout << "Union: "; print_set(c);

std::cout << "Intersection: "; print_set(d);

Trang 18

phần tử chắc chắn không thuộc trong tập hợp Phép giao và hợp của 2 tập hợp được thực hiện trên các cặp phần tử bằng nhau của 2 tập hợp, với độ thuộc mới được tính bằng phép toán min và max của hai

//nếu tồn tại cặp phần tử bằng nhau, độ thuộc bằng max của hai độ thuộc

if(x.first == y.first && tmp == 0) {

c.insert({x.first, max(x.second, y.second)});

Trang 19

for (const auto &x : a) {

std::cout << "(" << x.first << ", " << x.second << ") ";

}

cout << "}";

std::cout << std::endl;

}

Trang 20

std::map<int, double> c = fuzzy_set_union(a, b);

std::map<int, double> d = fuzzy_set_intersection(a, b);

std::cout << "Union: "; print_fuzzy_set(c);

std::cout << "Intersection: "; print_fuzzy_set(d);

}

Bài tập 9:

Cài đặt thuật toán Dijkstra trên đồ thị vô hướng được biểu diễn bằng danh sách kề sử dụng

priority_queue Cụ thể, bạn cần cài đặt hàm vector dijkstra(const vector< vector< pair > >&adj) nhận đầu vào là danh sách kề chứa các cặp pair biểu diễn đỉnh kề và trọng số tương ứng của cạnh Đồ thị gồm n đỉnh được đánh số từ 0 tới n-1 Hàm cần trả vector chứa n phần tử lần lượt là khoảng cách đường đi ngắn nhất từ đỉnh 0 tới các đỉnh 0, 1, 2, , n-1

Trang 21

//xây dựng thứ tự ưu tiên cho hàng đợi

struct compare{

bool operator() (pair<int, int> a, pair<int, int> b){

return a.second > b.second;

}

};

//hàm trả về vector chứa khoảng các đường đi ngắn nhất từ đỉnh 0 tới các đỉnh còn lại

vector<int> dijkstra(const vector< vector< pair<int, int> > >&adj) {

//khởi tạo khoảng cách từ đỉnh 0 tới các đỉnh còn lại

vector<int> dist(adj.size());

int dist_size = dist.size();

for(int i=0; i<dist_size; i++){

dist[i] = INT_MAX;

}

dist[0] = 0; //khoảng cách từ 0 tới 0 bẳng 0

//khởi tạo giá trị hàng đợi ưu tiên

priority_queue<pair<int, int>, vector< pair<int, int> >, compare> q;

for(int i=0; i<dist_size; i++){

q.push({i, dist[i]});

}

while(!q.empty()){

pair<int, int> u_pair = q.top(); q.pop();

int u = u_pair.first; //lấy đỉnh ưu tiên nhất trong q-khoảng cách tới đỉnh 0 nhỏ nhất

//tính lại khoảng cách nhỏ nhất từ đỉnh 0 tới các đỉnh kề của đỉnh u

for(auto v_pair : adj[u]){

int v = v_pair.first;

int weight = v_pair.second;

if(dist[v] > dist[u] + weight){

Trang 22

dist[v] = dist[u] + weight;

vector< vector< pair<int, int> > > adj(n);

auto add_edge = [&adj] (int u, int v, int w) {

Trang 23

add_edge(7, 8, 7);

vector<int> distance = dijkstra(adj);

for (int i = 0; i < distance.size(); ++i) {

cout << "distance " << 0 << "->" << i << " = " << distance[i] << endl;

}

return 0;

}

Phần 2: Bài tập về nhà

Bài tập 10: Search Engine

Xây dựng một máy tìm kiếm (search engine) đơn giản

Cho N văn bản và Q truy vấn Với mỗi truy vấn, cần trả về văn bản khớp với truy vấn đó nhất

Sử dụng phương pháp tính điểm TF-IDF:

 f(t,d)f(t,d) là số lần xuất hiện của từ tt trong văn bản dd

 maxf(d)maxf(d) là giá trị lớn nhất của f(t,d)f(t,d) với mọi tt

Trang 24

• Dòng thứ i trong N dòng tiếp theo thể hiện văn bản i, mỗi dòng là một dãy các từ ngăn cách nhau bởi dấu phẩy

• Dòng tiếp theo chứa số Q

• Dòng thứ i trong Q dòng tiếp theo thể hiện truy vấn thứ i, mỗi dòng là một dãy các từ ngăn cách nhau bởi dấu phẩy

Output: Gồm Q dòng, dòng thứ i là chỉ số của văn bản khớp với truy vấn thứ ii nhất Nếu có nhiều văn

bản có điểm số bằng nhau, in ra văn bản có chỉ số nhỏ nhất

Giới hạn:

 N≤1000N≤1000

 Q≤1000Q≤1000

 Số từ trong mỗi văn bản không quá 10001000

 Số từ trong mỗi truy vấn không quá 1010

 Độ dài mỗi từ không quá 1010

Bài làm

#include<bits/stdc++.h>

using namespace std;

int n, q;

vector< vector<string> > vector_train;

vector< vector<string> > vector_test;

vector<int> f_max; // tần xuất suất hiện của từ xuất hiện nhiều nhất trong văn bản i

map<string, int> df; //số văn bản từ word có xuất hiện

map<pair<string, int>, int> fe; // trong văn bản i, từ word xuất hiện bao nhiêu lần <word, i> = int // split string

vector<string> split_string(string str){

vector<string> vt;

while (!str.empty()){

string tmp = str.substr(0, str.find(","));

int pos = tmp.find(" ");

if(pos > tmp.size()) vt.push_back(tmp);

else {

while(pos <= tmp.size()){

Trang 25

if (str.find(",") > str.size()) break;

else str.erase(0, str.find(",") + 1);

Trang 26

map<string, int>::iterator ite = m.find(word_tmp);

if(ite == m.end()){ //nếu từ này xuất hiện trong từ điển mini

m.insert({word_tmp, 1});

} else ite->second += 1; //nếu không thì

max_f = max(m[word_tmp], max_f);

Trang 27

int frequence_word_int_document_i(string word, int i){

if(fe.find({word, i}) != fe.end()){ //nếu đã có trong kho thì lấy ra để trả về luôn

return fe[{word, i}];

}

int index = 0;

vector<string> str_tmp = vector_train[i];

for(string v : str_tmp if(word == v) index++;

fe.insert({{word, i}, index});

return index;

}

//tính số văn bản có xuất hiện từ word

int count_document_contain_word(string word){

if(df.find(word) != df.end()){ //nếu đã có trong kho thì lấy ra để trả về luôn

Trang 28

vector<string> list_word_train_doc = vector_train[i];

double score = 0;

for(string word : list_word){

if(find(list_word_train_doc.begin(), list_word_train_doc.end(), word) == list_word_train_doc.end()){ //nếu từ này không xuất hiện trong văn bản

continue;

} else {

int ftd = frequence_word_int_document_i(word, i);

int dft = count_document_contain_word(word);

int maxfd = f_max[i];

double tf_word = 0.5 + 0.5 * ((double) ftd / maxfd);

double idf_word = log2((double) n / dft);

score += tf_word * idf_word;

Trang 29

for(int i=0; i<q; i++) cout << search_engine(vector_test[i]) << endl;

return 0;

}

Bài tập 11 Bảo vệ lâu đài

Bức tường bao quanh một lâu đài nọ được cấu thành từ nn đoạn tường được đánh số từ 1 đến nn Quân giặc lên kế hoạch tấn công lâu đài bằng cách gửi aiai tên giặc đánh vào đoạn tường thứ ii Để bảo

Yêu cầu hãy viết chương trình phân bố lính đứng ở các đoạn tường sao cho tổng số lính là ss và tổng số lượng tên giặc lọt vào lâu đài là nhỏ nhất

Bài làm

Ngày đăng: 03/03/2023, 06:33

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w