Description
现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi。我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大)。
但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j)。幸运的是,一个软件最多依赖另外一个软件。如果一个软件不能正常工作,那么它能够发挥的作用为0。
我们现在知道了软件之间的依赖关系:软件i依赖软件Di。现在请你设计出一种方案,安装价值尽量大的软件。一个软件只能被安装一次,如果一个软件没有依赖则Di=0,这时只要这个软件安装了,它就能正常工作。
Input
第1行:N, M (0<=N<=100, 0<=M<=500) 第2行:W1, W2, ... Wi, ..., Wn (0<=Wi<=M ) 第3行:V1, V2, ..., Vi, ..., Vn (0<=Vi<=1000 ) 第4行:D1, D2, ..., Di, ..., Dn(0<=Di<=N, Di≠i )
Output
一个整数,代表最大价值。
软件之间的关系构成树或环,暴力把环缩成一点然后就是树形背包了。
#include<cstdio> #include<vector> std::vector<int> ss[128]; int pa[128]; int id[128]; int w[128],v[128],fa; int n,m; int f[128][512]; int g[128][512]; void maxs(int&a,int b){ if(a<b)a=b; } int t=0; void dfs(int x){ int sz=ss[x].size(); if(sz){ for(int i=0;i<sz;i++)dfs(ss[x][i]); int u=ss[x][0]; for(int j=m;j>=0;j--)g[x][j]=f[u][j]; for(int i=1;i<sz;i++){ u=ss[x][i]; for(int j=m;j>=0;j--) for(int k=0;k<=j;k++) maxs(g[x][j],g[x][j-k]+f[u][k]); } for(int j=w[x];j<=m;j++) f[x][j]=g[x][j-w[x]]+v[x]; }else{ for(int i=w[x];i<=m;i++)f[x][i]=v[x]; } } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",w+i); } for(int i=1;i<=n;i++){ scanf("%d",v+i); } for(int i=1;i<=n;i++){ scanf("%d",&fa); if(i!=fa)pa[i]=fa; id[i]=i; } for(int i=1;i<=n;i++){ int a=i; if(~pa[i]) for(int j=1;j<=110;j++){ a=pa[a]; if(a<1)break; if(a==i){ for(a=pa[a];a!=i&&~a;a=fa){ v[i]+=v[a]; w[i]+=w[a]; fa=pa[a]; pa[a]=-1; id[a]=i; } pa[i]=0; break; } } } for(int i=1;i<=n;i++){ if(~pa[i])ss[id[pa[i]]].push_back(i); } dfs(0); printf("%d",f[0][m]); return 0; }
时间: 2024-10-14 08:05:34