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;
}
posted @ 2017-08-06 22:12  Planet6174  阅读(373)  评论(0编辑  收藏  举报