• E


    题源:https://codeforces.com/gym/101635/attachments

    题意: n行,每行给定字符串s1,s2,s3代表一些菜谱名。s2和s3是煮成是的必要条件,然后给出c和v,分别代表s1的消耗和收获;

       (注意:这个消耗并不可能是s1的真正消耗和收获,s1的最后消耗和收获是得加上s2和s3的)

       然后问在不用超过C消耗的情况下最大收获是多少?

    分析:这里我们可以想象到,一道有条件的菜要做成是要若干个“前提”菜做成的,这个过程就是拓扑排序!我们对于每个s1,s2,s3编号后就是拓扑排序了,s2,s3,就是相当于给予s1一个入度;

       所有每次拓扑我们就枚举已经做成的s2和s3给最优的c和v给s1,然后最后对所有的菜进行01背包找出答案

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define pb push_back
    const int inf=0x3f3f3f3f;
    const ll INF=1e18;
    const int N=1e6+6;
    const int M=1e5+5;
    struct node{
        int u,id;
    };
    vector<node>g[N];
    ll dp[M],cc[M],vv[M],ind[M],book[N];
    ll c[N],v[N];
    int ID,cnt;
    char s1[50],s2[50],s3[50];
    map<int,int>mp;
    map<string ,int>sign;
    queue<int>que;
    int getid(string x){
        if(sign[x]==0){
            sign[x]=++ID;
        }
        return sign[x];
    }
    int main(){
        int C,n;
        scanf("%d%d",&C,&n);
        for(int i=1;i<=n;i++){
            scanf("%s%s%s%lld%lld",s1,s2,s3,&c[i],&v[i]);
            int z=getid(s1);
            int x=getid(s2);
            int y=getid(s3);
            ind[z]++;
            cc[z]=inf;
            mp[i]=z;
            g[x].pb({y,i});
            g[y].pb({x,i});
        }
        for(int i=1;i<=ID;i++){
            if(ind[i]==0)
                que.push(i);
        }
        while(!que.empty()){
            int x=que.front();
            que.pop();
            for(int i=0;i<g[x].size();i++){
                node nowv=g[x][i];
                int y=nowv.u,id=nowv.id,z=mp[id];
                if(!book[id]&&ind[y]==0){
                    book[id]=1;
                    ll cost=cc[x]+cc[y]+c[id];
                    ll val=vv[x]+vv[y]+v[id];
                    if(cc[z]>cost||(cc[z]==cost&&vv[z]<val)){
                        cc[z]=cost;
                        vv[z]=val;
                    }
                    if(--ind[z]==0)
                        que.push(z);
                }
                
            }
        }
    
        dp[0]=0;
        for(int i=1;i<=ID;i++){
            for(int j=C;j>=0;j--)
                if(j-cc[i]>=0)
                    dp[j]=max(dp[j],dp[j-cc[i]]+vv[i]);
        }
        ll maxx=0;
        ll lasc=0;
        for(int i=1;i<=C;i++){
            if(dp[i]>maxx){
                maxx=dp[i];
                lasc=i;
            }
        }
        printf("%lld
    %lld
    ",maxx,lasc);
        return 0;
        
    }
    View Code
  • 相关阅读:
    仙人球的残影
    Calculate the formula
    自定义代码段
    getter-setter方法练习
    封装
    Xcode文档安装
    Xcode模板修改
    匿名对象
    OC多文件开发介绍
    #pragma mark指令
  • 原文地址:https://www.cnblogs.com/starve/p/11964255.html
Copyright © 2020-2023  润新知