【题目描述】
Joe觉得云朵很美,决定去山上的商店买一些云朵。商店里有n朵云,云朵被编号为1,2,…...,n,并且每朵云都有一个价值。但是商店老板跟他说,一些云朵要搭配来买才好,所以买一朵云则与这朵云有搭配的云都要买。
但是Joe的钱有限,所以他希望买的价值越多越好。
【输入】
第1行n,m,w,表示n朵云,m个搭配,Joe有w的钱。
第2~n+1行,每行ci,di表示i朵云的价钱和价值。
第n+2~n+1+m行,每行ui,vi,表示买ui就必须买vi,同理,如果买vi就必须买ui。
【输出】
一行,表示可以获得的最大价值。
【输入样例】
5 3 10 3 10 3 10 3 10 5 100 10 1 1 3 3 2 4 2
【输出样例】
1
【提示】
【数据范围】
30%的数据保证:n≤100
50%的数据保证:n≤1,000;m≤100;w≤1,000
100%的数据保证:n≤10,000;0≤m≤5000;w≤10,000
并查集+01背包
错误代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int p1[10005];
int p2[10005];
int a[10005];
int dp[10005];
int findth(int x){
return a[x]==x?x:findth(a[x]);
}
int main()
{
int n,m,w;
scanf("%d %d %d",&n,&m,&w);
for(int i=1;i<=n;i++){
a[i]=i;
dp[i]=0;
scanf("%d %d",&p1[i],&p2[i]);
}
int x,y;
for(int i=1;i<=m;i++){
scanf("%d %d",&x,&y);
a[x]=y;
p1[findth(y)]+=p1[x];
p2[findth(y)]+=p2[x];
}
int ma=0;
//for(int i=1;i<=n;i++){
// cout<<i<<":"<<a[i]<<endl;
//}
for (int i = 1; i <= n; i++) //n的物品的种类
{
if(a[i]==i){
//cout<<i<<endl;
for (int j = w; j >= p1[i]; j--) //w[]表示物品的所占的容量
{
dp[j] = max(dp[j], dp[j - p2[i]] + p2[i]); //c[]表示物品的价值
if(dp[j]>ma) ma=dp[j];
}
}
}
//for(int i=1;i<=w;i++){
// cout<<i<<":"<<dp[i]<<endl;
//}
printf("%d\n",ma);
return 0;
}
正确代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1e4 + 10;
int n, m, s;
int p[N]; //并查集数组
int w[N];
int c[N];
int f[N];
struct node
{
int c;
int w;
bool flag;
}num[N];
int findth(int x)
{
if (x == p[x]) return x;
return p[x] = findth(p[x]);
}
void unionn(int x, int y)
{
int xx = findth(x);
int yy = findth(y);
if (xx != yy) p[yy] = xx;
}
int cnt;
int ci[N];
int di[N];
int main()
{
scanf("%d %d %d", &n, &m, &s);
for (int i = 1;i <= n;i++) p[i] = i; //初始化并查集
for (int i = 1;i <= n;i++) {
scanf("%d %d", &ci[i], &di[i]);
}
for (int i = 1;i <= m;i++) {
int x, y;
scanf("%d %d", &x, &y);
unionn(x, y);
}
for (int i = 1;i <= n;i++) { //把每个点直接连接父节点,
findth(i);
}
for (int i = 1;i <= n;i++) { //为背包建个结构体数组
num[p[i]].w += ci[i];
num[p[i]].c += di[i];
num[p[i]].flag = true; //标记
}
for (int i=1;i<=n;i++){ //cnt:背包种类个数
if (num[i].flag) {
w[++cnt] = num[i].w;
c[cnt] = num[i].c;
}
}
for (int i = 1;i <= cnt;i++) { //01背包
for (int j = s;j >= w[i];j--) {
f[j] = max(f[j], f[j - w[i]] + c[i]);
}
}
printf("%d\n", f[s]);
return 0;
}
本文介绍了一个结合并查集与01背包算法解决的购买云朵问题。问题中,玩家需在有限预算下,根据云朵的搭配规则和价值,最大化购买云朵的总价值。文章详细解析了问题的输入输出格式,提供了错误与正确的代码对比,帮助读者理解算法实现细节。
1444

被折叠的 条评论
为什么被折叠?



