CF808E Selling Souvenirs
一个牛逼又好写的做法!
首先,因为
这样的话会 WA on #21,因为会被形如这样的数据卡掉:
4001 12000
1 10000
3 10001
3 10001
3 10001
3 10001
3 10001
3 10001
3 10001
3 10001
3 10001
3 10001
...
这样的话虽然
为什么只需要反悔一个呢?假设我们在上面反悔了多个,显然
对于
然后就做完了。
#include <bits/stdc++.h>
#define int long long
#define F(i, a, b) for (int i = (a); i <= (b); i++)
#define dF(i, a, b) for (int i = (a); i >= (b); i--)
using namespace std;
const int N = 100005, M = (N << 1), inf = 1e16, mod = 1e9 + 7;
int n, m, ans, sum, f[10], x[4];
struct node {
int w, c;
bool operator < (node x) const { return w * x.c < c * x.w; }
} a[N];
signed main() {
ios_base::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n >> m;
F(i, 1, n) cin >> a[i].w >> a[i].c;
sort(a + 1, a + n + 1);
int pos = 1;
memset(x, 0x3f, sizeof x);
while (m > 6 && pos <= n) {
m -= a[pos].w, sum += a[pos].c;
if (x[a[pos].w] > a[pos].c) x[a[pos].w] = a[pos].c; pos++;
}
if (pos > n) cout << sum, exit(0);
memset(f, 0xcf, sizeof f); f[0] = 0;
F(i, pos, n) dF(j, m + 3, a[i].w) f[j] = max(f[j], f[j - a[i].w] + a[i].c);
F(i, 1, m + 3) f[i] = max(f[i], f[i - 1]);
F(i, 1, 3) if (x[i] < inf) ans = max(ans, sum - x[i] + f[m + i]);
cout << max(ans, sum + f[m]) << '\n';
return 0;
}