You are on page 1of 53

Thẩm Lập Phong – MSSV 20215449

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


****************

BÁO CÁO THỰC HÀNH


MÔN KỸ THUẬT LẬP TRÌNH
MÃ HỌC PHẦN IT3040

BUỔI SỐ 04 – TUẦN 39

Sinh viên thực hiện: Thẩm Lập Phong 20215449


Lớp: Khoa học máy tính 02 – K66
Mã lớp thực hành: 727637
GVHD: ThS. Lê Thị Hoa

Hà Nội, 2023

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449

Mục lục
Bài thực hành số 4 – Tuần 39 ................................................................................................................... 3
Bài tập 4.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)) .............................................. 3
Bài tập 4.2. 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 tính diện tích
tam giác theo tọa độ 3 đỉnh. ................................................................................................................. 7
Bài tập 4.3. Một vector trong không gian 3 chiều được biểu diễn bằng tuple<double, double, double>.
Hãy viết hàm tính tích có hướng của 2 vector. ...................................................................................... 8
Bài tập 4.4. Cho hai std::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. ......................................................... 9
Bài tập 4.5. Viết hàm void dfs(vector< list<int> > adj) 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ề. Đồ 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).. .... 13
Bài tập 4.6. Viết hàm void bfs(vector< list<int> > adj) 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ề. Đồ 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). ..... 16
Bài tập 4.7. 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. ... 17
Bài tập 4.8 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 đượ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.. ....................................................................................................................... 20
Bài tập 4.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
std::priority_queue Cụ thể, bạn cần cài đặt hàm vector<int> dijkstra(const vector< vector< pair<int,
int> > >&adj) nhận đầu vào là danh sách kề chứa các cặp pair<int, int> 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<int>` 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. .................. 23
Bài tập 4.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.. ..................................... 26
Bài tập 4.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ừ n đoạn tường
được đánh số từ 1 đến n . Quân giặc lên kế hoạch tấn công lâu đài bằng cách gửi ai tên giặc đánh vào
đoạn tường thứ i . Để bảo vệ lâu đài có tất cả s lính. 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ứ i , mỗi lính có thể đẩy

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
lùi tấn công của ki tên giặc. Giả sử đoạn tường thứ i có xi lính. Khi đó nếu số tên giặc không vượt
quá xi×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×ki tên
giặc lọt vào lâu đài qua đoạn tường này. 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à s và tổng số lượng tên giặc lọt vào lâu đài là nhỏ nhất. . ....................... 37
Bài tập 4.12. Lược đồ Cho một lược đồ gồm n 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,…,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..................................................................................... 42
Bài tập 4.13. Đếm xâu con Cho một xâu nhị phân độ dài n . 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. ..................................................................................... 48

Bài thực hành số 4 – Tuần 39


Bài tập 4.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))
Source code:

#include <iostream>
using namespace std;
// Tham Lap Phong 20215449
struct Node {
int data;
Node* next;

Node(int data) {
this->data = data;
next = NULL;
}
};

// push a new element to the beginning of the list


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

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
Node* new_node = new Node(data);
new_node -> next = head;
head = new_node;
return head;
}

// print the list contenth on a line


void print(Node* head) {
Node *tmp = head;
while(tmp != NULL){
printf("%d ",tmp->data);
tmp = tmp->next;
}
cout << endl;
}

// return the new head of the reversed list


Node* reverse(Node* head) {
Node* current = head->next;
Node* prev = head; prev->next = NULL;
Node* next = NULL;
while(current != NULL){
next = current->next;
current->next = prev;

prev = current;
current = next;

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
}
head = prev;

return head;
}

int main() {
int n, u;
cin >> n;
Node* head = NULL;
for (int i = 0; i < n; ++i){
cin >> u;
head = prepend(head, u);
}

cout << "Original list: ";


print(head);

head = reverse(head);

cout << "Reversed list: ";


print(head);

return 0;
}
return 0;
}

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449

Bài tập 4.2. 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
tính diện tích tam giác theo tọa độ 3 đỉnh.
SOURCE CODE:
#include <iostream>
#include <cmath>
#include <iomanip>
#include <utility>
using namespace std;
using Point = pair<double, double>;

double distance(Point a, Point b){


return sqrt((a.first - b.first)*(a.first - b.first) + (a.second - b.second)*(a.second -
b.second));
}

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


double distance (Point a,Point b){
return sqrt((a.first - b.first)*(a.first - b.first) +(a.second - b.second)*(a.second -
b.second));
}
double area(Point a, Point b, Point c) {

double ab = distance(a,b);
double ac = distance(a,c);
double bc = distance(b,c) ;
double p = (ab+bc+ac)/2;
return sqrt(p * (p-ab) * (p-bc) * (p-ac));
}
}

int main() {
cout << setprecision(2) << fixed;
cout << area({1, 2}, {2.5, 10}, {15, -5.25}) << endl;
return 0;
}

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449

Bài tập 4.3. Một vector trong không gian 3 chiều được biểu diễn bằng tuple<double,
double, double>. Hãy viết hàm tính tích có hướng của 2 vector.
SOURCE CODE:

// Tham Lap Phong 20215449

Vector cross_product(Vector a, Vector b) {

double c0 = get<1>(a)*get<2>(b) - get<1>(b)*get<2>(a),

c1 = get<2>(a)*get<0>(b) - get<2>(b)*get<0>(a),

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

return Vector{c0,c1,c2};

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449

Bài tập 4.4. Cho hai std::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.
SOURCE CODE:
#include <iostream>

#include <vector>

#include <algorithm>

using namespace std;

// Tham Lap Phong 20215449

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

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

cout << endl;

bool compare(int a, int b){

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
return a > b;

vector<int> delete_even(vector<int> &a) {

vector<int> tmp;

for(int v : a){

if(v % 2 != 0) tmp.push_back(v);

return tmp;

void sort_decrease(vector<int> &a) {

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

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

vector<int> sum;

for(int v : a){

sum.push_back(v);

for(int v : b){

sum.push_back(v);

sort(sum.begin(), sum.end(), compare);

return sum;

int main() {

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449

int m, n, u;

std::vector<int> a, b;

std::cin >> m >> n;

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

std:: cin >> u;

a.push_back(u);

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

std:: cin >> u;

b.push_back(u);

a = delete_even(a);

cout << "Odd elements of a: ";

print_vector(a);

b = delete_even(b);

cout << "Odd elements of b: ";

print_vector(b);

sort_decrease(a);

cout << "Decreasingly sorted a: ";

print_vector(a);

sort_decrease(b);

cout << "Decreasingly sorted b: ";

print_vector(b);

vector<int> c = merge_vectors(a, b);

cout << "Decreasingly sorted c: ";

print_vector(c);

return 0;

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449

Bài tập 4.5. Viết hàm void dfs(vector< list<int> > adj) 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ề. Đồ 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)..
SOURCE CODE:
void dfs(vector< list<int> > adj) {

stack<int> S;

vector<bool> visited(adj.size());

S.push(1); // Bắt đầu từ đỉnh số 1

while (!S.empty()) {

int u=S.top();

if (!visited[u]){

visited[u] = true;

std::cout<< u << std::endl;

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
if (!adj[u].empty()){

int v=adj[u].front(); adj[u].pop_front();

if(!visited[v]){

S.push(v);

}else { S.pop();}

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
}

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
Bài tập 4.6. Viết hàm void bfs(vector< list<int> > adj) 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ề. Đồ 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).
SOURCE CODE:
// Tham Lap Phong 2021549

void bfs(vector< list<int> > adj) {

queue<int> Q;

vector<bool> visited(adj.size());

Q.push(1); // Bắt đầu từ đỉnh số 1

while (!Q.empty()) {

int u=Q.front();

if (!visited[u]){

visited[u] = true;

std::cout<< u << std::endl;

if (!adj[u].empty()){

int v=adj[u].front(); adj[u].pop_front();

if(!visited[v]){

Q.push(v);

}else { Q.pop();}

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449

Bài tập 4.7. 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.
Source code:
// Tham Lap Phong 20215449

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
template<class T>

set<T> set_union(const set<T> &a, const set<T> &b) {

set<T> c;

for(T v:a){

c.insert(v);

for (T v: b){

c.insert (v);

return c;

template<class T>

set<T> set_intersection(const set<T> &a, const set<T> &b) {

set <T> c;

for (T v : a){

int index =0;

for (T u : b){

if (v==u) index++;

if (index != 0)

c.insert(v);

return c;

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
}

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449

Bài tập 4.8 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 đượ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..
SOURCE CODE:
// Tham Lap Phong 20215449

template<class T>

map<T, double> fuzzy_set_union(const map<T, double> &a, const map<T, double> &b) {

map<T, double> ans;

for (auto v : a){

double second = v.second;

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
for (auto u : b){

if (v.first == u.first){

second = max(second, u.second);

break;

ans.insert({v.first, second});

for (auto v : b){

double second = v.second;

for (auto u : a){

if (v.first == u.first){

second = max(second, u.second);

break;

ans.insert({v.first, second});

return ans;

template<class T>

map<T, double> fuzzy_set_intersection(const map<T, double> &a, const map<T, double> &b) {

map<T, double> ans;

for (auto v : a){

for (auto u : b){

if (v.first == u.first){

ans.insert({v.first, min(v.second, u.second)});

break;

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
}

return ans;

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449

Bài tập 4.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 std::priority_queue Cụ thể, bạn cần cài đặt hàm vector<int>
dijkstra(const vector< vector< pair<int, int> > >&adj) nhận đầu vào là danh sách kề chứa
các cặp pair<int, int> 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<int>` 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.
Source Code:

// Tham Lap Phong 20215449

struct comp{

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

return a.second > b.second;

};

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

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

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
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; // khoang cach tu 0 -> 0 = 0

// khoi tao gia tri cho hang doi uu tien

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; // lay ra dinh co thu tu uu tien nhat trong hang doi

for (auto v_pair : adj[u]){

int v = v_pair.first;

int weight = v_pair.second;

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

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

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

return dist;

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449

Bài tập 4.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..
Source code

#include<iostream>

#include<cmath>

#include<cstring>

#include<vector>

#include<map>

#include<queue>

using namespace std;

//??nh ngh?a l?i so sánh trong priority queue

//priority queue ch?a các c?p (x,y) trong ?ó x là s? hi?u v?n b?n, y là ?i?m s? c?a v?n b?n ?ó

struct cmp{

bool operator () (pair<int,int> x,pair<int,int> y){

//V?n b?n ?i?m cao s? ? trên cùng

if( x.second>y.second) return false;

//2 v?n b?n cùng ?i?m th́ v?n b?n có s? hi?u th?p h?n s? ? trên

else if(x.second==y.second) if(x.first<y.first) return false;

else return true;

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
else return true;

};

//So lan xuat hien t trong d

int f(string t,int d,vector<vector<string>> &a){

int dem=0;

for(string x: a[d]) {if(t==x) dem=dem+1;}

return dem;

// T́m max f(t,d) v?i m?i t thu?c v?n b?n d

int max(int d,vector<vector<string>> &a){

//1 t? s? t??ng ?ng v?i s? l?n nó xu?t hi?n

map<string,int> M;

for(string x:a[d]) M[x]++;

int max=0;

for(auto x:M) {

//max ch?a s? l?n xu?t hi?n nhi?u nh?t c?a t? xu?t hi?n nhi?u nh?t

if (x.second>max) max=x.second;

return max;

//S? v?n b?n ch?a t? t

int df(string t,vector<vector<string>> &a){

int dem=0;

for(auto x:a){

for(auto y:x){

if(y==t) {

//có ch?a t break sang v?n b?n ti?p theo

dem++;

break;}

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
}

return dem;

//Hàm tính ?i?m v?n b?n d v?i t? t

double tscore(string t,int d,vector<vector<string>> &a,int N){

//t không xu?t hi?n trong d th́ ?i?m b?ng 0

if (f(t,d,a)==0) return 0;

//Tính ?i?m theo công th?c

double TF=0.5+0.5*f(t,d,a)/max(d,a);

double IDF=log2(N/df(t,a));

return TF*IDF;

int main(){

//Nh?p d? li?u t? file input.txt

freopen("input.txt","r",stdin);

int N,Q;

cin>>N;

getchar();

//VB ch?a các vector là các v?n b?n, các vector ?ó ch?a các t? trong v?n b?n

vector<vector<string>> VB;

VB.resize(N);

//Nh?p các v?n b?n

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

string str;

str.resize(10);

char c;

//Bi?n dem dùng ?? nh?p kí t? vào xâu

int dem=0;

L0: do{

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
c=getchar();

if(c=='\n') goto L1;//c là xu?ng ḍ ng th́ nha? L1:cho xâu ?ang dang d? thành 1 t? vào v?n b?n hi?n
th?i,b? ??m v? 0,reset str

else if(c==',') goto L2;//c là d?u ph?y th́ l?u xâu ?ó thành m?t t?, dem v? 0,reset str và quay L0 b?t
??u t? ti?p theo

else{

str[dem]=c;

dem++;}

}while(1);

L2:{

VB[i].push_back(str);

dem=0;

str.clear();

str.resize(10);

goto L0;};

L1:{

VB[i].push_back(str);

dem=0;

str.clear();

str.resize(10);

};

//Nh?p các truy v?n t??ng t? nh?p v?n b?n

cin>>Q;

getchar();

vector<vector<string>> TV;

TV.resize(Q);

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

string str;

str.resize(10);

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
char c;

int dem=0;

L3: do{

c=getchar();

if(c=='\n') goto L4;

else if(c==',') goto L5;

else{

str[dem]=c;

dem++;}

}while(1);

L5:{

TV[i].push_back(str);

dem=0;

str.clear();

str.resize(10);

goto L3;};

L4:{

TV[i].push_back(str);

dem=0;

str.clear();

str.resize(10);

};

//Hàng ??i ?u tiên

priority_queue<pair<int,int>,vector<pair<int,int>>,cmp> pq;

//V?i m?i truy v?n

for(auto x:TV){

//V?i m?i v?n b?n i

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

double score=0;

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
//V?i m?i t? y thu?c truy v?n x ta tính ?i?m v?i t?ng v?n b?n i và c?ng d?n l?i

for(auto y:x){

score=score+tscore(y,i,VB,N);

//Ta ??y ?i?m c?a v?n b?n i v?i truy v?n x và hàng ??i

pq.push(make_pair(i,score));

//L?y ra ??nh c?a hàng ??i chính là ?i?m cao nh?t v?i truy v?n x, ta c?ng 1 do truy v?n ?ánh s? t? 1

cout<<pq.top().first+1<<endl;

//xóa hàng ??i chu?n b? sang truy v?n ti?p theo

while(!pq.empty()) {pq.pop();}

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449

*VÌ case test dài nên em xin phép chỉ để ảnh output
CASE 1:

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449

CASE 2:

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449

CASE 3:

CASE 4

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449

CASE 5:

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449

Bài tập 4.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ừ n
đoạn tường được đánh số từ 1 đến n . Quân giặc lên kế hoạch tấn công lâu đài bằng cách
gửi ai tên giặc đánh vào đoạn tường thứ i . Để bảo vệ lâu đài có tất cả s lính. 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ứ i , mỗi lính có thể đẩy lùi tấn công của ki tên giặc. Giả
sử đoạn tường thứ i có xi lính. Khi đó nếu số tên giặc không vượt quá xi×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×ki tên giặc lọt
vào lâu đài qua đoạn tường này. 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à s và tổng số lượng tên giặc lọt vào lâu đài là nhỏ nhất.
.
SOURCE CODE:
#include<bits/stdc++.h>
using namespace std;
struct data {
int ai;
int ki;

data(int ai, int ki){


this->ai = ai;
this->ki = ki;
}

};
struct compare{
bool operator() (data a, data b){
int ra, rb;

if(a.ai <= a.ki) ra = a.ai;


else ra = a.ki;

if(b.ai <= b.ki) rb = b.ai;

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
else rb = b.ki;

return ra < rb;


}

};
int n, s, kill_enemy, total_enemy;
priority_queue<data, vector<data>, compare> p_q;
void input(){
cin >> n >> s;

kill_enemy = 0;
total_enemy = 0;
for(int i=0; i<n; i++){
int tmp1, tmp2;
cin >> tmp1 >> tmp2;

total_enemy += tmp1;
p_q.push(data(tmp1, tmp2));
}
}
void solve(){

while(!p_q.empty() && s>0){


data inf = p_q.top(); p_q.pop();

if(inf.ai <= inf.ki){


kill_enemy += inf.ai;

} else {
int nenemy = inf.ai - inf.ki;
p_q.push(data(nenemy, inf.ki));
kill_enemy += inf.ki;

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
}

s -= 1;
}

}
int calc_enemy(){
return total_enemy - kill_enemy;
}
int main(){

input();
solve();
cout << calc_enemy();
return 0;
}

CASE 1:

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449

case 2:

CASE 3:

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449

CASE 4:

CASE 5:

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449

Bài tập 4.12. Lược đồ Cho một lược đồ gồm n 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,…,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.
Source code:

#include<bits/stdc++.h>

using namespace std;

long long n;

vector<long long> vt;

vector<long long> L; // mang trai luu tru gia tri ben trai gan nhat nho hon gia tri dang xet

vector<long long> R; // mang phai luu tru gia tri ben phai gan nhat nho hon gia tri dang
xet

void inputData(){

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
cin >> n;

vt.push_back(-1); // Dat linh canh o 2 dau mang

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

long long tmp;

cin >> tmp;

vt.push_back(tmp);

vt.push_back(-1); // Dat linh canh o 2 dau mang

void solve(){

while(true){

inputData();

if(n==0) return;

// Xu ly o day

stack<long long> st; // 1 stack de thuc hien thuat toan ghi ra cac gia tri L, R

L.resize(n+2);

R.resize(n+2);

for(long long i=1; i<=n+1; i++){

while(!st.empty() && vt[i] < vt[st.top()]){

L[st.top()] = i;

st.pop();

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
}

st.push(i);

for(long long i=n; i>=0; i--){

while(!st.empty() && vt[i] < vt[st.top()]){

R[st.top()] = i;

st.pop();

st.push(i);

long long maxh = 0;

for(long long i=1; i<=n; i++){

long long h = (L[i] - R[i] -1)*vt[i];

if(h > maxh) maxh = h;

cout << maxh << endl; break;

// Xoa mang truoc khi bat dau vong lap moi ( mang vt, mang L, mang R)

vt.erase(vt.begin(),vt.end());

L.erase(L.begin(),L.end());

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
R.erase(R.begin(),R.end());

int main(){

solve();

return 0;

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449

TEST CASE:
CASE 1:

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
CASE 2:

CASE 3:

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449

CASE 4:

Bài tập 4.13. Đếm xâu con Cho một xâu nhị phân độ dài n . 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.

Source code:

#include<bits/stdc++.h>

using namespace std;

const int MAX = 1000000;

string str;

int n, cnt;

int slg0[MAX]; // slg0[i] la dem so luong so 0 trong khoang 0 toi i

int slg1[MAX]; // slg0[i] la dem so luong so 1 trong khoang 0 toi i

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
void input(){

cnt = 0;

cin >> str;

n = str.length();

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

if(i==0){

if(str[i] == '0'){

slg0[i] = 1;

slg1[i] = 0;

} else {

slg0[i] = 0;

slg1[i] = 1;

continue;

if(str[i] == '0'){

slg0[i] = slg0[i-1] + 1;

slg1[i] = slg1[i-1];

} else {

slg0[i] = slg0[i-1];

slg1[i] = slg1[i-1] + 1;

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
}

void solve(){

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

for(int j=i+1; j<n; j = j + 2){

if(i==0){

if(slg0[j] == slg1[j]) cnt++;

} else {

int c0 = slg0[j] - slg0[i-1];

int c1 = slg1[j] - slg1[i-1];

if(c0 == c1) cnt++;

int main(){

ios_base::sync_with_stdio(false); cin.tie(NULL);

input();

solve();

cout << cnt;

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
return 0;

TEST CASE:

CASE 1

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449
CASE 2:

Case 3:

CASE 4:

IT3040 – 2022.2 – Mã lớp TH: 727637


Thẩm Lập Phong – MSSV 20215449

CASE 5:

IT3040 – 2022.2 – Mã lớp TH: 727637

You might also like