WHYZOJ-#93. 暗黑破坏神(垃圾01背包)

【题目描述】:

无聊中的小x玩起了Diablo I... 游戏的主人公有n个魔法,每个魔法分为若干个等级,第i个魔法有p[i]个等级(不包括0)。每个魔法的每个等级都有一个效果值,一个j级的i种魔法的效果值为w[i][j]。魔法升一级需要一本相应的魔法书。购买魔法书需要金币,第i个魔法的魔法书价格为c[i]。

而小x只有m个金币(好孩子不用修改器)

你的任务就是帮助小x决定如何购买魔法书才能使所有魔法的效果值之和最大。开始时所有魔法为0级,效果值为0。

【输入描述】:

第一行,用空格隔开的两个整数n m;

以下n行,描述n个魔法;

第i+1行描述,第i个魔法 格式如下:

c[i] p[i] w[i][1] w[i][2] ... w[i][p[i]]

【输出描述】:

输出一个整数,即最大效果值。

【样例输入】:

3 10
1 3 1 2 2
2 3 2 4 6
3 3 2 1 10

【样例输出】:

11

【时间限制、数据范围及描述】:

时间:1s 空间:128M

0<n<=100

0<m<=500

0<p[i]<=50

0<c[i]<=10

保证输入数据和最终结果在longint范围内

这题叫真几把简单,就是一最基本的01背包,然而当时我还以为是什么高级的多重背包或者其他什么神奇的背包……感冒果然什么都搞不好啊QAQ

 1 #include "bits/stdc++.h"
 2 using namespace std;
 3 typedef long long LL;
 4 const int MAX=505;
 5 int n,m;
 6 int c[MAX],p[MAX],w[MAX][MAX]={0};
 7 int f[MAX][MAX];
 8 inline int read(){
 9     int an=0,x=1;char c=getchar();
10     while (c<‘0‘ || c>‘9‘) {if (c==‘-‘) x=-1;c=getchar();}
11     while (c>=‘0‘ && c<=‘9‘) {an=an*10+c-‘0‘;c=getchar();}
12     return an*x;
13 }
14 int main(){
15     freopen ("godness.in","r",stdin);
16     freopen ("godness.out","w",stdout);
17     int i,j,k;
18     n=read();m=read();
19     for (i=1;i<=n;i++){
20         c[i]=read(),p[i]=read();
21         for (j=1;j<=p[i];j++){
22             w[i][j]=read();
23         }
24     }
25     memset(f,0,sizeof(f));
26     for (i=1;i<=n;i++){
27         for (j=0;j<=p[i];j++){
28             for (k=m;k>=c[i]*j;k--){
29                 f[i][k]=max(f[i][k],f[i-1][k-c[i]*j]+w[i][j]);
30             }
31         }
32     }
33     printf("%d",f[n][m]);
34     return 0;
35 }
时间: 2024-07-29 17:51:21

WHYZOJ-#93. 暗黑破坏神(垃圾01背包)的相关文章

【hdu3080】01背包(容量10^7)

[题意]n个物品,有wi和vi,组成若干个联通块,只能选取一个联通块,问得到m的价值时最小要多少空间(v).n<=50,v<=10^7 [题解] 先用并查集找出各个联通块. 这题主要就是v太大了,跟以往的背包不同. 我们回想01背包,f[j+v[i]]=max(f[j]+w[i]); 在这里面很明显很多状态都没有用. 优化:如果有2个状态,v1<=v2 && w1>=w2 则(v2,w2)这个状态是没有用的. 我们回到滚动数组中: f[i][j+v[i]]=max(

出差之前写一个0-1背包的程序吧

又要出差了,也不知道多久才能回来,这段时间应该都不能更新博客了,写了0-1背包程序热热手吧. 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #define MAX_NUM 20 //物品最大个数 5 #define MAX_PACK 100 //背包容量 6 7 int result[MAX_NUM][MAX_PACK]; //全局变量默认初始化0 8 9 /* 10 * 0 1背包问题动态规划方程 11 * 12 * m[i][j]

(01背包)HDU - 2126 Buy the souvenirs

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=2126 题意:给n个物品,和m块钱,输出最多物品个数和其方案数. 委屈:求出最多物品个数就是一个裸的01背包,但是同时求出方案数,难住了我. 想了半天,感觉可以一波dp求出来,但是又想不明白状态是怎么表示和转移的. 无奈就先写个dfs提交试一发,果断超时了. 最后无奈看了题解,只能说,01背包还是不会. 其实与其说01背包不会不如说动态规划不会,感觉好难. 感觉自己好lowbee啊.. 感觉碰到dp就

hdu3339 In Action(Dijkstra+01背包)

1 /* 2 题意:有 n 个站点(编号1...n),每一个站点都有一个能量值,为了不让这些能量值连接起来,要用 3 坦克占领这个站点!已知站点的 之间的距离,每个坦克从0点出发到某一个站点,1 unit distance costs 1 unit oil! 4 最后占领的所有的站点的能量值之和为总能量值的一半还要多,问最少耗油多少! 5 6 */ 7 8 /* 9 思路:不同的坦克会占领不同的站点,耗油最少那就是路程最少,所以我们先将从 0点到其他各点的 10 最短距离求出来!也就是d[i]的

hdu 3339 In Action (最短路径+01背包)

In Action Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3869    Accepted Submission(s): 1237 Problem Description Since 1945, when the first nuclear bomb was exploded by the Manhattan Project t

hdu 1561 树形dp+0-1背包

1 /* 2 根据先后关系,可以建立一棵树 3 dp[i][j]表示第i个节点选j个的最大值 4 dp[i][j]=max(sigma(dp[c[i][ki]])) 5 sigma(dp[c[i][ki]])表示从i的儿子节点中一共选取j个点的最大值 6 */ 7 /*#include <iostream> 8 #include <cstdio> 9 #include <cstring> 10 #include <vector> 11 using names

01背包(类) UVA 10564 Paths through the Hourglass

题目传送门 1 /* 2 01背包(类):dp[i][j][k] 表示从(i, j)出发的和为k的方案数,那么cnt = sum (dp[1][i][s]) 3 状态转移方程:dp[i][j][k] = dp[i+1][j][k-c] + dp[i+1][j+1][k-c];(下半部分) 上半部分类似 4 因为要输出字典序最小的,打印路径时先考虑L 5 */ 6 /************************************************ 7 * Author :Runni

UVA 562 Dividing coins --01背包的变形

01背包的变形. 先算出硬币面值的总和,然后此题变成求背包容量为V=sum/2时,能装的最多的硬币,然后将剩余的面值和它相减取一个绝对值就是最小的差值. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define N 50007 int c[102],d

17-又见01背包

/*                                        又见01背包时间限制:1000 ms  |  内存限制:65535 KB难度:3 描述        有n个重量和价值分别为wi 和 vi 的 物品,从这些物品中选择总重量不超过 W     的物品,求所有挑选方案中物品价值总和的最大值.    1 <= n <=100    1 <= wi <= 10^7    1 <= vi <= 100    1 <= W <= 10^