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;    

}

你可能感兴趣的:(HDU)