洛谷 P1064 金明的预算方案(动态规划)

https://www.luogu.com.cn/problem/P1064

题意:

有n元m件物品,每个物品价值v重要度w和附件p,若p=0说明这是主件,p>0则p表示该物品为附件,p是所属主件的编号。附件必须和主件一起买。

思路:

和01背包很像,只不过多了附件。附件必须和主件一起购买,我们可以把它们绑起来,遍历主件,若主件有附件则再去判断附件。(有点像hash里拉链法的存储结构,只不过这里用数组来模拟,指针写起来太麻烦)

代码:

#include <bits/stdc++.h>
using namespace std;
int fu[100][2],f[40000];//fu[i][]记录第i件的附件有哪些 
int v[100],w[100],p[100];
int main()
{
    
    
	int n,m;
	cin>>n>>m;
	int x,y,z;
	int cnt=0;
	for(int i=1;i<=m;i++)
	{
    
    
		cin>>v[i]>>w[i]>>p[i];
		w[i]*=v[i];
		if(p[i])//如果是附件则记录 
		{
    
    
			if(!fu[p[i]][0])//第一件 
			fu[p[i]][0]=i;
			else
			fu[p[i]][1]=i;
		}
	}
	for(int i=1;i<=m;i++)
	{
    
    
		if(!p[i])//不是附件 
		for(int j=n;j>=0;j--)
		{
    
    
			if(j>=v[i])
			{
    
    
				f[j]=max(f[j],f[j-v[i]]+w[i]);
				if(fu[i][0])//如果有附件 
				{
    
    
					int t1=fu[i][0];
					int t2=fu[i][1];//若无附件,则t2为零,不影响结果 
					if(j-v[i]-v[t1]>=0)//可以买主件和附件1 
					f[j]=max(f[j],f[j-v[i]-v[t1]]+w[i]+w[t1]);
					if(j-v[i]-v[t2]>=0)//可以买主件和附件2 
					f[j]=max(f[j],f[j-v[i]-v[t2]]+w[i]+w[t2]);
					if(j-v[i]-v[t1]-v[t2]>=0)//可以买主件和附件1、2; 
					f[j]=max(f[j],f[j-v[i]-v[t1]-v[t2]]+w[i]+w[t1]+w[t2]);
				}
			}
		}
	}
	cout<<f[n];
	return 0;
 } 

猜你喜欢

转载自blog.csdn.net/xiaolan7777777/article/details/105668613