萌新求助!
查看原帖
萌新求助!
169844
w2321楼主2020/10/1 08:15
//桶排+分组背包 20
#include<cstdio>
#define max(a,b) a>b?a:b
#define ri register int
#define maxn 205
int dp[maxn*maxn];
int v0[maxn],w0[maxn];//时间,价值 
int v[maxn][maxn],w[maxn][maxn];//时间,价值 
double k[maxn];//第几个斜率为多大 
int tong[maxn][maxn];
int a[maxn],minv[maxn];
int n,m,cnt,sk;//sk表示第几种斜率 
inline int read()
{
	ri x=0,f=1;
	char ch=getchar();
	while(ch>'9'||ch<'0')
	{
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch<='9'&&ch>='0')
	{
		x=x*10+ch-'0';
		ch=getchar();
	}
	return x*f;
}
int min(int a,int b)
{
	if(a<b) return a;
	return b;
}
int main()
{
	n=read(),m=read();
	for(ri i=1,flag;i<=n;++i)//预处理 
	{
		ri x=read(),y=read();
		v0[i]=read(),w0[i]=read();
		if(x==0)
		{
			tong[0][y]=i;
			continue;
		}
		double k1=y/x*1.0;
		flag=0;
		for(ri j=1;j<=sk;++j)
			if(k1==k[j])
			{
				tong[j][y]=i;//第j种斜率 纵坐标为y 黄金序号 
				flag=1;
				break;
			}
		if(flag==1) continue;
		sk++;//斜率种数加1 
		k[sk]=k1;//记录斜率 
		tong[sk][y]=i;//第sk种斜率 纵坐标为y 黄金序号
	}
	for(ri i=0;i<=sk;++i)
	{
		minv[i]=maxn*maxn;
		for(ri j=0;j<=200;++j)
		{
			ri xu=tong[i][j];
			if(xu==0) continue;
			a[i]++;
			v[i][a[i]]=v[i][a[i]-1]+v0[xu];
			w[i][a[i]]=w[i][a[i]-1]+w0[xu];
			minv[i]=min(minv[i],v[i][a[i]]);
		}
	}
	for(ri i=0;i<=sk;++i)
		for(ri j=m;j>=minv[i];--j)
			for(ri k0=1;k0<=a[i];++k0)
				if(j-v[i][k0]>=0)
					dp[j]=max(dp[j],dp[j-v[i][k0]]+w[i][k0]);
	printf("%d",dp[m]);
	return 0;
}
2020/10/1 08:15
加载中...