洛谷 P1455 搭配购买
作者:互联网
搭配购买这一题很适合刚学并查集的同学练习。
这一题思路是:并查集 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