2022.1.21

上午 P1455 搭配购买发现它除了并查集还需要01背包来解决。然后就去看01背包,才发现这个还有空间优化。

下午 写了这一题,看了P2835 刻录光盘(无果)

题目描述

明天就是母亲节了,电脑组的小朋友们在忙碌的课业之余挖空心思想着该送什么礼物来表达自己的心意呢?听说在某个网站上有卖云朵的,小朋友们决定一同前往去看看这种神奇的商品,这个店里有 nn 朵云,云朵已经被老板编号为 1,2,3,...,n1,2,3,...,n,并且每朵云都有一个价值,但是商店的老板是个很奇怪的人,他会告诉你一些云朵要搭配起来买才卖,也就是说买一朵云则与这朵云有搭配的云都要买,电脑组的你觉得这礼物实在是太新奇了,但是你的钱是有限的,所以你肯定是想用现有的钱买到尽量多价值的云。

输入格式

第一行输入三个整数,n,m,wn,m,w,表示有 nn 朵云,mm 个搭配和你现有的钱的数目。

第二行至 n+1n+1 行,每行有两个整数, c_i,d_ici​,di​,表示第 ii 朵云的价钱和价值。

第 n+2n+2 至 n+1+mn+1+m 行 ,每行有两个整数 u_i,v_iui​,vi​。表示买第 u_iui​ 朵云就必须买第 v_ivi​ 朵云,同理,如果买第 v_ivi​ 朵就必须买第 u_iui​ 朵。

输出格式

一行,表示可以获得的最大价值。

输入输出样例

输入 #1复制

5 3 10
3 10
3 10
3 10
5 100
10 1
1 3
3 2
4 2

输出 #1复制

1

说明/提示

  • 对于 30\%30% 的数据,满足 1 \le n \le 1001≤n≤100;
  • 对于 50\%50% 的数据,满足 1 \le n,w \le 10^31≤n,w≤103,1 \le m \le 1001≤m≤100;
  • 对于 100\%100% 的数据,满足 1 \le n \le 10^41≤n≤104,0 \le m \le 5 \times 10^30≤m≤5×103。

先并查集将云的亲戚价格价值弄到一起,然后01背包求最大价值,这个时候要空间优化,不然就内存超限了。

#include<stdio.h>

int n,m,sw;
int f[10001],w[10001],v[10001];
int dp[10001]={0},q[10001]={0};
int w1[10001],v1[10001];

int getf(int v)
{
    if(f[v]==v) return v;
    else{
        f[v]=getf(f[v]);//路径压缩
        return f[v];
    }
}

void merge(int x,int y)//合并
{
    int t1,t2;
    t1=f[x];
    t2=f[y];
    if(t1!=t2){
        f[t2]=t1;
    }
}

int max(int x,int y)//最大值
{
    int max=x;
    if(x<y) max=y;
    return max;
}

int main()
{

    scanf("%d%d%d",&n,&m,&sw);
    for(int i=1;i<=n;i++)//初始化
        f[i]=i;
    for(int i=1;i<=n;i++)
        scanf("%d%d",&w[i],&v[i]);
    for(int i=1;i<=m;i++){
            int x,y;
        scanf("%d%d",&x,&y);
        merge(x,y);//合并
    }
    int k=1,t;
    //将可以合并的价格价值合并到一起
    for(int i=1;i<=n;i++){
        if(q[i]==0){//没有合并过
            t=getf(i);
            w1[k]=w[i];
            v1[k]=v[i];
            q[i]=1;
        }
        else continue;
        for(int j=1;j<=n;j++){
            if(q[j]==0){//找没有合并过的
                if(t==getf(j)){
                    w1[k]+=w[j];
                    v1[k]+=v[j];
                    q[j]=1;
                }
            }
        }
        k++;
    }
    //01背包空间优化
    for(int i=1;i<k;i++){
        for(int j=sw;j>=1;j--)
            if(j>=w1[i]) dp[j]=max(dp[j],dp[j-w1[i]]+v1[i]);
    }
    printf("%d\n",dp[sw]);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值