【动态规划 贪心】JZOJ_6309 完全背包

题意

完全背包 ( n ≤ 1 0 6 , m ≤ 1 0 16 , a i , b i ≤ 100 ) (n\leq10^6,m\leq10^{16},a_i,b_i\leq100) (n106m1016ai,bi100)

思路

m m m很大, O ( n m ) O(nm) O(nm)直接 G G GG GG
但是发现 a i , b j ≤ 100 a_i,b_j\leq100 ai,bj100,所以最多选 100 100 100种物品。获得了 60 60 60分的好成绩。

其实我们能发现一个大背包能由若干个小背包组成,并且在这里插入图片描述
所以对于每种容量的背包,把它选完,剩下的用剩下容量的背包填补。

代码

#include <cctype>
#include <cstdio>
#include <algorithm>
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
#define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)

char buf[1 << 21], *p1 = buf, *p2 = buf;

inline long long read() {
    long long res = 0, f = 0;
	char ch = getchar();
    while (!isdigit(ch)) {
        if (ch == '-') f = 1;
        ch = getchar();
    }
    while (isdigit(ch)) {
        res = res * 10 + ch - 48;
        ch = getchar();
    }
    return f ? -res : res;
}

long long n, m, ans;
int a[101];
long long f[5052];

int main() {
	file(backpack);
	n = read();
	m = read();
	for (register int i = 1; i <= n; i++) {
		int x = read(), y = read();
		a[x] = std::max(a[x], y);
	}
	for (register int i = 1; i <= 100; i++)
		for (register int j = i; j <= 5051; j++)
			f[j] = std::max(f[j], f[j - i] + a[i]), ans = std::max(ans, m / j * f[j] + f[m % j]);
	printf("%lld", ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值