百练4980 拯救行动[BFS]

公主被恶人抓走,被关押在牢房的某个地方。牢房用N*M 
(N, M <= 200)的矩阵来表示。矩阵中的每项可以代表道路(@)
、墙壁(#)、和守卫(x)。
英勇的骑士(r)决定孤身一人去拯救公主(a)。我们假设
拯救成功的表示是‚骑士到达了公主所在的位置‛。由于在通往
公主所在位置的道路中可能遇到守卫,骑士一旦遇到守卫,必须
杀死守卫才能继续前进。
现假设骑士可以向上、下、左、右四个方向移动,每移动一
个位置需要1个单位时间,杀死一个守卫需要花费额外的1个单位
时间。同时假设骑士足够强壮,有能力杀死所有的守卫。
给定牢房矩阵,公主、骑士和守卫在矩阵中的位置,请你计

算拯救行动成功需要花费最短时间。

这道题目是典型的宽搜问题,算法本身没有难度,不过真是把我写伤了,总是因为逻辑没想周全犯各种错误,关键是还找不出错误,总感觉自己写的没错,真是= =。不过还是代码写的少了,还得再多练习。

<pre name="code" class="cpp">#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<queue>
using namespace std; 
int N,M;
int n,m;
char map[210][210];
struct position{
	int x;
	int y;
	int time;
	position(int xx,int yy,int t){
		x=xx;
		y=yy;
		time=t;
	}
};
int dx[4]={-1,0,1,0};
int dy[4]={0,-1,0,1};
queue<position> q;
void bfs()
{
	while(!q.empty()){
		position p=q.front();
		q.pop();
		if(p.x==n && p.y==m){
			//这也是容易犯错的地方,如果思维不够缜密的话,因为你在没找完一个点后都给这个点做了标记,所以导致最终公主的那个点已经不是a了
			//所以在判断是否找到时不能写成if(map[p.x][p.y]=='a')而要用位置坐标点判断 
			printf("%d\n",p.time);
			return;
		}
			for(int i=0;i<4;i++){
				int a=p.x+dx[i];
				int b=p.y+dy[i];
				if(a>=0 && a<N && b>=0 && b<M && map[a][b]!='#'){
					if(map[a][b]=='@'){
						q.push(position(a,b,p.time+1));
						//printf("a=%d b=%d p.time=%d\n",a,b,p.time+1);
					}
						
					if(map[a][b]=='x'){
						q.push(position(a,b,p.time+2));
						//printf("a=%d b=%d p.time=%d\n",a,b,p.time+2);
					}
					//就这步当时忘了写,忘了找到了公主也要将公主push进去,否则怎么得到最终的q.front()呢?所以导致不能输出最终答案
					//真是思维不够缜密啊 
					if(map[a][b]=='a'){
						q.push(position(a,b,p.time+1));
					}	
					map[a][b]='#';//这样标记之后最终公主的那个点也是#而不是a ,判断时要注意 
				}
			}
	}
}
int main()
{
	scanf("%d%d",&N,&M);
	for(int i=0;i<N;i++)
		scanf("%s",map[i]);
	for(int i=0;i<N;i++)
		for(int j=0;j<M;j++){
			if(map[i][j]=='r'){
				q.push(position(i,j,0));
				map[i][j]='#';
			}
			if(map[i][j]=='a'){
				 n=i;
				 m=j;
				 //printf("n=%d m=%d\n",n,m);
			}
		}
		bfs();
		return 0;
}
/*
7 8
#@#####@
#@a#@@r@
#@@#x@@@
@@#@@#@#
#@@@##@@
@#@@@@@@
@@@@@@@@
*/


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值