zoukankan      html  css  js  c++  java
  • cf1271D——经典 dp+贪心+图论

    /*
    该题目很好的将图论和dp的状态转移结合在了一起
    首先有一个贪心策略:
        每个点都只能被离其最远(最靠右)的那个点派兵守卫,这个点可能是其自身
        正确性显然:士兵留到越后面,其产生的贡献越大,所以不到关键时刻,就不派兵守卫 
    dp[i,j]表示进攻到i点时,剩余兵力为j时的最大收益
        转移时的策略:将i点连的所有点按收益从大到小排序,设该点派出l个兵,那么对应前状态就是dp[i-1][j-bi+l] 
    
    复杂度:求最坏情况下的复杂度:初始k=5000
        那么每次转移时都要让第二重循环跑5000次,由于每个点最多只有一个入边,所以总复杂度为O(n^2) 
    
    */
    #include<bits/stdc++.h>
    #include<vector>
    using namespace std;
    #define N 5005
    #define M 300005
    int a[N],b[N],c[N],n,m,k;
    int Max[N],dp[N][N];
    vector<int>G[N];
    
    int cmp(int a,int b){return c[a]>c[b];}
    
    int main(){
        cin>>n>>m>>k;
        for(int i=1;i<=n;i++)
            scanf("%d%d%d",&a[i],&b[i],&c[i]),Max[i]=i;
        for(int i=1;i<=m;i++){
            int u,v;scanf("%d%d",&u,&v);
            Max[v]=max(Max[v],u);
        }
        for(int i=1;i<=n;i++)
            G[Max[i]].push_back(i);
        for(int i=1;i<=n;i++)
            sort(G[i].begin(),G[i].end(),cmp);
        /*
        for(int i=1;i<=n;i++){
            for(auto x:G[i])cout<<x<<" ";
            puts("");
        }*/
        
        memset(dp,0x3f,sizeof dp);
        dp[0][k]=0;
        for(int i=1;i<=n;i++)
            for(int j=0;j<=5000;j++){
                int sum=0;
                if(j-b[i]>=a[i] && dp[i-1][j-b[i]]!=0x3f3f3f3f)//一个兵也不派 
                    dp[i][j]=dp[i-1][j-b[i]];
                for(int l=0;l<G[i].size();l++){
                    if(j-b[i]+l+1>5000)break;
                    int v=G[i][l];
                    sum+=c[v];
                    if(j-b[i]+l+1>=a[i] && dp[i-1][j-b[i]+l+1]!=0x3f3f3f3f)
                        if(dp[i][j]!=0x3f3f3f3f)
                            dp[i][j]=max(dp[i][j],dp[i-1][j-b[i]+l+1]+sum);
                        else dp[i][j]=dp[i-1][j-b[i]+l+1]+sum;
                }
            }
        /*
        for(int i=1;i<=n;i++){
            for(int j=1;j<=20;j++)
                cout<<dp[i][j]<<" ";
            puts("");
        }*/
        
        int ans=-1;
        for(int j=0;j<=5000;j++)
            if(dp[n][j]!=0x3f3f3f3f)ans=max(ans,dp[n][j]);
        cout<<ans<<'
    ';
                
        return 0;
    }
  • 相关阅读:
    Maven导包失败三种解决方案-Could not transfer artifact
    MySQL远程登录赋权操作各命令的意思
    大数据技术与应用课堂测试01
    软件体系架构课堂测试01
    设计模式复习笔记23
    设计模式复习笔记22
    设计模式复习笔记21
    设计模式复习笔记20
    设计模式复习笔记19
    设计模式复习笔记18
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12116024.html
Copyright © 2011-2022 走看看