【泛化物品】【HDU1712】【ACboy needs your help】

ACboy needs your help

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4491    Accepted Submission(s): 2403


Problem Description
ACboy has N courses this term, and he plans to spend at most M days on study.Of course,the profit he will gain from different course depending on the days he spend on it.How to arrange the M days for the N courses to maximize the profit?
 

Input
The input consists of multiple data sets. A data set starts with a line containing two positive integers N and M, N is the number of courses, M is the days ACboy has.
Next follow a matrix A[i][j], (1<=i<=N<=100,1<=j<=M<=100).A[i][j] indicates if ACboy spend j days on ith course he will get profit of value A[i][j].
N = 0 and M = 0 ends the input.
 

Output
For each data set, your program should output a line which contains the number of the max profit ACboy will gain.
 

Sample Input
   
   
   
   
2 2 1 2 1 3 2 2 2 1 2 1 2 3 3 2 1 3 2 1 0 0
 

Sample Output
   
   
   
   
3 4 6
 

Source
HDU 2007-Spring Programming Contest
 


背包九讲中已经很好的介绍了这种问题:

复杂度(n*m*m)

泛化物品 

定义  
考虑这样一种物品,它并没有固定的费用和价值,而是它的价值随着你分配给它的费用而变化。这就是泛化物品的概念。  

更严格的定义之。在背包容量为 V 的背包问题中,泛化物品是一个定义域为 0..V 中的整数的函数 h ,当分配给它的费用为 v 时,能得到的价值就是 h(v)  

这个定义有一点点抽象,另一种理解是一个泛化物品就是一个数组 h[0..V] ,给它费用 v ,可得到价值 h[V]  

一个费用为 c 价值为 w 的物品,如果它是 01 背包中的物品,那么把它看成泛化物品,它就是除了 h(c)=w 其它函数值都为 0 的一个函数。如果它是完全背包中的物品,那么它可以看成这样一个函数,仅当 v c 整除时有 h(v)=v/c*w ,其它函数值均为 0 。如果它是多重背包中重复次数最多为 n 的物品,那么它对应的泛化物品的函数有 h(v)=v/c*w 仅当 v c 整除且 v/c<=n ,其它情况函数值均为 0  

一个物品组可以看作一个泛化物品 h 。对于一个 0..V 中的 v ,若物品组中不存在费用为 v 的的物品,则 h(v)=0 ,否则 h(v) 为所有费用为 v 的物品的最大价值。 P07 中每个主件及其附件集合等价于一个物品组,自然也可看作一个泛化物品。  

泛化物品的和  
如果面对两个泛化物品 h l ,要用给定的费用从这两个泛化物品中得到最大的价值,怎么求呢?事实上,对于一个给定的费用 v ,只需枚举将这个费用如何分配给两个泛化物品就可以了。同样的,对于 0..V 的每一个整数 v ,可以求得费用 v 分配到 h l 中的最大价值 f(v) 。也即 f(v)=max{h(k) +l(v-k)|0<=k<=v} 。可以看到, f 也是一个由泛化物品 h l 决定的定义域为 0..V 的函数,也就是说, f 是一个由泛化物品 h  l 决定的泛化物品。  

由此可以定义泛化物品的和: h l 都是泛化物品,若泛化物品 f 满足 f(v)=max{h(k)+l(v-k)|0<=k<=v} ,则称 f h l 的和,即 f=h+l 。这个运算的时间复杂度是 O(V^2)  

泛化物品的定义表明:在一个背包问题中,若将两个泛化物品代以它们的和,不影响问题的答案。事实上,对于其中的物品都是泛化物品的背包问题,求它的答案的过程也就是求所有这些泛化物品之和的过程。设此和为s,则答案就是s[0..V]中的最大值。 


#include <cstdio>  
#include <cstdlib>  
#include <cmath>  
#include <cstring>  
#include <ctime>  
#include <algorithm>  
#include <iostream>
#include <sstream>
#include <string>
#define oo 0x13131313   
using namespace std;
int n,m;
int A[101][101];
void input()
{
	for(int i=1;i<=n;i++)
	 for(int j=1;j<=m;j++)
	 	scanf("%d",&A[i][j]);
}
void init()
{
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
}
void ADD(int *ans,int *a,int *b)
{
	for(int i=0;i<=m;i++)
	{
		ans[i]=0;
		for(int j=0;j<=i;j++)
		{
			ans[i]=max(ans[i],a[j]+b[i-j]);
		}
	}
}
void solve()
{
	int ans=0;
	if(n>=2)
	{
		ADD(A[0],A[1],A[2]);
		for(int i=3;i<=n;i++)
		ADD(A[i-2],A[i-3],A[i]);
		for(int i=1;i<=m;i++)
		ans=max(ans,A[n-2][i]);
		printf("%d\n",ans);
	}
	else 
	{
		for(int i=1;i<=m;i++)
		ans=max(ans,A[1][i]);
		printf("%d\n",ans);
	}
}
int main()
{
//	init();
	while(cin>>n>>m&&(n||m))
	{
		input();
		solve();
	}
}
  


你可能感兴趣的:(【泛化物品】【HDU1712】【ACboy needs your help】)