zoukankan      html  css  js  c++  java
  • hdu6007 spfa+完全背包

    题意:给你M,N,K,代表你有M点法力值,N个物品,K个制造方式

    接下来N行,如果以1开头则代表既能卖又能合成,0代表只能卖。

    然后K行,每行第一个数是要合成的东西,第二个数代表有几对,每对第一个数是那种物品,第二个是需要几个。

    注意不能直接合成的可以通过制造方式来合成。然后问你花费完所有的法力制造的东西,能获得最大的金钱是多少

    题解:首先处理出来对于所有物品所需要消耗的最小法力值,然后就是做一下完全背包就可以了。

    消耗最小法力值可以通过spfa获得,一个技巧就是对于同属一个目标产物的原材料,可以用一个fa[]数组来指向目标产物的vector的数组下标.目标产物有两个vector,其中一个代表了是哪几种原材料,然后另一个对应的是这几种原材料的个数。

    然后再利用head[]数组,得知一个目标产物的原材料的边的编号tot一定是连续的,那么就把这连续一段的边的编号指为当前目标产物的两个vector的数组下标就可以了。

    具体详见代码。---强迫症是从0开始计的,所以说建边的时候要减一

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<queue>
    using namespace std;
    const int INF=0x3f3f3f3f;
    int dp[10086],sell[208],pct[208],head[208];
    bool vis[208];
    int M,N,K,op,n,T,tas=1,tot;
    struct node
    {
        int v,next;
    } e[100861];
    void add(int u,int v)
    {
        e[tot].v=v;
        e[tot].next=head[u];
        head[u]=tot++;
    }
    vector<int>U[208];
    vector<int>num[208];
    int fa[100861];
    void spfa()
    {
        queue<int>Q;
        for(int i=0; i<N; ++i) if(pct[i]!=INF)
            {
                Q.push(i),vis[i]=1;
            }
        while(!Q.empty())
        {
            int u=Q.front();
            Q.pop();
            vis[u]=0;
            for(int i=head[u]; ~i; i=e[i].next)
            {
                bool ok=1;
                int ans=0;
                for(int j=0; j<(int)U[fa[i]].size(); ++j)
                {
                    if(pct[U[fa[i]][j]]==INF)
                    {
                        ok=0;
                        break;
                    }
                    ans+=pct[U[fa[i]][j]]*num[fa[i]][j];
                }
                if(!ok) continue;
                if(ans<pct[e[i].v])
                {
                    pct[e[i].v]=ans;
                    if(!vis[e[i].v]) Q.push(e[i].v),vis[e[i].v]=1;
                }
            }
        }
    }
    int main()
    {
        for(scanf("%d",&T); T--;)
        {
            memset(head,-1,sizeof(head));
            memset(pct,INF,sizeof(pct));
            tot=0;
            scanf("%d%d%d",&M,&N,&K);
            for(int i=0; i<N; ++i)
            {
                scanf("%d",&op);
                if(op==0) scanf("%d",&sell[i]);
                else scanf("%d%d",&pct[i],&sell[i]);
            }
            int now=0;
            for(int i=0; i<K; ++i)
            {
                int tar,par,ne,nn;
                scanf("%d%d",&tar,&par);
                if(!par) continue;
                U[now].clear();
                num[now].clear();
                int last=tot;
                --tar;
                for(int j=0; j<par; ++j)
                {
                    scanf("%d%d",&ne,&nn);
                    --ne;
                    add(ne,tar);
                    U[now].push_back(ne);
                    num[now].push_back(nn);
                }
                for(int j=last; j<tot; ++j) fa[j]=now;
                ++now;
            }
            spfa();
            memset(dp,0,sizeof(dp));
            for(int i=0; i<N; ++i) for(int j=pct[i]; j<=M; ++j) dp[j]=max(dp[j],dp[j-pct[i]]+sell[i]);
            printf("Case #%d: %d
    ",tas++,dp[M]);
        }
    }
  • 相关阅读:
    Odoo Entypo Regular Icon List
    Ubuntu 循环遍历当前目录下所有文本文件中的字符
    FairyGUI学习
    FairyGUI和NGUI对比
    热更新有多重要?游戏代码热更新杂谈
    收藏的链接
    Vuforia AR实战教程
    BleedTree动画混合树
    Unity3d导出安卓版本
    Unity+高通Vuforia SDK——AR
  • 原文地址:https://www.cnblogs.com/mfys/p/7674352.html
Copyright © 2011-2022 走看看