Codeforces #536 div2 E (1106E)Lunar New Year and Red Envelopes (DP)
題意:過年了,Bob要搶紅包。搶紅包的時間段為1 - n,有m個紅包,每個紅包有三個屬性:st(紅包出現的時間), ed(紅包消失的時間),d(如果搶了這個紅包,能夠搶下一個紅包的時間),w(紅包的收益)。注:結束時間為ed是指在ed + 1的時候才能搶其它的紅包,d同理。Bob是一個貪心的人,如果當前時間段他可以搶紅包,他會搶現在出現的紅包中收益最大的紅包。如果有多個收益最大的紅包,他會搶d最大的那個。Alice可以打斷Bob k次,每次打斷可以使Bob在1秒內無法行動,下一秒恢復正常。現在問Bob可以獲得的最小的收益是多少?
思路:這種題一看就知道常規方法解決不了啦,只能DP了。首先,每個時間點搶的是什么紅包其實是固定的,我們只需要先把紅包按開始時間排序,然后用堆或者mutiset維護這個時間點搶什么。其次,我們可以發現,如果Bob搶了某個紅包,他只有在特定的時間之后才能搶下一個紅包,這是明顯的狀態轉移過程。我們設dp[i][j]為處于時間點i,還可以打擾j次的最小收益。那么我們可以執行兩種轉移:
1:我們搶這個紅包,(設這個紅包的w為wi,d為di)那么dp[di + 1][j ] = min(dp[di + 1][j], dp[i][j] + wi)
2:現在不搶,用掉一次打擾機會,那么dp[i + 1][j - 1] = min(dp[i + 1][j - 1], dp[i][j]);
代碼:
#include <cstdio> #include <algorithm> #include <vector> #include <iostream> #include <cstring> #include <map> #include <set> #include <bitset> #include <queue> #include <cmath> #include <string> #define INF 0x3f3f3f3f3f3f3f3f #define pii pair<int, int> #define lowbit(x) (x & (-x)) #define ls(x) (x << 1) #define rs(x) ((x << 1) | 1) #define LL long long using namespace std; const int maxn = 100010; struct node {int st, ed, d, pos;LL w;bool operator < (const node& rhs) const {if(w == rhs.w) return d < rhs.d;return w < rhs.w;} }; node a[maxn]; vector<int> b[maxn],c[maxn]; priority_queue<node> q; LL dp[maxn][210]; node re[maxn]; bool v1[maxn]; bool cmp(node x, node y) {if(x.st == y.st) return x.ed < y.ed;return x.st < y.st; } int main() {int n, k, m;scanf("%d%d%d", &n, &k ,&m);for (int i = 1; i <= m; i++) {scanf("%d%d%d%d", &a[i].st, &a[i].ed, &a[i].d, &a[i].w);}sort(a + 1, a + 1 + m);for (int i = 1; i <= m; i++) {b[a[i].st].push_back(i);c[a[i].ed].push_back(i);a[i].pos = i;}for (int i = 1; i <= n; i++) {for (int j = 0; j < b[i].size(); j++) {int y = b[i][j];q.push(a[y]);}while(q.size() && v1[q.top().pos]) {q.pop();}if(!q.empty())re[i] = q.top();else re[i] = (node) {0, 0, i, 0, 0};for (int j = 0; j < c[i].size(); j++) {int y = c[i][j];v1[y] = 1;}}memset(dp, 0x3f, sizeof(dp));dp[1][k] = 0;for (int i = 1; i <= n; i++) {for (int j = 0; j <= k; j++) {int d = re[i].d;if(j) dp[i + 1][j - 1] = min(dp[i + 1][j - 1], dp[i][j]);dp[d + 1][j] = min(dp[d + 1][j], dp[i][j] + re[i].w);}}LL ans = INF;for (int i = 0; i <= k; i++) {ans = min(ans, dp[n + 1][i]);}printf("%lld\n", ans); }
?
轉載于:https://www.cnblogs.com/pkgunboat/p/10345935.html
總結
以上是生活随笔為你收集整理的Codeforces #536 div2 E (1106E)Lunar New Year and Red Envelopes (DP)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux内核启动时报错ubi0 err
- 下一篇: 客户端连接caching-sha2-pa