题意:给你若干个集合,每个集合内的物品要么选任意一个,要么所有都选,求最后在背包能容纳的范围下最大的价值。
分析:对于每个并查集,从上到下滚动维护即可,其实就是一个01背包= =。
代码如下:
1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 #include <vector> 5 using namespace std; 6 const int N = 1000 + 5; 7 8 int w[N],b[N]; 9 int n,m,W; 10 int root[N]; 11 vector<int> v[N]; 12 int allw[N],allb[N]; 13 int dp[N]; 14 int find(int x) {return x == root[x] ? x : root[x] = find(root[x]);} 15 16 int main() 17 { 18 scanf("%d%d%d",&n,&m,&W); 19 for(int i=1;i<=n;i++) root[i] = i; 20 for(int i=1;i<=n;i++) scanf("%d",w+i); 21 for(int i=1;i<=n;i++) scanf("%d",b+i); 22 for(int i=1;i<=m;i++) 23 { 24 int x,y;scanf("%d%d",&x,&y); 25 int rx = find(x), ry = find(y); 26 if(rx != ry) root[rx] = ry; 27 } 28 for(int i=1;i<=n;i++) 29 { 30 int t = find(i); 31 v[t].push_back(i); 32 allw[t] += w[i]; 33 allb[t] += b[i]; 34 } 35 for(int i=1;i<=n;i++) 36 { 37 if(v[i].size() == 0) continue; 38 for(int j=W;j>=0;j--) 39 { 40 for(int k=0;k<v[i].size();k++) 41 { 42 if(j-w[v[i][k]] >= 0) dp[j] = max(dp[j], dp[j-w[v[i][k]]] + b[v[i][k]]); 43 } 44 if(j-allw[i] >= 0) dp[j] = max(dp[j], dp[j-allw[i]] + allb[i]); 45 } 46 } 47 printf("%d\n",dp[W]); 48 return 0; 49 }
codeforces 742D Arpa's weak amphitheater and Mehrdad's valuable Hoses ——(01背包变形)
时间: 2024-11-10 00:18:58