hdu 3535 AreYouBusy 混合背包

2024-08-28 17:18

本文主要是介绍hdu 3535 AreYouBusy 混合背包,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

个人感觉思路一点不好想,看了网上的总算是懂了,也自己敲了敲,懂思路就很简单了

题意:

给你n种工作,给你T的时间去做它们。给你m和s,说明这种工作有m件事可以做,它们是s类的工作(s=0,1,2,s=0说明这m件事中最少得做一件,s=1说明这m件事中最多只能做一件,s=2说明这m件事你可以做也可以不做)。再给你ci和gi代表你做这件事要用ci的时间,能获得gi的快乐值。求在T的时间内你能获得的最大快乐值。


思路:

经典混合背包

     题目给了很多类别的物品。用 数组dp[i][j],表示第i组,时间为j时的快乐值。每得到一组工作就进行一次DP,所以dp[i]为第i组的结果。

 

  第一类,至少选一项,即必须要选,那么在开始时,对于这一组的dp的初值,应该全部赋为负无穷,这样才能保证不会出现都不选的情况。

状态转移方程:

dp[i][j]=max(dp[i][j],max(dp[i][j-w[x]]+p[x],dp[i-1][j-w[x]]+p[x]));

 

dp[i][j]: 是不选择当前工作;

dp[i-1][j-w[x]]+p[x]: 第一次在本组中选物品,由于开始将该组dp赋为了负无穷,所以第一次取时,必须由上一组的结果推知,这样才能保证得到全局最优解;

dp[i][j-w[x]]+p[x]:表示选择当前工作,并且不是第一次取;

 

  第二类,最多选一项,即要么不选,一旦选,只能是第一次选。

状态转移方程:

dp[i][j]=max(dp[i][j],dp[i-1][j-w[x]]+p[x]);

由于要保证得到全局最优解,所以在该组DP开始以前,应该将上一组的DP结果先复制到这一组的dp[i]数组里,因为当前组的数据是在上一组数据的基础上进行更新的。

 

     第三类,任意选,即不论选不选,选几个都可以。

状态转移方程为:

dp[i][j]=max(dp[i][j],dp[i][j-w[x]]+p[x]);

同样要保证为得到全局最优解,先复制上一组解,数据在当前组更新。

 

Description

Happy New Term! 
As having become a junior, xiaoA recognizes that there is not much time for her to AC problems, because there are some other things for her to do, which makes her nearly mad. 
What's more, her boss tells her that for some sets of duties, she must choose at least one job to do, but for some sets of things, she can only choose at most one to do, which is meaningless to the boss. And for others, she can do of her will. We just define the things that she can choose as "jobs". A job takes time , and gives xiaoA some points of happiness (which means that she is always willing to do the jobs).So can you choose the best sets of them to give her the maximum points of happiness and also to be a good junior(which means that she should follow the boss's advice)? 

Input

There are several test cases, each test case begins with two integers n and T (0<=n,T<=100) , n sets of jobs for you to choose and T minutes for her to do them. Follows are n sets of description, each of which starts with two integers m and s (0<m<=100), there are m jobs in this set , and the set type is s, (0 stands for the sets that should choose at least 1 job to do, 1 for the sets that should choose at most 1 , and 2 for the one you can choose freely).then m pairs of integers ci,gi follows (0<=ci,gi<=100), means the ith job cost ci minutes to finish and gi points of happiness can be gained by finishing it. One job can be done only once.

Output

One line for each test case contains the maximum points of happiness we can choose from all jobs .if she can’t finish what her boss want, just output -1 .

Sample Input

       
3 3 2 1 2 5 3 8 2 0 1 0 2 1 3 2 4 3 2 1 1 13 4 2 1 2 5 3 8 2 0 1 1 2 8 3 2 4 4 2 1 1 11 1 1 0 2 15 3 2 0 1 0 2 1 2 0 2 2 1 1 2 0 3 2 2 1 2 1 1 5 2 8 3 2 3 8 4 9 5 10

Sample Output

       
5 13 -1 -1

二维数组:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define INF 1<<29
using namespace std;
int w[101],p[101];
int dp[101][101];
int main()
{int n,T;while(~scanf("%d %d",&n,&T)){memset(dp,0,sizeof(dp));for(int i=1; i<=n; i++){int m,flag;scanf("%d %d",&m,&flag);for(int x=1; x<=m; x++)scanf("%d %d",&w[x],&p[x]);if(flag==0){for(int j=0; j<=T; j++)dp[i][j]=-INF;for(int x=1; x<=m; x++)for(int j=T; j>=w[x]; j--)dp[i][j]=max(dp[i][j],max(dp[i-1][j-w[x]]+p[x],dp[i][j-w[x]]+p[x]));}else  if(flag==1){for(int j=0; j<=T; j++)dp[i][j]=dp[i-1][j];for(int x=1; x<=m; x++)for(int j=T; j>=w[x]; j--)dp[i][j]=max(dp[i][j],dp[i-1][j-w[x]]+p[x]);}else{for(int j=0; j<=T; j++)dp[i][j]=dp[i-1][j];for(int x=1; x<=m; x++)for(int j=T; j>=w[x]; j--)dp[i][j]=max(dp[i][j],dp[i][j-w[x]]+p[x]);}}dp[n][T]=max(dp[n][T],-1);printf("%d\n",dp[n][T]);}return 0;
}
 


滚动数组解法————>>>滚动数组解释连接点击打开链接

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define INF 0x3f3f3f3f
using namespace std;
int w[101],p[101];
int dp[101],tem[101];
int main()
{int n,T;while(~scanf("%d %d",&n,&T)){memset(dp,0,sizeof(dp));for(int i=1; i<=n; i++){int m,flag;scanf("%d %d",&m,&flag);for(int x=1; x<=m; x++)scanf("%d %d",&w[x],&p[x]);if(flag==0){for(int j=0; j<=T; j++){tem[j]=dp[j];dp[j]=-INF;}for(int x=1; x<=m; x++)for(int j=T; j>=w[x]; j--)dp[j]=max(dp[j],max(dp[j-w[x]]+p[x],tem[j-w[x]]+p[x]));}else  if(flag==1){for(int j=0; j<=T; j++){tem[j]=dp[j];}for(int x=1; x<=m; x++)for(int j=T; j>=w[x]; j--)dp[j]=max(dp[j],tem[j-w[x]]+p[x]);}else{for(int x=1; x<=m; x++)for(int j=T; j>=w[x]; j--)dp[j]=max(dp[j],dp[j-w[x]]+p[x]);}}dp[T]=max(dp[T],-1);printf("%d\n",dp[T]);}return 0;
}



这篇关于hdu 3535 AreYouBusy 混合背包的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1115393

相关文章

poj2576(二维背包)

题意:n个人分成两组,两组人数只差小于1 , 并且体重只差最小 对于人数要求恰好装满,对于体重要求尽量多,一开始没做出来,看了下解题,按照自己的感觉写,然后a了 状态转移方程:dp[i][j] = max(dp[i][j],dp[i-1][j-c[k]]+c[k]);其中i表示人数,j表示背包容量,k表示输入的体重的 代码如下: #include<iostream>#include<

hdu2159(二维背包)

这是我的第一道二维背包题,没想到自己一下子就A了,但是代码写的比较乱,下面的代码是我有重新修改的 状态转移:dp[i][j] = max(dp[i][j], dp[i-1][j-c[z]]+v[z]); 其中dp[i][j]表示,打了i个怪物,消耗j的耐力值,所得到的最大经验值 代码如下: #include<iostream>#include<algorithm>#include<

csu(背包的变形题)

题目链接 这是一道背包的变形题目。好题呀 题意:给n个怪物,m个人,每个人的魔法消耗和魔法伤害不同,求打死所有怪物所需的魔法 #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>//#include<u>#include<map

hdu1011(背包树形DP)

没有完全理解这题, m个人,攻打一个map,map的入口是1,在攻打某个结点之前要先攻打其他一个结点 dp[i][j]表示m个人攻打以第i个结点为根节点的子树得到的最优解 状态转移dp[i][ j ] = max(dp[i][j], dp[i][k]+dp[t][j-k]),其中t是i结点的子节点 代码如下: #include<iostream>#include<algorithm

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

hdu 2093 考试排名(sscanf)

模拟题。 直接从教程里拉解析。 因为表格里的数据格式不统一。有时候有"()",有时候又没有。而它也不会给我们提示。 这种情况下,就只能它它们统一看作字符串来处理了。现在就请出我们的主角sscanf()! sscanf 语法: #include int sscanf( const char *buffer, const char *format, ... ); 函数sscanf()和

hdu 2602 and poj 3624(01背包)

01背包的模板题。 hdu2602代码: #include<stdio.h>#include<string.h>const int MaxN = 1001;int max(int a, int b){return a > b ? a : b;}int w[MaxN];int v[MaxN];int dp[MaxN];int main(){int T;int N, V;s

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :