• Luogu P1860 新魔法药水


    DP

    首先考虑如何将答案DP转移出来

    记$dp[i][j]$表示使用了$i$次魔法,用了$j$个金币时的最大获利

    因为可以将几个药水合成一个药水

    那么在转移时会发现还需要处理出用了第$i$种药水由$j$次魔法合成的最小成本,记此为$tc[i][j]$

    那么转移方程就是$dp[i][j]=min(dp[i-q][j-tc[p][q]]+w[p]-tc[p][q])$

    $w$表示这个药水的售价

    那么现在就要处理出$tc$数组

    对于$tc[i][j]$,因为当前合成i需要一次操作,那么分配给其原料的合成次数为$j-1$

    $tc[i][j]=max(sum_{k=1}^{Number}tc[a[k]][t[k]])$

    且$sum_{k}^{Number}t[k]=j-1$

    $a$数组表示这个合成这个药水的原料,$t$为给这个原料分配合成的次数,$Number$为原料总数

    那么这个表达式也是可以DP转移的

    记$tmp[i][j]$表示前$i$个原料,用了$j$次魔法的最小成本

    填表转移即可

    注意此处合成同一个药水的配方可能有多个

    那么在这多个配方中$tc$选取最佳的即可

    #include <bits/stdc++.h>
    #define inf (int)1e9
    using namespace std;
    int n,m,v,k,tmp[100][100],tc[100][100];
    int dp[45][1100];
    struct node
    {
        int v,w;
    }sh[100];
    struct magic
    {
        int p,h;
        vector <int> a;
    }d[300];
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&v,&k);
        for (int i=1;i<=n;i++)
          scanf("%d%d",&sh[i].v,&sh[i].w);
        for (int i=1;i<=m;i++)
        {
            scanf("%d%d",&d[i].p,&d[i].h);
            for (int j=1;j<=d[i].h;j++)
            {
                int num;
                scanf("%d",&num);
                d[i].a.push_back(num);
            }
        }
        for (int i=1;i<=n;i++)
        {
            for (int j=1;j<=k;j++)
              tc[i][j]=inf;
            tc[i][0]=sh[i].v;
        }
        for (int j=1;j<=k;j++)
        {
            for (int i=1;i<=m;i++)
            {
                for (int p=0;p<j;p++)
                  tmp[0][p]=tc[d[i].a[0]][p];//初始值
                for (int p=1;p<(int)d[i].a.size();p++)
                {
                    for (int q=0;q<j;q++)
                    {
                        tmp[p][q]=inf;
                        for (int r=0;r<=q;r++)
                          tmp[p][q]=min(tmp[p][q],tmp[p-1][r]+tc[d[i].a[p]][q-r]);//tmp的DP转移
                    }
                }
                tc[d[i].p][j]=min(tc[d[i].p][j],tmp[(int)d[i].a.size()-1][j-1]);//在多个方案中取最优
            }
        }
        for (int i=0;i<=k;i++)
        {
            for (int j=0;j<=v;j++)
              dp[i][j]=-inf;
        }
        dp[0][0]=0;
        for (int i=0;i<=k;i++)
        {
            for (int j=0;j<=v;j++)
            {
                for (int p=1;p<=n;p++)
                {
                    for (int q=0;q<=i;q++)
                    {
                        if (tc[p][q]==inf)
                          continue;
                        if (j>=tc[p][q])//注意边界条件
                          dp[i][j]=max(dp[i][j],dp[i-q][j-tc[p][q]]+sh[p].w-tc[p][q]);  //转移
                    }
                }
            }
        }
        int ans=0;
        for (int i=0;i<=k;i++)
        {
            for (int j=0;j<=v;j++)
              ans=max(ans,dp[i][j]);//统计答案
        }
        printf("%d
    ",ans);
    }
  • 相关阅读:
    ASP.NET权限管理系统(FrameWork) 1.0.4 Release
    广告统计分析系统(ADCount) 1.0.0 Beta
    Asp.Net权限管理系统 专用代码生成工具(DDBuildTools) 1.1.0
    ASP.NET权限管理系统(FrameWork) 1.0.7 Release
    remoting缓存设计总结
    关于在Page_Load定义外部变量输出
    ASP.NET权限管理系统(FrameWork) 1.0.5 Release
    DDBuildTools 1.3.0 Release发布
    ASP.NET权限管理系统(FrameWork) 1.0.6 Release
    缺席
  • 原文地址:https://www.cnblogs.com/huangchenyan/p/11305070.html
Copyright © 2020-2023  润新知