2018.11.09【NOIP2006】【洛谷P1064】金明的预算方案(有依赖的背包问题)

传送门


解析:

首先我并没有读完题。。我也没有管什么只有两个依赖,,我直接写的最裸的单层依赖的背包问题。。。(其实依赖下面套分组还比这个要恶心)。

思路:

由于我们直接枚举所有策略,对于一个物品集合是O(2∣S∣)O(2^{|S|})O(2S)的,所以我们可以先在集合内部做一次010101背包,注意,为了减小最终的物品个数,可以使用恰好背包。

然后就是集合与集合之间的分组背包裸题了。


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const

cs int N=65,M=32004;
vector<pair<int,int> > vec[N];
vector<pair<int,int> > item[N];
int v[N],p[N],q[N];
int f[M];
int n,m;
signed main(){
	scanf("%d%d",&n,&m);
	for(int re i=1;i<=m;++i){
		scanf("%d%d%d",&v[i],&p[i],&q[i]);
		if(q[i]){
			vec[q[i]].push_back(make_pair(v[i],p[i]));
		}
	}
	for(int re i=1;i<=m;++i){
		if(!vec[i].empty()){
			memset(f,-1,sizeof f);
			f[0]=0;
			for(int re j=0;j<vec[i].size();++j){
				for(int re k=n-v[i];k>=vec[i][j].first;--k){
					if((~f[k-vec[i][j].first])&&f[k]<f[k-vec[i][j].first]+vec[i][j].first*vec[i][j].second){
						f[k]=f[k-vec[i][j].first]+vec[i][j].first*vec[i][j].second;
					}
				}
			}
			for(int re k=n-v[i];k;--k){
				if(~f[k]){
					item[i].push_back(make_pair(k+v[i],f[k]+v[i]*p[i]));
				}
			}
		}
		if(!q[i]){
			item[i].push_back(make_pair(v[i],v[i]*p[i]));
		}
	}
	memset(f,0,sizeof f);
	for(int re i=1;i<=m;++i)
	for(int re k=n;k;--k)
	for(int re j=0;j<item[i].size();++j)
	if(k>=item[i][j].first)f[k]=max(f[k],f[k-item[i][j].first]+item[i][j].second);
	cout<<f[n];
	return 0;
}

转载于:https://www.cnblogs.com/zxyoi/p/10047094.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值