题解 P1064 【金明的预算方案】

大致思路

这个题给了主件,附件,很明显按照主件来分组,然后再转化为背包问题

各变量

int v[65],p[65],q[65],ty[65][65],dp[200005],temp[200005];

v为每个物品价格,p为重要度,q为是否为主件或从属主件的编号,ty为分的组,dp储存的状态,temp为暂存数组

分组部分代码

	for(int i=1;i<=m;i++)
	{
		cin>>v[i]>>p[i]>>q[i];
		if(q[i]!=0)
			ty[q[i]][++ty[q[i]][0]]=i;		
	}

每个数组的第一个元素存该组的附件数量,数组的值存的是每个附件的下标。

最重要的部分

既然已经分了组,那么就可以先枚举每一个分的组。接下来就可以按照0-1背包的思路来做了。

	for(int i=1;i<=m;i++)//按照编号来枚举
	{
		if(q[i]!=0)
			continue;//如果枚举到附件就跳过
		if(ty[i][0]!=0)//如果该主件有附件
		{
			for(int j=v[i];j<=n;j++)
				temp[j]=dp[j];//将现在的每个状态暂时储存
			for(int j=n;j>=v[i];j--)
				dp[j]=dp[j-v[i]]+v[i]*p[i];//将每一个状态都更新为选了该主件的状态
			for(int j=1;j<=ty[i][0];j++)
			{
				int x=ty[i][j];
				for(int k=n;k>=v[x]+v[i];k--)
					dp[k]=max(dp[k],dp[k-v[x]]+v[x]*p[x]);					
			}//0-1背包
			for(int j=v[i];j<=n;j++)
				dp[j]=max(dp[j],temp[j]);//比较选与不选的值谁更大		
		}
		else//没有附件
		{
			for(int k=n;k>=v[i];k--)
				dp[k]=max(dp[k],dp[k-v[i]]+v[i]*p[i]);//0-1背包
		}		
	}

最后再输出就行了

posted @ 2020-08-07 11:46  DSHUAIB  阅读(53)  评论(0)    收藏  举报