codeforces 1106 E

显然是dp啊,dp[i][j]表示到时间i打扰了j次的最小收益

显然要排序,官方题解说set没看懂,优先队列就行啊。

按照时间排序,显然这样扫的话可以保证当前时间点的点在优先队列里吧,

然后有打断和不打断两种方式。搞一下就行了。

这个题其实只要想清楚,我在每个点能选的红包是唯一的,这样子一想就变得很**了。

头脑混乱写不出来不能怪我啊,我老人家持续表演了一个月的小品了啊

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 struct Red{
 5     ll s,t,d,w;
 6     bool operator<(const Red& a)const{
 7         if(w==a.w)
 8             return d<a.d;
 9         return w<a.w;
10     }
11 }r[100005];
12 bool cmp(Red a,Red b){
13     if(a.s==b.s){
14         if(a.w==b.w){
15             return a.d>b.d;
16         }
17         return a.w>b.w;
18     }
19     return a.s<b.s;
20 }
21 int n,m,k;
22 ll dp[100005][201];
23 priority_queue<Red> q;
24 int main() {
25     ios::sync_with_stdio(false);
26     cin>>n>>m>>k;
27     for(int i=2;i<=n+1;i++)for(int j=0;j<=m;j++)dp[i][j]=1e18;
28     for(int i=1;i<=k;i++){
29         cin>>r[i].s>>r[i].t>>r[i].d>>r[i].w;
30     }
31     sort(r+1,r+1+k,cmp);
32     int j=1;
33     for(int i=1;i<=n;i++){//
34         for(;j<=k;){
35             if(r[j].s<=i) {
36                 q.push(r[j]);
37                 j++;
38             } else break;
39         }
40         while (!q.empty()&&q.top().t<i) q.pop();
41         if(q.empty()){
42             for(int l=0;l<=m;l++){
43                 dp[i+1][l]=min(dp[i+1][l],dp[i][l]);
44             }
45             continue;
46         }
47         Red tmp = q.top();
48         for(int l=0;l<=m;l++) {
49             dp[min(tmp.d+1,n+1ll)][l]=min(dp[min(tmp.d+1,n+1ll)][l],dp[i][l]+tmp.w);
50         }
51         for(int l=1;l<=m;l++){
52             dp[i+1][l]=min(dp[i+1][l],dp[i][l-1]);
53         }
54     }
55     ll ans = 1e18;
56     for(int i=0;i<=m;i++){
57         ans = min(ans,dp[n+1][i]);
58     }
59     cout<<ans<<endl;
60 }
View Code

猜你喜欢

转载自www.cnblogs.com/MXang/p/10347189.html