拔河比赛2(子集型动规)

Description

  学校决定举行一次全校性的拔河比赛,以班为单位组队。我们知道影响拔河比赛胜负的因素有:参赛队的合力量、总重量和技巧。如果每只队伍的人数都一样的话,那么低年级的班级会没有获胜的希望。因此学校考虑到比赛公平性和参与的广泛性,做出如下规定:

  ◆ 每只队伍的人数不一定相同,但队员的总重量不能超过某个规定的值。
  ◆ 每只队伍的女队员必须达到一定的人数。

  多多是高二x班的体育委员,班主任将本班组队的任务交给了他。多多深知影响比赛胜败的三个关键因素中力量和重量是前提,技巧靠后期训练。因此他必须先考虑在学校规定的前提下,选那些同学才能获得最大的合力量。

Input

  第一行3个数整数:分别表示队员总重量上限W(<=4000)、多多班上学生总人数N(<=60)、女同学人数M(<=30);  第2行一个整数,表示参赛队中必须达到的女队员人数K(<=10);  接下来N行每行2个整数,分别表示多多班上每个同学的重量和力量,其中第3到M+2行是所有女生的重量和力量,第M+3到N+2行表示所有男同学的重量和力量,每个整数在60至180之间。

Output

  一行一个整数,合力量的最大值。

思路:对男生做01背包,f1[i]表示重量为i时最大的力量。对女生做K物品背包,f2[i][j]表示选了i个女生,重量为j时的最大力量。然后枚举女生的人数和重量即可。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXN=65;
const int MAXM=35;
const int MAXK=35;
const int MAXW=4005;
const int INF=500000000;
int K,N,M,W,w1[MAXN],s1[MAXN],w2[MAXN],s2[MAXN],f1[MAXW],f2[MAXN][MAXW],sum1[MAXN],sum2[MAXN];
int main()
{
	scanf("%d%d%d%d",&W,&N,&M,&K);
	int i,j,k;
	for(i=1;i<=M;i++)
		scanf("%d%d",&w2[i],&s2[i]);
		
	for(i=1;i<=N-M;i++)
		scanf("%d%d",&w1[i],&s1[i]);
	
	for(i=1;i<=N;i++)
		f1[i]=-INF;
	for(i=1;i<=M;i++)
	for(j=1;j<=W;j++)
		f2[i][j]=-INF;	
	
	for(i=1;i<=N-M;i++)  //对男生做01背包 
	for(j=W;j>=w1[i];j--)
		f1[j]=max(f1[j],f1[j-w1[i]]+s1[i]);
	
	for(i=1;i<=M;i++)    //对女生做K物品背包 
	for(j=i;j>=1;j--)
	for(k=W;k>=w2[i];k--)
		f2[j][k]=max(f2[j][k],f2[j-1][k-w2[i]]+s2[i]);
	
	int ans=0;
	for(i=K;i<=M;i++)    //女生K个人起步 
	for(j=0;j<=W;j++)    //枚举女生重量 
		ans=max(ans,f2[i][j]+f1[W-j]);
	printf("%d",ans);
	return 0;
	
}

猜你喜欢

转载自blog.csdn.net/WWWengine/article/details/81156004