洛谷 P1064 金明的预算方案

第一次写有依赖的背包问题

哇 感觉好难啊

好不容易搞懂一点点

写个博客吧!

题目链接:https://www.luogu.org/problemnew/show/P1064

#include<iostream>
#include<cstring>
using namespace std;
struct aa
{
	int v,p,q;
}a[60],pat[60][60];
int n,m,t[60],V[60][10],P[60][10],cnt[60],f[32000],ans,i,j,k;
int main()
{
	cin>>n>>m;
	for(i=1;i<=m;i++)
	{
		cin>>a[i].v>>a[i].p>>a[i].q;//输入 
		if(a[i].q!=0)//当他是附件时  
		{
			t[a[i].q]++;//主件有多少附件 
			pat[a[i].q][t[a[i].q]].v=a[i].v;
			pat[a[i].q][t[a[i].q]].p=a[i].p;
			pat[a[i].q][t[a[i].q]].q=a[i].q;//替换输入 
		}
	}
	for(i=1;i<=m;i++)//当物品是附件时是直接跳过的  
	{
		if(t[i]!=0)//选主件也选附件 
		{
			memset(f,-1,sizeof(f)); //当f[i]==-1时表示这个体积下没有选任何一个附件(恰好背包) 
			f[0]=0;
			for(j=1;j<=t[i];j++)//多重背包 对于这件物品的附件选择 
			for(k=n-a[i].v;k>=pat[i][j].v;k--)
			if(f[k]<f[k-pat[i][j].v]+pat[i][j].v*pat[i][j].p&&f[k-pat[i][j].v]!=-1)
			f[k]=f[k-pat[i][j].v]+pat[i][j].v*pat[i][j].p;
			for(j=0;j<=n-a[i].v;j++)
			if(f[j]!=-1)//有用的情况 选择了一个或多个附件  
			{
				cnt[i]++;
				V[i][cnt[i]]=j+a[i].v;
				P[i][cnt[i]]=f[j]+a[i].v*a[i].p;//记录代替 
			}
		}
		if(a[i].q==0)//只选主件 
		{
			cnt[i]++;
			V[i][cnt[i]]=a[i].v;
			P[i][cnt[i]]=a[i].p*a[i].v;//记录代替 
		}
	}
	memset(f,0,sizeof(f));
	for(i=1;i<=m;i++)//分组背包  当物品是附件时是直接跳过的  
	for(j=n;j>=0;j--)
	for(k=1;k<=cnt[i];k++)
	if(j>=V[i][k])
	f[j]=max(f[j],f[j-V[i][k]]+P[i][k]);
	for(i=0;i<=n;i++)
	ans=max(ans,f[i]);//求出最大值 
	cout<<ans<<endl;//输出 
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值