HDU-4341 Gold miner 分组背包
这里有多个点与原点的连线共线的话,那么需要对其进行并组,将前一个作为单独的一个,把前两个作为单独的一个...最后直接分组背包就可以了。
代码如下:
#include <cstdlib> #include <cstdio> #include <cstring> #include <algorithm> #define MAXN 205 using namespace std; int N, M, cnt[MAXN], vis[MAXN], idx; int f[40005]; struct Node { int x, y, t, v; bool operator < (Node temp) const { return y < temp.y; } // 对y轴进行排序,这样保证能够先得到最近的点 }e[MAXN]; struct Team { int t, v; }p[MAXN][MAXN]; bool Inline(int a, int b) { return e[a].x * e[b].y == e[a].y * e[b].x; } void init() { int st = 0, sv = 0; idx = 0; memset(vis, 0, sizeof (vis)); memset(cnt, 0, sizeof (cnt)); for (int i = 1; i <= N; ++i) { if (!vis[i]) { vis[i] = 1; ++idx, ++cnt[idx]; st = e[i].t, sv = e[i].v; p[idx][cnt[idx]].t = st; p[idx][cnt[idx]].v = sv; for (int j = 1; j <= N; ++j) { if (!vis[j] && Inline(i, j)) { vis[j] = 1; ++cnt[idx]; st += e[j].t, sv += e[j].v; p[idx][cnt[idx]].t = st; p[idx][cnt[idx]].v = sv; } } } } } void solve() { memset(f, 0, sizeof (f)); for (int i = 1; i <= idx; ++i) { // 首先考虑到某一组,得到这一组的最佳答案 for (int t = M; t >= 0; --t) { // 由于一组中只能够取一件物品,所以这个循环在外层 for (int j = 1; j <= cnt[i]; ++j) { if (t >= p[i][j].t) { f[t] = max(f[t], f[t-p[i][j].t] + p[i][j].v); } } } } printf("%d\n", f[M]); } int main() { int ca = 0; while (scanf("%d %d", &N, &M) == 2) { for (int i = 1; i <= N; ++i) { scanf("%d %d %d %d", &e[i].x, &e[i].y, &e[i].t, &e[i].v); } sort(e+1, e+1+N); printf("Case %d: ", ++ca); init(); solve(); } return 0; }