zoukankan      html  css  js  c++  java
  • 【luogu P1064】 金明的预算方案

    https://www.luogu.org/problemnew/show/P1064

      从题目描述中可以很清楚地看出这是一个背包问题, 并且只有两类物品:主件和附件。所以这是一个非树形有依赖的背包问题。先对每种主件的 附件的集合 进行一次 01背包处理,就可以先求出 对于每一种主件包括其附件的组合中,每种花费的最大价值。

    这样可以得到主件k的附件中费用依次为0nv[k]时的相应最大价值f[0nv[k]],那么我们就得到了主件k及其附件集合的nv[k]+1种不同选择情况,其中费用为v[k]+t的物品的价值就是f[t]+v[k]p[k]。

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    #include<cstring>
    using namespace std;
    struct node {
        int v, p, q;
    } a[65], p[65][65];
    int n, m;
    int t[65], V[65][15], F[65][15], cnt[65], f[32005], ans;
    int main() {
        scanf("%d %d", &n, &m);
        for(int i = 1; i <= m; i++) {
            scanf("%d %d %d", &a[i].v, &a[i].p, &a[i].q);
            if(a[i].p) {
                t[a[i].q]++;
                p[a[i].q][t[a[i].q]].v = a[i].v;
                p[a[i].q][t[a[i].q]].p = a[i].p;
                p[a[i].q][t[a[i].q]].q = a[i].q;
            }
        }
        for(int i = 1; i <= m; i++) {
            if(t[i]) {
                memset(f,-1,sizeof(f));
                f[0] = 0;
                for(int j = 1; j <= t[i]; j++)
                    for(int k = n - a[i].v; k >= p[i][j].v; k--)
                        if(f[k] < f[k - p[i][j].v] + p[i][j].v * p[i][j].p && f[k - p[i][j].v] != -1)
                            f[k] = f[k - p[i][j].v] + p[i][j].v * p[i][j].p;
                for(int j = 0; j <= n - a[i].v; j++)
                    if(f[j] != -1) {
                        cnt[i]++;
                        V[i][cnt[i]] = j + a[i].v;
                        F[i][cnt[i]] = f[j] + a[i].v * a[i].p;
                    }
            }
            if(!a[i].q) {
                cnt[i]++;
                V[i][cnt[i]] = a[i].v;
                F[i][cnt[i]] = a[i].v * a[i].p;
            }
        }
        memset(f,0,sizeof(f));
        for(int i = 1; i <= m; i++)
            for(int j = n; j >= 0; j--)
                for(int k = 1; k <= cnt[i]; k++)
                    if(j >= V[i][k])
                        f[j] = max(f[j],f[j - V[i][k]] + F[i][k]);
        for(int i = 0; i <= n; i++)
            ans = max(ans,f[i]);
        printf("%d",ans);
        return 0;
    }
    View Code

     

  • 相关阅读:
    HDU 4539郑厂长系列故事――排兵布阵(状压DP)
    HDU 2196Computer(树形DP)
    HDU 4284Travel(状压DP)
    HDU 1520Anniversary party(树型DP)
    HDU 3920Clear All of Them I(状压DP)
    HDU 3853LOOPS(简单概率DP)
    UVA 11983 Weird Advertisement(线段树求矩形并的面积)
    POJ 2886Who Gets the Most Candies?(线段树)
    POJ 2828Buy Tickets
    HDU 1394Minimum Inversion Number(线段树)
  • 原文地址:https://www.cnblogs.com/jiqimin/p/11030989.html
Copyright © 2011-2022 走看看