HDU-1300 Pearls(斜率DP)
阿新 • • 發佈:2020-07-24
分析:假設dp[i]為購買前i種珍珠花費的最小价格,我們可以得到dp轉移方程,\(dp[i] = min\{(cnt[i] - cnt[k] + 10) * p[i] + dp[k]\}(1 <= k < i)\),我們可以對方程式進行變形,\(dp[k] = p[i] * cnt[k] + dp[i] - cnt[i] * p[i] + 10 * p[i]\),假設\(dp[k]為y\),\(cnt[k]為x\),\(截距(dp[i] - cnt[i] * p[i] + 10 * p[i])為b\),那麼我們可以得到\(y = p[i] * x + b\),那麼斜率則為\(p[i]\)
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <vector> #include <queue> #include <algorithm> using namespace std; const int N = 105; int a[N], p[N]; int dp[N]; int q[N]; int cnt[N]; int main() { int t; scanf("%d", &t); while (t--) { int c; scanf("%d", &c); for (int i = 1; i <= c; ++i) { scanf("%d%d", &a[i], &p[i]); } for (int i = 1; i <= c; ++i) cnt[i] = cnt[i - 1] + a[i]; int hh = 0, tt = 0; q[0] = 0; for (int i = 1; i <= c; ++i) { while (hh < tt && (dp[q[hh + 1]] - dp[q[hh]]) <= p[i] * (cnt[q[hh + 1]] - cnt[q[hh]])) ++hh; int k = q[hh]; dp[i] = (cnt[i] - cnt[k] + 10) * p[i] + dp[k]; while (hh < tt && (dp[q[tt]] - dp[q[tt - 1]]) * (cnt[i] - cnt[q[tt]]) >= (dp[i] - dp[q[tt]]) * (cnt[q[tt]] - cnt[q[tt - 1]])) --tt; q[++tt] = i; } printf("%d\n", dp[c]); } return 0; }