HDU3182 - Hamburger Magi(状压DP)

题目链接 HDU3182

【题意】

有n个汉堡,某个人当前有E能量值,吃掉每个汉堡需要花费ei能量,可以获得vi价值,并且吃掉当前汉堡之前必须先制作Q[ ]汉堡,每个Qi输入最后几行给出了,每个汉堡只能被吃掉一次。求出改人能获得的最大的能量值。

【分析】

有点类似背包,其实不需要背包,超级简单,只要用dp[s]表示当前已经吃掉的的汉堡集合s(状压表示)最多还能获得多少价值,直接记忆化搜一下就行了,达不到要求的不会被搜索到。最后dp[0]就是所求的最大值,具体看代码。

【AC代码】0ms

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAXN 15
struct NODE{
	int len, s[MAXN];
}p[MAXN];
int n, m, v[MAXN], w[MAXN], dp[1<<MAXN];
//dp[s]表示当前已经吃掉的汉堡集合s还能获得的最大价值

bool ok(int s, int i)//判断现在已经吃掉的汉堡能否满足吃掉汉堡i
{
	for (int j = 0; j < p[i].len; j++)
	{
		if (0 == (s&(1 << p[i].s[j])))
			return false;
	}
	return true;
}
int dfs(int s, int c)
{
	if (-1 != dp[s]) return dp[s];
	dp[s] = 0;
	for (int i = 0; i < n; i++)
	{
		if (s&(1 << i)) continue;//已经吃掉的汉堡不能再做了
		if (0 <= c - w[i] && ok(s, i))//找到下一个吃掉哪种汉堡能获得的价值最大
			dp[s] = max(dp[s], dfs(s|(1<<i),c-w[i])+v[i]);
	}
	return dp[s];
}
int main()
{
#ifdef SHY
	freopen("e:\\1.txt", "r", stdin);
#endif
	int t;
	scanf("%d%*c", &t);
	while (t--)
	{
		int a;
		scanf("%d %d%*c", &n, &m);
		for (int i = 0; i < n; i++)
			p[i].len = 0;
		memset(dp,-1,sizeof(dp));
		for (int i = 0; i < n; i++)
			scanf("%d%*c", &v[i]);
		for (int i = 0; i < n; i++)
			scanf("%d%*c", &w[i]);
		for (int i = 0; i < n; i++)
		{
			scanf("%d%*c", &p[i].len);
			for (int j = 0; j < p[i].len; j++)
			{
				scanf("%d%*c", &a);
				p[i].s[j] = a-1;
			}
		}
		printf("%d\n", dfs(0, m));
	}
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值