NHOI2015E 黄金矿工
分组背包
在那些多色线段上,每个与方格格点的交点都可以埋藏一个物品。显然,在每条线段上,要取距坐标原点远的物品,一定要先取这条线段上距坐标原点近的所有物品。将这条线段上的物品按照到原点的距离从近到远编号为1~x,那么可能的情况有不取、取第1件物品、取前2件物品、取前3件物品……取前x件物品(全取)共(x+1)种情况。因此,按线段分组,每一组里包含了这条线段上的(x+1)种情况即可
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 101, maxm = 10001;
struct node {
int x, y, c;
} item[maxn];
int f[maxm], f_[maxm], t[maxn], c[maxn];
//slope斜率
int slopecmp(node a, node b) {
return a.x * b.y - b.x * a.y;
}
bool cmp(node a, node b) {
if (slopecmp(a, b))
return slopecmp(a, b) > 0;
return a.y > b.y;
}
int main() {
freopen("gold.in", "r", stdin);
freopen("gold.out", "w", stdout);
int n, m, i, j, k, v;
scanf("%d%d", &n, &m);
for (i = 0; i < n; i++)
scanf("%d%d%d", &item[i].x, &item[i].y, &item[i].c);
sort(item, item + n, cmp);
for (i = 0; i < n; ) {
j = 1;
do {
t[j] = t[j - 1] + item[i].x * item[i].x + item[i].y * item[i].y;
c[j] = c[j - 1] + item[i].c;
i++, j++;
} while (i < n && !slopecmp(item[i - 1], item[i]));
for (k = 1; k < j; k++)
for (v = m; v >= t[k]; v--)
f[v] = max(f[v], f_[v - t[k]] + c[k]);
for (v = 0; v <= m; v++)
f_[v] = f[v];
}
printf("%d\n", f[m]);
return 0;
}
再贴一个逻辑不明就里的标程
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 100 + 2;
const int maxm = 10000 + 2;
struct Point {
int x, y, c;
} d[maxn];
bool cmp(Point a, Point b) {
if (a.y * b.x != a.x * b.y)
return a.y * b.x < a.x * b.y;
return a.y > b.y;
}
int cost[maxn], value[maxn], f[maxn][maxm], g[maxn][maxm];
int main() {
freopen("gold.in", "r", stdin);
freopen("gold.out", "w", stdout);
int n, m;
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++)
scanf("%d%d%d", &d[i].x, &d[i].y, &d[i].c);
sort(d, d + n, cmp);
for (int h = 0; h < n; h++) {
int t = h;
while (t < n && d[t].y * d[h].x == d[t].x * d[h].y)
t++;
t--;
cost[h] = d[h].x * d[h].x + d[h].y * d[h].y;
value[h] = d[h].c;
for (int i = h + 1; i <= t; i++) {
cost[i] = cost[i - 1] + d[i].x * d[i].x + d[i].y * d[i].y;
value[i] = value[i - 1] + d[i].c;
}
for (int i = h; i <= t; i++) {
for (int j = cost[i]; j <= m; j++) {
if (h == 0)
f[i][j] = value[i];
else
f[i][j] = max(g[h - 1][j], g[h - 1][j - cost[i]] + value[i]);
g[t][j] = max(g[t][j], f[i][j]);
}
for (int j = 0; j < cost[i]; j++)
g[t][j] = max(g[t][j], g[h - 1][j]);
}
h = t;
}
printf("%d\n", g[n - 1][m]);
return 0;
}