礼物

问题描述

       L小f和P小z的周年纪念日快到啦!为了个L小f一个惊喜,P小z决定去超市买一些礼物
    P小z去的超市共贩卖N种不同的物品,每种物品有三种属性,物品的价格 ,L小f的喜欢程度 ,物品的玄学程度 。
       这家超市有以下三条奇怪的规矩:
    1.每件商品只能购买一次
    2.对于每位客人,随机一件商品,这位客人不能购买这件商品
    3.物品的玄学值是个玄学,没有任何用处。
       现在,P小z有M为客人的购物记录,但是记录残缺不全,只有这些客人进店时带的钱数和被禁止购买的商品的编号。P小z想知道,对于每位客人,最优方案中让L小f的喜欢程度最大的值是多少?

输入格式

          

输出格式

样例输入

样例输出

数据范围

题解

这题01背包应该很明显吧。。。

关键是01背包求的是前i件物品的最大价值(即喜欢程度),要怎么得到前i件物品中有一件不能选的最大价值。

假设第p件物品不能选,以p为分界点,把n件物品分成两个区间,那么我们要求的就是前1->p-1件物品和后p+1->n件物品的最大价值。而[1,p-1],[p+1,n]这两段区间是连续的,这样就可以用01背包了。

从1->n,n->1分别做一次01背包,设f[i][j]表示前i件物品总价格不超过j的最大喜欢程度,g[i][j]表示i+1->n件物品总价格不超过j的最大喜欢程度,则不选第p件物品的最大喜欢程度为max(f[p-1][j]+g[p+1][m-j]) (m为客人带的钱数,0<=j<=m)

 1 #include <cstdio>
 2 int n,Q,w[1005],c[1005],a[1005],m[300005],p[300005];
 3 int f[1005][1005],g[1005][1005],V,ans;
 4 int max(int x,int y)
 5 {
 6     return x>y?x:y;
 7 }
 8 int main()
 9 {
10     int i,j,k;
11     scanf("%d",&n);
12     for (i=1;i<=n;i++)
13       scanf("%d%d%d",&w[i],&c[i],&a[i]);
14     scanf("%d",&Q);
15     for (i=1;i<=Q;i++)
16     {
17         scanf("%d%d",&p[i],&m[i]);
18         p[i]++;
19         if (m[i]>V) V=m[i];
20     }
21     for (i=1;i<=n;i++)
22       for (j=0;j<=V;j++)
23       {
24           f[i][j]=f[i-1][j];
25           if (j>=w[i]) f[i][j]=max(f[i][j],f[i-1][j-w[i]]+c[i]);
26       }   
27     for (i=n;i>=1;i--)
28       for (j=0;j<=V;j++)
29       {
30           g[i][j]=g[i+1][j];
31           if (j>=w[i]) g[i][j]=max(g[i][j],g[i+1][j-w[i]]+c[i]);
32       }    
33     for (i=1;i<=Q;i++)
34     {
35         for (ans=0,j=0;j<=m[i];j++)
36           ans=max(ans,f[p[i]-1][j]+g[p[i]+1][m[i]-j]);
37         printf("%d
",ans);
38     }
39     return 0;
40 }
原文地址:https://www.cnblogs.com/rabbit1103/p/9756349.html