CF1271D Portals dp 贪心

地址

  • 首先可以观察得出:  如果可以defence 城堡i有多个城市,那么选择最后一个城市再考虑是否defence该城堡是最优方案
  • 第一种方法 可以采用dp 因为发现士兵数量C 小于5000  所以设置dp[i]表示攻打到当前城堡时,士兵数剩余i个所取得的最大贡献
  • 第二种方法 可以用优先队列优化
  • 要求出第i个城市最多可以使用多少个额外的士兵非常的麻烦
  • 可以用反悔贪心法
  • 如果能占领城市那么就去占领, 如果攻打下一个城市缺人, 那么可以将之前派去的士兵召集回来
  • 用一个小顶堆存放派去的士兵,这样如果召回的话损失也最小
 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
 
const int inf=0x3f3f3f3f;
const int N=5e5+100;
 
int dp[6000],a[N],b[N],c[N];
vector<int>contribution[N];
int last[N];
int main () {
    int n,m,k;
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++) {
        scanf("%d%d%d",&a[i],&b[i],&c[i]);
        last[i]=i;
    }
    int u,v;
    while(m--) {
        scanf("%d%d",&u,&v);
        last[v]=max(last[v],u);
    }
    for(int i=1;i<=n;i++) contribution[last[i]].push_back(c[i]);
    memset(dp,-1,sizeof dp);
    dp[k]=0;
 
    for(int i=1;i<=n;i++) {
        for(int j=0;j<a[i];j++) dp[j]=-1;
 
        for(int j=5500;j>=b[i];j--) dp[j]=dp[j-b[i]];
 
        for(auto &v:contribution[i])
            for(int j=0;j<=5500;j++)
                if(dp[j+1]!=-1)
                    dp[j]=max(dp[j],dp[j+1]+v);
    }
    cout<<*max_element(dp,dp+5500);
}
dp
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=3e5+10;

int a[N],b[N],c[N],last[N];
vector<int>contribution[N];

int main() {
    int n,m,k;
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++) scanf("%d%d%d",&a[i],&b[i],&c[i]),last[i]=i;
    int u,v;
    while(m--) scanf("%d%d",&u,&v),last[v]=max(last[v],u);
    for(int i=1;i<=n;i++)
        contribution[last[i]].push_back(c[i]);
    priority_queue<int ,vector<int>, greater<int> >q;
    int sum=k,ans=0;
    for(int i=0;i<=n;i++) {
        sum+=b[i];
        for(auto &v:contribution[i])
            sum--,q.push(v);

        while(!q.empty()&&sum<a[i+1])
            sum++,q.pop();

        if(sum<a[i+1]) printf("-1"),exit(0);
    }
    while(!q.empty())
        ans+=q.top(),q.pop();
    cout<<ans;
}
贪心

猜你喜欢

转载自www.cnblogs.com/bxd123/p/12076644.html