【洛谷_P2515】软件安装

软件安装


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

第1行:一个整数,代表最大价值。

Sample Input

3 10
5 5 6
2 3 4
0 1 1 

Sample Output

5

解题思路

我们先缩点,再反制,再DP

#include<iostream>
#include<cstdio>
using namespace std;

int n,m,totn,totw,a[1100][1100];
int w[1100],v[1100],b[1100],c[1100];
int fa[1100],f[1100][5100];

void floyed()
{
    
    
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			for(int k=1;k<=n;k++)
				if(a[k][i]==1&&a[i][j]==1)
					a[k][j]=1;
}

void merge()
{
    
    
	totn=n;
	for(int i=1;i<=totn;i++)
		for(int j=1;j<=totn;j++)
		{
    
    
			if(a[i][j]==1&&a[j][i]==1&&w[i]>0&&w[j]>0&&i!=j)
			{
    
    
				totn++;
				w[totn]=w[i]+w[j];
				v[totn]=v[i]+v[j];
				totw--;
				w[i]=totw,w[j]=totw;
			}
			if(a[fa[j]][j]==1&&a[j][fa[j]]==1&&w[fa[j]]<0&&w[j]>0)
			{
    
    
				w[n-w[fa[j]]]+=w[j];
				v[n-w[fa[j]]]+=v[j];
				w[j]=w[fa[j]];
			}
			if(w[fa[j]]<0&&w[j]>0)
				if((a[fa[j]][j]==1&&a[j][fa[j]]==0)||(a[fa[j]][j]==0&&a[j][fa[j]]==1))
					fa[j]=n-w[fa[j]];
		}
}

int dfs(int x,int k)
{
    
    
	if(f[x][k]>0)
		return f[x][k];
	if(x==0||k<=0)
		return 0;
	f[b[x]][k]=dfs(b[x],k);
	f[x][k]=f[b[x]][k];
	int y=k-w[x];
	for(int i=0;i<=y;i++)
	{
    
    
		f[c[x]][y-i]=dfs(c[x],y-i);
		f[b[x]][i]=dfs(b[x],i);
		f[x][k]=max(f[x][k],v[x]+f[c[x]][y-i]+f[b[x]][i]);
	}
	return f[x][k];
}

int main()
{
    
    
	cin>>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[i]);
		a[fa[i]][i]=1;
	}
	floyed();
	merge();
	for(int i=1;i<=totn;i++)
		if(w[i]>0)
		{
    
    
			b[i]=c[fa[i]];
			c[fa[i]]=i;
		}
	cout<<dfs(c[0],m)<<endl;
}

猜你喜欢

转载自blog.csdn.net/SSL_guyixin/article/details/108018286