欢迎神犇吊打|

Hanx16Msgr

园龄:2年8个月粉丝:12关注:3

2022-07-11 11:37阅读: 30评论: 0推荐: 0

#P2056. ABCD

#P2056. ABCD

题目描述

有 4 个长度为 N 的数组 a,b,c,d。现在需要你选择 N 个数构成数组 e,数组 e 满足 a[i]e[i]b[i] 以及

i=1ne[i]c[i]=0

并且使得

i=1Ne[i]d[i]

最大。

输入格式

输入文件共 N+1 行。

第 1 行包含 1 个正整数 N。

第 i+1 行包含 4 个整数 a[i],b[i],c[i],d[i]。

输出格式

输出共 1 行,包含 1 个整数,表示所给出公式的最大值。输入数据保证一定有解。

样例

输入数据 1

5
-1 1 2 5
-2 2 1 2
0 1 1 3
-2 -1 3 10
-2 2 3 9

输出数据 1

2

输入数据 1

10
1 10 1 7
-10 10 2 0
-10 10 2 2
-10 10 2 0
1 10 1 0
-10 10 2 0
10 10 2 0
1 10 1 0
-10 10 2 0
1 10 1 0

输出数据 1

90

数据规模与约定

对于 20%的数据,N102a[i]<b[i]2

对于 60%的数据,N5020a[i]<b[i]20

对于 100%的数据,N20025a[i]<b[i]25,1c[i]20;0d[i]100000

Solution

这道题可以看作一道多重背包的题,每个物品可以选 a[i]b[i] 件,重量为 c[i] ,价值为 d[i] ,最终要求总重量为 0 即可。

可以最简单的多重背包暴力枚举,常数小一点时间可以卡过去,如果担心常数,单调队列优化即可。

如果不对 a[i],b[i],c[i] 做特殊处理, f 的第二维会出现负数,导致 RE ,解决办法就是在更新答案的时候将第二维加上 MAXN (此题 MAXN=aminN=50000),就可以使第二维全部为自然数而非负数,注意 f 的大小应该开到 MAXN×2,因为第二维的大小在加上 MAXN 前为 [MAXN,MAXN]

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<limits.h>
#include<cmath>
#define mem(a,b) memset(a,b,sizeof(a));
using namespace std;
template<typename T> void read(T &k)
{
 	k=0;
	T flag=1;char b=getchar();
	while (b<'0' || b>'9') {flag=(b=='-')?-1:1;b=getchar();}
	while (b>='0' && b<='9') {k=(k<<3)+(k<<1)+(b^48);b=getchar();}
	k*=flag;
}
const int _SIZE=2e2;
int n;
int a[_SIZE+5],b[_SIZE+5],c[_SIZE+5],d[_SIZE+5];
const int MAXN=5e4;
int f[_SIZE+5][(MAXN<<1)+5];
int main()
{
	read(n);
	for (int i=0;i<=n;i++)
		for (int j=0;j<=(MAXN<<1);j++)
			f[i][j]=-INT_MAX/3;
	for (int i=1;i<=n;i++)
	{
		read(a[i]);read(b[i]);
		read(c[i]);read(d[i]);
	}
	int l=0,r=(MAXN<<1);
	f[0][MAXN]=0;
	for (int i=1;i<=n;i++)
	{
		for (int j=l;j<=r;j++)
		{
			for (int k=a[i];k<=b[i];k++)
			{
				if (j-k*c[i]>=l && j-k*c[i]<=r)
					f[i][j]=max(f[i][j],f[i-1][j-k*c[i]]+k*d[i]);
			}
		}
	}
	//for (int j=MAXN-5;j<=MAXN+5;j++) printf("%d rm=%d\n",f[1][j],j-MAXN);puts("");
	printf("%d\n",f[n][MAXN]);
	return 0;
}

posted @   Hanx16Msgr  阅读(30)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起