3094Escape from Enemy Territory——zoj

本文介绍了一种利用曼哈顿距离进行路径规划的方法。通过预处理敌营距离,使用BFS实现敌营距离的计算,并采用二分查找确定最大允许距离。最后,通过BFS寻找从起点到终点的最短路径。
思路
 
因为题中说了曼哈顿距离   所以在遍历中  每走一步就是一个距离   就缩小了难度(业界良心。。)
又说要找最小最大距离。。
对于每一个点的预处理最小距离就是一定了


然后再找到那个最小最大距离
然后再来找步数

两个一定要分开找  不然时间上要t


因为找标准要logn次   就要清理logn次哈希表  如果把标准与步数一起更新  就要清理2*logn次哈希表
如果分开找  就只用清理logn+1次哈希表   就不会超时了。。。。 


预处理

dis[i][j]表示i,j到最近的一个敌营的距离
如果暴力来  时间上o(n^3)1000*1000*1000t定了
就要机智一点,,
用bfs来实现   将所有敌营加到队列里   如果当前点的距离算过了
就continue   因为bfs先到的一定是最短距离
这样就只有o(n^2)
ok了。

找最小最大距离
这个肯定二分找了。。。不然呢、
在预处理的时候   记录下所有距离中的最大值  
最小值就不管了  一定是0 (没想到军爷(不用在意这些细节)们居然可以直接穿过敌营  七进七出还战术撤退啊。。。O(∩_∩)O~)
具体步骤见后代码


找到最小步数
裸bfs无压力
找到了二分出来的标准
就用标准来进行真实意义上的bfs
找到最短路
判断如果当前的距离在标准允许内就push  不然就continue





#include<iostream>/*预处理出i,j点到敌营 的最小值  先二分bfs找到一个离敌营最大值   在用标准bfs出最小步数*/
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int dx[5]={0,-1,1,0,0};
const int dy[5]={0,0,0,-1,1};
int hash[1000+10][1000+10];//最小step
int ste[1000+10][1000+10];//最少step 
int maxn;
int l,r,mid;
struct edge
{
	int v,u;
	int step;
	int mins;
}cs,ns,ans,res;
queue<edge>q;
int dis[1000+10][1000+10];
int t;
int n,x,y;
int stx,sty,enx,eny;
void readdata()
{
	maxn=-1;
	while(!q.empty())
	q.pop();
	cs.step=0;
	cs.mins=0;
	cs.u=0;
	cs.v=0;
	ans=cs;
	memset(dis,0,sizeof(dis));
	memset(ste,0,sizeof(ste));
	scanf("%d%d%d",&n,&x,&y);
	scanf("%d%d%d%d",&stx,&sty,&enx,&eny);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&cs.u,&cs.v);
		dis[cs.u][cs.v]=-1;
		q.push(cs);
	}
}
void ready()
{
	while(!q.empty())
	{
		cs=q.front();
		q.pop();
		for(int i=1;i<=4;i++)
		{
			ns=cs;
			ns.u+=dx[i];
			ns.v+=dy[i];
			ns.step++;
			if(ns.u<=x-1&&ns.u>=0)
			if(ns.v<=y-1&&ns.v>=0)
			if(!dis[ns.u][ns.v])
			{
				dis[ns.u][ns.v]=ns.step;
				maxn=max(maxn,dis[ns.u][ns.v]);
				q.push(ns);
			}
		}
	}
	while(!q.empty())
	q.pop();
}
bool bfs_for_bz(int bz)
{
	memset(hash,0,sizeof(hash)) ;
	cs.u=stx;
	cs.v=sty;
	cs.mins=dis[stx][sty];
	q.push(cs);
	while(!q.empty())
	{
		cs=q.front();
		q.pop();
		for(int i=1;i<=4;i++)
		{
			ns=cs;
			ns.u+=dx[i];
			ns.v+=dy[i];			
			if(!(ns.u<=x-1&&ns.u>=0))
			continue;
			if(!(ns.v<=y-1&&ns.v>=0))
			continue;
			ns.mins=min(ns.mins,dis[ns.u][ns.v]);
			if(dis[ns.u][ns.v]==-1)
			ns.mins=0;
			if(ns.mins<bz)
			continue;
			if(hash[ns.u][ns.v]==0)
			{
				if(ns.u==enx&&ns.v==eny)
				{					
					while(!q.empty())
					q.pop();
					return true;
				}
				hash[ns.u][ns.v]=1;				
				q.push(ns);
			}
		}
	}
	return false;
}
int bfs_for_step(int bz)
{
	cs.u=stx;
	cs.v=sty;
	cs.step=0;
	q.push(cs);
	while(!q.empty())
	{
		cs=q.front();
		q.pop();
		for(int i=1;i<=4;i++)
		{
			ns=cs;
			ns.u+=dx[i];
			ns.v+=dy[i];
			ns.step++;
			if(!(ns.u<=x-1&&ns.u>=0))
			continue;
			if(!(ns.v<=y-1&&ns.v>=0))
			continue;
			if(dis[ns.u][ns.v]==-1)
			dis[ns.u][ns.v]=0;
			if(dis[ns.u][ns.v]<bz)
			continue;
			if(ste[ns.u][ns.v]==0)
			{
				if(ns.u==enx&&ns.v==eny)
				{					
					while(!q.empty())
					q.pop();
					return ns.step;
				}
				ste[ns.u][ns.v]=1;
				q.push(ns);
			}
		}
	}
}
int main()
{
	scanf("%d",&t);
	for(int tt=1;tt<=t;tt++)
	{
		readdata();
		ready();
		if(enx==stx&&eny==sty)
		{
			printf("%d %d\n",dis[enx][eny],0);
			continue;
		}
		r=maxn;
		l=0;
		int cs=0;
		while(l<=r) 
		{
			mid=(l+r)/2; 
			if(bfs_for_bz(mid))
			l=mid+1;
			else r=mid-1;
		}
		if(mid==l)
		{
			printf("%d %d\n",mid-1,bfs_for_step(mid-1));	
			continue;
		}
		else
		{
			printf("%d %d\n",mid,bfs_for_step(mid));	
			continue;			
		}
	}
}


<think>好的,用户的问题是关于如何在C++中遍历enemy_list来访问每个Enemy对象。首先,我需要回忆一下C++中常见的迭代方法,比如传统的for循环、基于范围的for循环,还有可能的迭代器方法。用户提供的引用内容提到了Unreal Engine中的Actor迭代器,这可能涉及到UE特定的实现,所以需要结合这些引用进行分析。 首先,用户提到的enemy_list可能是一个存储Enemy对象的容器。在Unreal Engine中,Enemy可能继承自AActor,所以引用[2]提到Actor迭代器只处理从AActor派生的对象,这可能适用。引用[3]指出创建Actor迭代器需要一个UWorld实例的指针,而像APlayerController这样的类提供了GetWorld方法,这可能帮助用户获取正确的World上下文。 接下来,用户可能需要两种方法:一种是使用UE的TActorIterator,另一种是标准的C++容器遍历。比如,如果enemy_list是TArray<AEnemy*>,那么基于范围的for循环会更简洁。但如果enemy_list是分散在World中的Actors,可能需要使用TActorIterator来遍历所有Enemy实例。 另外,引用[4]提到了UPROPERTY的重要性,确保对象不被垃圾回收。所以在存储Enemy指针时,必须使用UPROPERTY()修饰,避免出现悬挂指针的问题。 然后,需要考虑用户可能的错误点,比如忘记检查迭代器返回的指针是否有效,或者没有正确获取World上下文。此外,性能方面,频繁遍历可能需要优化,比如使用事件驱动而不是每帧遍历,但这可能超出当前问题的范围。 最后,生成相关问题需要涵盖UE迭代器的其他操作、性能优化、垃圾回收的影响等,确保用户全面了解相关知识点。</think>在虚幻引擎C++中遍历`enemy_list`访问每个Enemy对象,可以采用以下两种典型方法: ### 方法一:使用TActorIterator(推荐) ```cpp #include "EngineUtils.h" void AMyClass::IterateEnemies() { UWorld* World = GetWorld(); // 通过Actor获取World实例[^3] // 使用模板类TActorIterator遍历所有Enemy对象 for (TActorIterator<AEnemy> It(World); It; ++It) { AEnemy* Enemy = *It; if (Enemy && Enemy->IsValidLowLevel()) // 有效性校验 { // 执行操作,例如 Enemy->TakeDamage(); } } } ``` - 特点:自动过滤非Enemy对象,仅遍历当前World中的有效Actor[^2] - 注意:需要确保`AEnemy`继承自`AActor` ### 方法二:手动遍历TArray容器 ```cpp // 假设enemy_list是TArray<AEnemy*>类型且已初始化 void AMyClass::ManualIteration() { for (AEnemy* Enemy : enemy_list) { if (IsValid(Enemy)) // 必须进行有效性检查[^4] { // 执行操作 } } } ``` - 注意:必须使用`UPROPERTY()`标记容器以防止垃圾回收 ```cpp UPROPERTY() TArray<AEnemy*> enemy_list; ``` ### 性能优化提示 1. 避免每帧遍历:建议使用事件驱动模式而非持续轮询[^5] 2. 空间局部性:将Enemy对象按空间分区存储 3. 延迟处理:使用异步任务处理非紧急操作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值