1. 程式人生 > 其它 >codeforces1271 D. Portals(dp or 帶悔貪心)

codeforces1271 D. Portals(dp or 帶悔貪心)

技術標籤:Codeforcesdp貪心

D. Portals

由於每個點可以選擇前面的某些點存在重複選擇的情況,考慮除去重複選擇的可能。

貪心:對於每一個城堡,我們都儘可能在最晚的時間控制,也就是在最後一個能控制它的點考慮是否控制

於是考慮設計dp

狀態表示: f ( i , j ) f_{(i,j)} f(i,j)表示考慮到第 i i i個城堡(已經佔領),當前士兵是 j j j的情況的最大值
狀態轉移:①不選擇佔領城堡從第 i − 1 i-1 i1個城堡轉移②考慮佔領城堡

注意:考慮第 i i i個城堡佔領的情況時,可以佔領多個城堡因而與“分組揹包”不同(分組揹包每組只能選一個)

#define IO ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
#pragma GCC optimize(2)
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
constexpr int N=5010;
int a[N],b[N],c[N];
int n,m,k;
int f[N][N];
int last[N];
vector<
int> g[N]; int main() { IO; int T=1; //cin>>T; while(T--) { cin>>n>>m>>k; for(int i=1;i<=n;i++) cin>>a[i]>>b[i]>>c[i]; while(m--) { int u,v; cin>>u>>v; last[
v]=max(last[v],u); } for(int i=1;i<=n;i++) { last[i]=max(last[i],i); g[last[i]].push_back(i); } memset(f,-0x3f,sizeof f); f[0][k]=0; for(int i=1;i<=n;i++) { for(int j=a[i];j+b[i]<=5000;j++) f[i][j+b[i]]=max(f[i][j+b[i]],f[i-1][j]); for(auto t:g[i]) for(int j=0;j<=4999;j++) f[i][j]=max(f[i][j],f[i][j+1]+c[t]); } int res=-1; for(int i=0;i<=5000;i++) res=max(res,f[n][i]); cout<<res<<'\n'; } return 0; }

帶悔貪心

n log ⁡ ( n ) n\log(n) nlog(n)
用一個優先佇列維護選擇的集合,每次把每個城堡連線的城堡都佔領,士兵不夠的時候從優先佇列集合中彈出

#define IO ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
#pragma GCC optimize(2)
#include<queue>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
constexpr int N=5010;
int a[N],b[N],c[N];
int n,m,k;
int last[N];
vector<int> g[N];
int main()
{
    IO;
    int T=1;
    //Pinit(1000000);
    //Cinit(1000);
    //cin>>T;
    while(T--)
    {
        cin>>n>>m>>k;
        for(int i=1;i<=n;i++) cin>>a[i]>>b[i]>>c[i];
        while(m--)
        {
            int u,v;
            cin>>u>>v;
            last[v]=max(last[v],u);
        }
        for(int i=1;i<=n;i++)
        {
            last[i]=max(last[i],i);
            g[last[i]].push_back(i);
        }
        priority_queue<int,vector<int>,greater<int> >  q;
        int now=k;
        for(int u=1;u<=n;u++)
        {
            while(now<a[u]&&q.size()) now++,q.pop();
            if(now<a[u]) return cout<<-1<<'\n',0;
            now+=b[u];
            for(auto t:g[u]) q.push(c[t]),now--;
        }
        while(now<0&&q.size()) now++,q.pop();
        if(now<0) cout<<-1<<'\n';
        else
        {
            int res=0;
            while(q.size()) res+=q.top(),q.pop();
            cout<<res<<'\n';
        }
    }
    return 0;
}