hdu 3810 Magina 队列优化的0-1背包t

本文探讨了一种使用深搜和队列模拟的方法来解决怪组升级问题,通过深搜找到组内所有怪,利用队列进行状态转移优化,实现最小花费升级。适用于大规模数据量场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意:

给你n个怪,这些怪,有的在一组内,有的不在一组内,要杀只能杀一个组内的怪,m为升级需要的金钱要求,问最少花费多少可以升级;

解题思路:

根据怪的联通方式,我们可以通过深搜搜出一个组内的所有的怪;
因为本题的数据量很大,所以普通的背包无论是在空间上还是时间上都是无法承受的,所以需要借助队列模拟;
这里向网上的大牛致敬,慢慢学习!
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<vector>
using namespace std;

#define inf 0x3f3f3f3f

struct Node{
	int cost,val;
	bool operator <(const Node &t)const{
	if(val!=t.val)
	return val<t.val;
	else
	return cost>t.cost;}
}node[55],s;
int n,m,cnt,ans;
vector<Node> q[55];
bool flag[55],map[55][55];
void dfs(int u)
{
	flag[u]=true;
	q[cnt].push_back(node[u]);
	for(int i=1;i<=n;i++)
	if(!flag[i]&&map[u][i])
	dfs(i);
}
void divid()
{
	cnt=0;
	memset(flag,false,sizeof(flag));
	for(int i=1;i<=n;i++)
	{
		if(!flag[i])
		{
			cnt++;
			q[cnt].clear();
			dfs(i);
		}
	}
}
void solve()
{
	ans=inf;
	priority_queue<Node> q1,q2;
	for(int i=1;i<=cnt;i++)
	{
		while(!q1.empty()) q1.pop();
		while(!q2.empty()) q2.pop();
		s.cost=s.val=0;
		q1.push(s);
		for(int j=0;j<q[i].size();j++)
		{
			while(!q1.empty())
			{
				s=q1.top();
				q1.pop();
				q2.push(s);
				s.cost+=q[i][j].cost;
				s.val+=q[i][j].val;
				if(s.val>=m)
				{
					ans=min(ans,s.cost);
					continue;
				}
				if(s.cost>=ans)
				continue;
				q2.push(s);
			}
			int mincost=inf;
			while(!q2.empty())
			{
				s=q2.top();
				q2.pop();
				if(s.cost<mincost)
				{
					q1.push(s);
					mincost=s.cost;
				}
			}
		}
	}
}
int main()
{
	int t;
	scanf("%d",&t);
	int cas=0;
	while(t--)
	{
		memset(map,false,sizeof(map));
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++)
		{
			int k,u;
			scanf("%d%d%d",&node[i].cost,&node[i].val,&k);
			while(k--)
			{
				scanf("%d",&u);
				map[i][u]=true;
			} 
		}
		divid();
		solve();
		printf("Case %d: ",++cas); 
		if(ans==inf)
		printf("Poor Magina, you can't save the world all the time!\n");
		else
		printf("%d\n",ans);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值