ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

洛谷 P1455 搭配购买

2022-07-31 12:01:07  阅读:106  来源: 互联网

标签:P1455 洛谷 bcj 搭配 kn int include dp first


搭配购买这一题很适合刚学并查集的同学练习。

这一题思路是:并查集 01背包

  并查集:将搭配购买的云用并查集来连接, 并将连接起来的一坨云看做一个物品,再用01背包思路,就可以解决喽。

个人认为的难点是:如何用并查集和怎样存储云的价值和价钱,还有怎么将云的价值和云的价钱合并。

    我个人是这样解决的:

      用结构体定义 p -- 表示并查集的下标,vl -- 价值,r -- 价钱

    

typedef struct bcj1 {
    int p,vl,r;
}BCJ;
BCJ bcj[N];

    那么查找和路径压缩就是

int find(int x) {
  if(bcj[x].p != x) bcj[x].p = find(bcj[x].p);
  return bcj[x].p;        
}

    完成并查集后,

    就是将一坨云的价值和价格存入,转换为01背包问题

    这里我用的是pair<int,int>,first表示价格,second表示价值,

    rep(i,1,n) { // 等价于 for(int i = 1; i <= n; ++i)
        int k = find(i);
        kn[k].first += bcj[i].r;
        kn[k].second += bcj[i].vl;
    }
    sort(kn+1, kn+n+1, cmp); // cmp 自己写的,排序由大到小
    rep(i, 1, n) {
        if(kn[i].first == 0 && kn[i].second == 0) { // 去掉没有 价值的数值
            break;
        }
        cnt++;
    }

    最后是01背包

    for(int i = 1; i <= cnt; ++i) {
        for(int j = w; j >= kn[i].first; --j) {
            dp[j] = max(dp[j], dp[j - kn[i].first] + kn[i].second);
        }
    }
    cout<<dp[w];

    输出答案 dp[w]

最后贴个AC代码:

#include <iostream>
#include <vector>
#include <string>
#include <set>
#include <map>
#include <stdio.h>
#include <sstream>
#include <algorithm>
using namespace std;

#define rep(i,x,n) for(int i = x; i <= n; i++)

typedef long long LL;
typedef pair<int,int> PII;
typedef struct bcj1 {
    int p,vl,r;
}BCJ;

const int N = 10021;
int dp[N];
BCJ bcj[N];
PII kn[N];
int find(int x) {
    if(bcj[x].p != x) bcj[x].p = find(bcj[x].p);
    return bcj[x].p; 
}
bool cmp(PII a, PII b) {
    if(a.first == b.first) {
        return a.second > b.second;
    } else {
        return a.first > b.first;
    }
}
void test();

int main()
{
    //test();
    int n, m, w;
    cin>>n>>m>>w;
    rep(i,1,n) bcj[i].p = i;
    rep(i,1,n) {
        int c,d;
        cin>>c>>d;
        bcj[i].r = c; bcj[i].vl = d;
    }
    rep(i,1,m) {
        int v1,v2;
        cin>>v1>>v2;
        bcj[find(v1)].p = find(v2);
    }
    int cnt = 0;
    rep(i,1,n) {
        int k = find(i);
        kn[k].first += bcj[i].r;
        kn[k].second += bcj[i].vl;
    }
    sort(kn+1, kn+n+1, cmp);
    rep(i, 1, n) {
        if(kn[i].first == 0 && kn[i].second == 0) {
            break;
        }
        cnt++;
    }
    for(int i = 1; i <= cnt; ++i) {
        for(int j = w; j >= kn[i].first; --j) {
            dp[j] = max(dp[j], dp[j - kn[i].first] + kn[i].second);
        }
    }
    cout<<dp[w];
    return 0;
}


void test() {
    #define mytest
    #ifdef mytest
    freopen("test.out", "w", stdout);
    #endif
}
View Code

 

标签:P1455,洛谷,bcj,搭配,kn,int,include,dp,first
来源: https://www.cnblogs.com/yahh/p/16536801.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有