杭电1242-Rescue(bfs+优先队列||队列)

本文介绍了一个迷宫救援问题,通过两种不同的搜索算法实现——优先队列和普通队列结合特殊处理,来寻找从多个起点到达目标位置的最短路径。

Rescue

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 21824    Accepted Submission(s): 7776


Problem Description
Angel was caught by the MOLIGPY! He was put in prison by Moligpy. The prison is described as a N * M (N, M <= 200) matrix. There are WALLs, ROADs, and GUARDs in the prison.

Angel's friends want to save Angel. Their task is: approach Angel. We assume that "approach Angel" is to get to the position where Angel stays. When there's a guard in the grid, we must kill him (or her?) to move into the grid. We assume that we moving up, down, right, left takes us 1 unit time, and killing a guard takes 1 unit time, too. And we are strong enough to kill all the guards.

You have to calculate the minimal time to approach Angel. (We can move only UP, DOWN, LEFT and RIGHT, to the neighbor grid within bound, of course.)
 

Input
First line contains two integers stand for N and M.

Then N lines follows, every line has M characters. "." stands for road, "a" stands for Angel, and "r" stands for each of Angel's friend. 

Process to the end of the file.
 

Output
For each test case, your program should output a single integer, standing for the minimal time needed. If such a number does no exist, you should output a line containing "Poor ANGEL has to stay in the prison all his life." 
 

Sample Input
  
7 8 #.#####. #.a#..r. #..#x... ..#..#.# #...##.. .#...... ........
 

Sample Output
  
13
 

Author
CHEN, Xue
 

Source
 


题意:
    Angel被传说中神秘的邪恶的Moligpy人抓住了!他被关在一个迷宫中。迷宫的长、宽不超过200。 迷宫中有不可以越过的墙以及监狱的看守。
Angel的朋友带了一些救援队来到了迷宫中。他们的任务是:接近Angel。我们假设接近Angel就是到达Angel所在的位置。

假设移动需要1单位时间,杀死一个看守也需要1单位时间。到达一个格子以后,如果该格子有看守,则一定要杀死。交给你的任务是,最少要多少单位时间,才能到达Angel所在的地方?(只能向上、下、左、右4个方向移动)


这个题是个很好的搜索题,有一个坑就是一定要从天使开始搜索盆友,因为盆友的数量不定的,我们找的是离天使最近的那个盆友,但是以前不知道的时候从天使搜索竟然没错!数据太水了!

还有一点需要注意的是遇到警卫时时间要加二,如果还是用普通队列就要注意了,不处理的话求出来的一定不是最小时间,所以第一次遇到标记一下,第二次如果碰到标记,时间再加一,不再往4面搜索!但是用优先队列就不用管那么多了,遇到警卫就加二就行了

所以这个题两种解法:

1:优先队列

2:普通队列+特殊处理

下面给出代码!


1:优先队列


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
char map[210][210];
int vis[210][210],mov[4][2]={0,1,0,-1,1,0,-1,0};
int m,n;
struct node 
{
	int x,y,step;
	friend bool operator <(node x,node y)//重载布尔,定义优先队列按步数从小到大排序 
	{
		return x.step>y.step;
	}
}now,nex;
bool can(node x)//检查当前点是否可以走 
{
	if(x.x<0||x.y<0||x.x>m-1||x.y>n-1||vis[x.x][x.y]||map[x.x][x.y]=='#')
	return false;
	return true;
}
int bfs(int x,int y)
{
	priority_queue<node>q;
	now.x=x;
	now.y=y;
	now.step=0;
	q.push(now);//将起点入队列 
	while(!q.empty())
	{
		now=q.top();
		q.pop();
		if(map[now.x][now.y]=='r')//找到朋友就直接函数结束,找到结果 
		return now.step;
		for(int i=0;i<4;i++)
		{
			nex.x=now.x+mov[i][0];
			nex.y=now.y+mov[i][1];
			if(can(nex))
			{
				if(map[nex.x][nex.y]=='x')
				nex.step=now.step+2;//如果当前点可以走,且此点为警卫,步数加二 
				else
				nex.step=now.step+1;//如果当前点可以走,步数加一 
				vis[nex.x][nex.y]=1;
				q.push(nex);//将此点入队列 
			}
		}
	}
return -1;
}

int main()
{
	int i,j,sx,sy;
	while(scanf("%d%d",&m,&n)!=EOF)
	{
		for(i=0;i<m;i++)//输入图 
		{
			scanf("%s",map[i]);
			for(j=0;j<n;j++)
			{
				if(map[i][j]=='a')//记录搜索的起点 
				{
					sx=i;
					sy=j;
				}
			}
		}
		memset(vis,0,sizeof(vis));//标记清0 
		vis[sx][sy]=1;//起点也只能走一次,保证步数最少 
		int step = bfs(sx,sy);	
		if(step==-1)
		printf("Poor ANGEL has to stay in the prison all his life.\n");
		else
		printf("%d\n",step);
	}
	return 0;
 } 

2:普通队列+特殊处理



#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
char map[210][210];
int vis[210][210],mov[4][2]={1,0,-1,0,0,1,0,-1};
int m,n;
struct node
{
	int x,y,step,flag;
}now,nex;
bool can(node x)//检查当前点是否可以走 
{
	if(vis[x.x][x.y]||x.x<0||x.x>m-1||x.y<0||x.y>n-1||map[x.x][x.y]=='#')
	return false;
	return true;
}

int bfs(int a,int b)
{
	int i;
	queue<node> q;
	now.x=a;
	now.y=b;
	now.step=0;
	now.flag=0;
	q.push(now);//将起点入队列 
	while(!q.empty())
	{
		now=q.front();
		q.pop();
		if(now.flag)//第二次遇见警卫步数加一,重新标记flag=0 
		{
			now.step++;
			now.flag=0;
			q.push(now);//这里一定要重新放回队列里 
			continue;
		}
		if(map[now.x][now.y]=='r')//找到朋友就直接函数结束,找到结果 
		return now.step;
		for(i=0;i<4;i++)
		{
			nex.x=now.x+mov[i][0];
			nex.y=now.y+mov[i][1];
			if(can(nex)) 
			{
				nex.step=now.step+1;//如果当前点可以走,步数加一 
				
				if(map[nex.x][nex.y]=='x')
				nex.flag=1;
				else
				nex.flag=0;//第一次遇见警卫,标记走过,且flag标记为 1 
				
				vis[nex.x][nex.y]=1;
				q.push(nex);//将此点入队列 
			}
		}
	}
	return -1;//如果没找到就返回-1 
}
int main()
{
	int i,j,sx,sy;
	while(scanf("%d%d",&m,&n)!=EOF)
	{
		for(i=0;i<m;i++)//输入图 
		{
			scanf("%s",map[i]);
			for(j=0;j<n;j++)
			{
				if(map[i][j]=='a')//记录搜索的起点 
				{
					sx=i;
					sy=j;
				}
			}
		}
		memset(vis,0,sizeof(vis));//标记清0 
		vis[sx][sy]=1;//起点也只能走一次,保证步数最少 
		int step = bfs(sx,sy);	
		if(step==-1)
		printf("Poor ANGEL has to stay in the prison all his life.\n");
		else
		printf("%d\n",step);
	}
	return 0;
 } 




<think> 嗯,用户遇到了OpenStack卷状态显示为error的问题,看来挺着急的。从引用材料看,用户已经查阅了相关文档,但可能还需要更系统的解决方案。用户明确提出了"OpenStack volume状态为error的解决办法"这个需求,说明ta正在处理实际的运维问题。 用户引用的资料提供了几个关键点:CLI操作指南、状态重置命令、服务不可用报错、以及手动恢复的尝试。不过引用[4]提到的底层KVM手动操作风险较大,应该作为最后手段。用户可能更希望先通过OpenStack原生工具来解决。 考虑到用户身份应该是云平台运维人员,需要给出专业且安全的操作方案。ta可能已经尝试过基本命令但未奏效,所以需要提供更深入的排查思路。从引用[3]看,Keystone服务状态可能也是关联因素,这点要重点提醒。 解决方案需要分层设计:先简单后复杂。第一步肯定是检查基础服务状态,这个最容易忽略但往往能快速解决问题;然后是标准的状态重置操作;最后考虑复杂情况下的深度恢复。要特别注意强调重置状态的潜在风险,运维人员最怕的就是误操作导致数据丢失。 监控工具建议部分,用户可能没意识到Prometheus这类工具的价值,可以适当展开。对于虚拟机启动失败的特殊情况,引用[4]的经验值得参考但要谨慎表述,毕竟绕过OpenStack控制台属于非标准操作。 相关问题的设计要覆盖用户后续可能的需求:性能监控是运维刚需,状态转换关系能帮助理解错误本质,而数据备份更是核心关注点。这些延伸问题应该能帮用户建立更完整的知识体系。 </think> 以下是OpenStack卷状态为`error`的完整解决方案,结合引用内容及最佳实践整理: --- ### **一、核心解决步骤** 1. **检查基础服务状态** ```bash openstack volume service list # 检查Cinder服务状态 openstack network agent list # 检查Neutron服务 systemctl status openstack-cinder-* # 查看Cinder服务日志 ``` - 若返回`Keystone service temporarily unavailable`(引用[3]),需先修复认证服务: ```bash systemctl restart httpd keystone # 重启Keystone及Web服务 ``` 2. **重置卷状态** ```bash openstack volume reset-state --state available <volume_id> # 强制重置为可用状态(引用[1]) ``` **注意**:此操作仅修改数据库状态,不修复底层问题。 3. **尝试重新挂载** ```bash openstack server add volume <instance_name> <volume_id> --device /dev/vdb # 引用[2] ``` --- ### **二、深度修复方案** #### ▶ **场景1:底层存储故障** - **检查存储后端** ```bash cinder-volume.log | grep <volume_id> # 在Cinder节点查看日志 ``` - **手动恢复(高危操作)** 若日志显示QEMU/KVM异常(引用[4]): 1. 定位虚拟机配置文件:`/etc/libvirt/qemu/instance-*.xml` 2. 检查XML中卷的设备路径(如`/dev/vda`) 3. 通过`virsh edit <vm_id>` 手动解除错误卷绑定 #### ▶ **场景2:卷数据损坏** - **创建快照备份**(即使状态为error): ```bash openstack volume backup create <volume_id> --name rescue_backup ``` - **强制卸载残留挂载**: ```bash openstack volume set --state detached <volume_id> # 标记为已卸载 ``` --- ### **三、预防措施 1. **监控配置** ```bash openstack metric list --volume-id <volume_id> # 对接Prometheus监控I/O异常 ``` 2. **自动化恢复脚本** ```python # 示例:自动重置ERROR状态的卷 volumes = os_conn.block_storage.volumes(state='error') for vol in volumes: os_conn.block_storage.reset_volume_state(vol.id, 'available') ``` --- ### **关键注意事项** 1. **状态重置风险** ```mermaid graph LR A[卷状态ERROR] --> B{底层是否损坏?} B ----> C[重置状态可能导致数据丢失] B ----> D[重置后可安全使用] ``` 2. **服务依赖验证** 使用`openstack catalog list`确认所有服务Endpoint状态正常(避免引用[3]的Keystone故障)。 ---
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值