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