1252. 搭配购买 - AcWing题库
一个有条件的背包题,大意就是给出一个01背包题的数据,然后加上一些必须在一起的组合
题目:
一开始思路是写一个并查集,然后遍历把原来的背包数据更新后存在两个新的数组中(后来想想其实多此一举)(想想为什么不用把更新后的数据单放在其他数组里)
我的复杂ac代码:
#includeusing namespace std; const int N=10005; int w[N],v[N],p[N];//原始数据和标记 int book[N];//存下标 int ww[N],vv[N];//新数据 int dp[N];//背包 int find(int x){ if(p[x]!=x)p[x]=find(p[x]); return p[x]; } int main(){ int n,m,c; cin>>n>>m>>c; for(int i=1;i<=n;i++){ p[i]=i; }//初始化 for(int i=1;i<=n;i++){ cin>>v[i]>>w[i]; } int x,y; for(int i=1;i<=m;i++){ cin>>x>>y; p[find(x)]=find(y);//这句别忘 }//并查集核心 *** 作 int vis=0;//下标 for(int i=1;i<=n;i++){ if(!book[find(p[i])])book[find(p[i])]=++vis;//存下标 ww[book[find(p[i])]]+=w[i]; vv[book[find(p[i])]]+=v[i]; } int ans=0; for(int i=1;i<=vis;i++){ for(int j=c;j>=vv[i];j--){ dp[j]=max(dp[j],dp[j-vv[i]]+ww[i]);//背包 } } cout< 题解简洁代码:
#includeusing namespace std; const int N=10010; int p[N],w[N],v[N],f[N]; int n,m,c; int find(int x) { if (p[x] != x) p[x] = find(p[x]); return p[x]; } int main(){ cin >> n >> m >> c; for (int i = 1; i <= n; i ++ ) p[i] = i; for (int i = 1; i <= n; i ++ ) cin >> v[i] >> w[i]; while(m--){ int a,b; cin >> a >> b; int pa=find(a);int pb=find(b); if(pa!=pb){ w[pb]+=w[pa]; v[pb]+=v[pa]; p[pa]=p[pb]; } } for (int i = 1; i <= n; i ++ ) if (p[i] == i)//这里一开始没想到 for (int j = c; j >= v[i]; j -- ) f[j] = max(f[j], f[j - v[i]] + w[i]); cout << f[c]; } 通过这个题解回答前面的伏笔
for (int i = 1; i <= n; i ++ ) if (p[i] == i)//这里一开始没想到 for (int j = c; j >= v[i]; j -- ) f[j] = max(f[j], f[j - v[i]] + w[i]);这个思路就是在原先的数组里更改,利用了p[i]==i时是一个根节点的性质,能省不少行代码。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)