Checkpoint 6 tháng đầu năm 2023 (Bài tham khảo)

4 min read

checkpoint

Hello mọi người, đây là solution của e cho checkpoint 6 tháng đầu năm 2023.

Ý tưởng:

Tạo mảng Profits với kích N, với Profit[i] lưu lợi nhuận tối đa khi bán cổ phiếu tại thời điểm i:

=> Profit[i] = Giá tại vị trí i – Giá nhỏ nhất trước vị trí i;

Kết quả = Max(Profits)

Tối ưu:

Dùng biến CurrentMin (giá trị cổ phiếu nhỏ nhất tính đến hiện tại, khởi tạo = 10^6), CurrentMaxProfit (Lợi nhuận lớn nhất tính đến hiện tại, khởi tạo = 0).

Duyệt qua từng phần tử trong danh sách cổ phiếu:

  • Nếu: giá trị hiện tại < CurrentMin => cập nhật lại CurrentMin = giá trị hiện tại, continue
  • Nếu: giá trị hiện tại – CurrentMin > CurrentMaxProfit => cập nhật lại CurrentMaxProfit = giá trị hiện tại – CurrentMin

Code tham khảo:

N = int(input());
arr = [int(i) for i in input().split()];
CurrentMin = 1000000;
CurrentMaxProfit = 0;
for i in arr:
    if i < CurrentMin:
        CurrentMin = i;
        continue;
    if CurrentMaxProfit < i - CurrentMin:
        CurrentMaxProfit = i - CurrentMin;
print(CurrentMaxProfit);

Để người tại vị trí i đứng khi kết thúc thì số ước số của i phải là số lẻ, để điều đó xảy ra i phải là số chính phương.

=> Đề bài : Tìm số chính phương lớn nhất <= N

Code ví dụ:

import math
print(int(math.sqrt(int(input())) // 1))

Ý tưởng:

Gom các máy được liên kết với nhau thành cụm => Số dây ít nhất = Số cụm – 1

Thuật toán dùng để gom cụm có thể dùng DSU (Disjoint Sets Union)

Code tham khảo:

class GomCum:
    def __init__(self, n):
        self.parent = [i for i in range(n)]
        self.rank = [0 for i in range(n)]

    def findRoot(self, x):
        if self.parent[x] != x:
            return self.findRoot(self.parent[x])
        return self.parent[x]

    def noi2May(self, x, y):
        x_root = self.findRoot(x)
        y_root = self.findRoot(y)
        if x_root == y_root:
            return
        if self.rank[x_root] < self.rank[y_root]:
            self.parent[x_root] = y_root
        elif self.rank[x_root] > self.rank[y_root]:
            self.parent[y_root] = x_root
        else:
            self.parent[y_root] = x_root
            self.rank[x_root] += 1
    def soDayItNhat(self, n):
        return len(set([self.findRoot(i) for i in range(n)])) - 1

[n, m] = [int(i) for i in input().split()]
res = GomCum(n)
for i in range(m):
    [a, b] = [int(i) for i in input().split()]
    res.noi2May(a, b)
if m < n - 1 :
    print(-1)
print(res.soDayItNhat(n))

Chạy vòng lặp. Khi 1 trong 2 chuỗi đã hết ký tự trong vòng lặp, thực hiện so sánh

Các case có thể gặp:

  • 2 chuỗi khác tiền tố => Lấy ký tự đầu của chuỗi nhỏ hơn
  • 2 chuỗi cùng tiền tố =>Lấy ký tự đầu của chuỗi có ký tự sau phần tiền tố chung nhỏ hơn (‘ABCD’ vs ‘ABCC’ => Lấy A trong ABCC)
  • 2 chuỗi giống nhau => Lấy ký tự đầu của dãy nào cũng được
  • 1 chuỗi là tiền tố của 1 chuỗi khác => Lấy ký tự đầu của dãy dài hơn ( Test thử với các case trong trường hợp này có thể đúc kết ra)

Code tham khảo:

def GetKey(d1, d2):
    res = ''
    while len(d1) and len(d2) :
        Len = min(len(d1), len(d2))
        if d1[:Len] < d2[:Len]:
            res += d1[0]
            d1 = d1[1:]
            continue                            

        if d2[:Len] < d1[:Len]:
            res += d2[0]
            d2 = d2[1:]
            continue    

        if len(d1) > len(d2):
            res += d1[0]
            d1 = d1[1:]
            continue                                        
        if len(d2) >= len(d1):
            res += d2[0]
            d2 = d2[1:]
            continue                                        

    if len(d1) != 0:
        return res + d1
    if len(d2) != 0:
        return res + d2    
    return res

n = int(input())
key = []
for i in range(n):
    d1 = input() 
    d2 = input() 
    key.append(GetKey(d1, d2))
[print(i) for i in key]

Bài này chúng ta có thể giải bằng quy hoạch động:

Dùng 1 list ArrRes N phần tử, ArrRes[i] = (Min tổng các dự án bị loại bỏ từ 0 -> i) + Vi

Triển khai:

Tạo 1 store để lưu min tổng các dự án bị loại bỏ từ 0 -> i

Duyệt từ dự án đầu đến dự án cuối:

1) Nếu: i < k + 1: thêm vi vào store, ArrRes[i] = Vi, continue

2) ArrRes[i] = Vi + min(store)

3) xóa ArrRes[i – k – 1] khỏi store

Tối ưu store dùng BinarySearchTree

Code tham khảo:

class BinarySearchTree:
    class Node:
        def __init__(self, value):
            self.value = value
            self.left = None
            self.right = None

    def __init__(self):
        self.root = None
        self.min_value = None

    def add(self, value):
        if self.root is None:
            self.root = self.Node(value)
            self.min_value = value
        else:
            self._add_recursive(self.root, value)

        if value < self.min_value:
            self.min_value = value

    def _add_recursive(self, node, value):
        if value < node.value:
            if node.left is None:
                node.left = self.Node(value)
            else:
                self._add_recursive(node.left, value)
        else:
            if node.right is None:
                node.right = self.Node(value)
            else:
                self._add_recursive(node.right, value)

    def remove(self, value):
        self.root = self._remove_recursive(self.root, value)

        if value == self.min_value:
            if self.root is None:
                self.min_value = None
            else:
                node = self.root
                while node.left is not None:
                    node = node.left
                self.min_value = node.value

    def _remove_recursive(self, node, value):
        if node is None:
            return None

        if value < node.value:
            node.left = self._remove_recursive(node.left, value)
        elif value > node.value:
            node.right = self._remove_recursive(node.right, value)
        else:
            if node.left is None:
                return node.right
            elif node.right is None:
                return node.left
            else:
                successor = self._find_min(node.right)
                node.value = successor.value
                node.right = self._remove_recursive(node.right, successor.value)

        return node

    def _find_min(self, node):
        if node.left is None:
            return node
        return self._find_min(node.left)

    def begin(self):
        return self.min_value

    def add_list(self, values):
        for value in values:
            self.add(value)


def solve(n, x):
    if n == 0:
        return 0

    Max = sum(arr)
    if x >= n:
        return Max

    store = BinarySearchTree()
    store.add_list(arr[:x + 1])

    for i in range(x + 1, n):
        arr[i] = arr[i] + store.begin() 
        store.remove(arr[i - x - 1])
        store.add(arr[i])
    return Max - store.begin()

n, x = map(int, input().split())
arr = [int(input()) for _ in range(n)]
print(solve(n, x))

Avatar photo

Clean Code: Nguyên tắc viết hàm trong lập trình…

Trong quá trình phát triển phần mềm, việc viết mã nguồn dễ đọc, dễ hiểu là yếu tố then chốt để đảm bảo code...
Avatar photo Dat Tran Thanh
3 min read

Leave a Reply

Your email address will not be published. Required fields are marked *