Hướng dẫn giải của duong3982oj Contest 01 - Dãy hình nón


Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.

Subtask 1: ~n \le 5~

  • Duyệt tất cả các hoán vị của mảng ~a~ để tìm xem số lần chia đoạn ít nhất thỏa mãn đề bài.

Độ phức tạp: ~O(n!)~

Subtask 2: ~n \le 20~

Ta có thể duyệt vét cạn khéo léo hơn, hoặc sử dụng DP bitmask.

Độ phức tạp: ~O~ ~(2^n * n^2)~.

Subtask 3 + Subtask 4: ~n \le 50~

Nhận xét: Ta sẽ chỉ cắt đoạn ở vị trí ~i~ mà ở đó, ~a_i \neq a_{i - 1}~ để đảm bảo số lần cắt là ít nhất. Chính vì vậy, ta sẽ nén mảng (ví dụ, từ {~1, 1, 2, 2, 3, 3~} xuống còn {~1, 2, 3~}) rồi quy hoạch động trên mảng đó.

Giả sử một đoạn ~[l, r]~ là dãy hình nón thỏa mãn, ta sẽ gọi ~a_i~ là "đỉnh nón" khi ~a_i = max(a_l, a_{l+1}, ..., a_r)~

Đầu tiên, ta sẽ nén số mảng ~a~ lại. Gọi ~dp_{a_i, l, r}~ là số lần cắt ít nhất với ~i~ là đỉnh nón trong đoạn từ ~l~ đến ~r~.

-> Với cách tiếp cận này, đáp số bài toán chính là min(~dp_{a_i, i, i + 1}~) với mọi vị trí ~i~ là đỉnh nón trong mảng ~a~.

Vậy, với mọi ~dp_{a_i, l, r}~, ta sẽ làm như sau:

int dp (int mid, int l, int r){
    if (mid == -1) return L[l] + R[r - 1];
    if (f[mid][l][r] != -1) return f[mid][l][r];
    int val = (s[l] == mid);
    if (l && s[l - 1] == mid){
        l--; val++;
    }
    if (r < n && s[r] == mid && l != r){
        val++; r++;
    }
    if (pos[mid].size () == val) return dp (mid - 1, l, r);
    int b = 0;
    if (s[l] != mid) b += L[l];
    if (s[r - 1] != mid) b += R[r - 1];
    int ret = n;
    for (int i : pos[mid]){
        if (i == l || i == r - 1) continue;
        ret = min ({ret, dp (mid - 1, i, r) - L[i] - R[r - 1], dp (mid - 1, l, i + 1) - L[l] - R[i]});
        for (int j : pos[mid]){
            if (j != l && j + 1 != r && j != i) ret = min (ret, dp (mid - 1, i, j + 1) - L[i] - R[j]);
        }
    }
    return f[mid][l][r] = ret + b + base[mid];
} 

với ~s_i~ là phần tử thứ ~i~ của dãy sau khi đã nén, ~n~ là số phần tử của dãy đã nén.

Độ phức tạp: ~O~ ~(n^3)~.


Bình luận

Hãy đọc nội quy trước khi bình luận.


Không có bình luận tại thời điểm này.