Hướng dẫn thuật toán

Trùm CUỐI 2026-01-11 10:51:55

Link bài tập

1. Phân tích đề bài

  • Mục tiêu: Tìm số lượng xu ít nhất để tổng bằng x .
  • Đặc điểm: Một mệnh giá có thể dùng nhiều lần (bài toán Knapsack dạng không giới hạn số lượng).
  • Ràng buộc: x lên đến 10^6 , n lên đến 100 . Thuật toán cần có độ phức tạp khoảng O(n \cdot x) để chạy kịp thời gian.

2. Ý tưởng thuật toán

Chúng ta sẽ dùng một mảng để lưu trữ kết quả tối ưu của các bài toán con từ 0 đến x .

  • Gọi dp[i] là số lượng xu tối thiểu để tạo ra tổng bằng i.
  • Mục tiêu cuối cùng là tìm giá trị của dp[x].

3. Các bước thực hiện

  1. Khởi tạo:

    • Tạo mảng dp có kích thước x + 1 .
    • Đặt dp[0] = 0 (để có tổng bằng 0 thì cần 0 đồng xu).
    • Tất cả các vị trí khác dp[1...x] khởi tạo bằng một giá trị vô cực (một số lớn hơn x , ví dụ: 10^9 ) để đánh dấu là chưa thể đạt tới.
  2. Trạng thái chuyển đổi (Công thức quy hoạch động):

    • Duyệt qua từng giá trị mục tiêu i từ 1 đến x .
    • Với mỗi giá trị i , thử dùng lần lượt từng loại mệnh giá c_j trong danh sách:
      • Nếu i \ge c_j và có thể tạo được tổng (i - c_j) (tức là dp[i - c_j] khác vô cực):
      • Cập nhật: dp[i] = min(dp[i], dp[i - c_j] + 1).
  3. Kết quả:

    • Sau khi lặp xong, kiểm tra giá trị tại dp[x].
    • Nếu dp[x] vẫn là vô cực, in ra -1.
    • Ngược lại, in ra giá trị dp[x].