D. Learning to Paint

纯粹的發表於2024-07-19

原題連結

題解

dp+多次優先佇列

\(dp[i]\)\([1,i]\) 區間內,前 \(k\) 個最大值(有可能不足k個)(注意 \(dp[i]\) 是一個序列)

\(dp[i]=\{dp[j][t]+a[j+2][i],j\in[0,i-2],t\in[0,top_j]\} ,\sum t=k\)

code

#include <bits/stdc++.h>
#define ll long long
using namespace std;

int a[1005][1005];

struct Compare {
    bool operator()(const array<int, 4>& a, const array<int, 4>& b) {
        return a[3] < b[3];
    }
};

void solve()
{
    int n, k;
    cin >> n >> k;

    for (int i = 1; i <= n; i++)
        for (int j = i; j <= n; j++) cin >> a[i][j];


    vector<vector<int>> dp(n + 5);
    dp[0].push_back(0);

    for (int i = 1; i <= n; i++)
    {
        priority_queue<array<int, 4>, vector<array<int, 4>>, Compare> q;

        q.push({i+1, i - 1, 0, dp[i - 1][0]});

        for (int j = i; j >= 1; j--)  q.push({j, max(0,j - 2), 0, a[j][i] + dp[max(0,j-2)][0]});


        while (!q.empty() && dp[i].size() < k)
        {
            auto [l, it, cnt, val] = q.top();
            q.pop();

            dp[i].push_back(val);
            if (cnt +1< dp[it].size()) q.push({l, it, cnt + 1, dp[it][cnt+1] + a[l][i]});
        }
    }


    for(auto it:dp[n]) cout<<it<<' ';cout<<'\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t = 1;
    cin >> t;
    while (t--) solve();
    return 0;
}