您的位置:首页 > 其它

Vijos P1250 - 最勇敢的机器人

2014-08-28 20:39 337 查看


思路

用并查集,然后分组背包。

背包九讲造福人类。

分组背包和一般的背包差不多,就是把一组作为一个点考虑。

在如何把它们集中到一组想了很久,后来还是暴力了。先把它们都分好,然后扫描一遍根节点,把相同根节点的都存到一个数组里,然后遍历一遍数组。


代码

#include <cstdio>

#include <cstring>

#include <algorithm>

#include <map>

#include <queue>

#include <cctype>

#define MP(a, b) make_pair(a, b)

using namespace std;

const int MAXN = 1000 + 5;

const int INF = 0x3f3f3f3f;


struct EQP

{

int val, w;

}eqp[MAXN];


vector<int> ve[MAXN];

int dp[MAXN][10000], pa[MAXN];


int Find(int x)

{

return pa[x] == x ? x : pa[x] = Find(pa[x]);

}


int main()

{

//freopen("input.txt", "r", stdin);

int n, wMax, k, i, j;

scanf("%d%d%d", &n, &wMax, &k);

for (i = 1; i <= n; i++)

scanf("%d%d", &eqp[i].val, &eqp[i].w);

for (i = 1; i <= n; i++)

pa[i] = i;

for (i = 0; i < k; i++)

{

int a, b;

scanf("%d%d", &a, &b);

int x = Find(a), y = Find(b);

if (x != y)

pa[x] = y;

}

for (i = 1; i <= n; i++)

{

int x = Find(i);

ve[x].push_back(i);

}

int cnt = 0;

for (i = 1; i <= n; i++)

{

if (!ve[i].empty())

{

cnt++;

for (j = 0; j <= wMax; j++)

{

dp[cnt][j] = dp[cnt - 1][j];

for (int k = 0; k < ve[i].size(); k++)

if (j >= eqp[ve[i][k]].w)

dp[cnt][j] = max(dp[cnt][j], dp[cnt - 1][j - eqp[ve[i][k]].w] + eqp[ve[i][k]].val);

}

}

}

printf("%d\n", dp[cnt][wMax]);

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: