Abbott的复仇(Abbott's Revenge, ACM/ICPC World Finals 2000, UVa 816)<经典BFS>

本文深入探讨了一种迷宫寻路算法的具体实现过程,详细介绍了如何利用BFS(宽度优先搜索)解决迷宫寻路问题,并展示了具体的C++代码实现细节。通过对关键函数如turn_id和dir_id的理解及应用,读者可以掌握如何将字符方向转换为数字表示,以及如何通过这些转换高效地在迷宫中找到路径。

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

the reason of failure:1、各种坑坑洼洼的修改。2、在第一个dir上,已经将其转换为数字了,就不该在计算时又转换一次

how to solve:对着正确的一遍又一遍找错误,最后自己不看答案完整写出

question:

where is difficult:

key point:1、BFS的使用方法。2、strchr的使用

(const char * dirs = "NESW";   //N开始顺时针 
const char * turns = "FLR"; 

int turn_id(char b){return strchr(turns,b)-turns;}
 int dir_id(char b){return strchr(dirs,b)-dirs;}) 根据输入的字母得转换成一个数字

3、在print()中每次u=p[u.r][u.c][u.dir];得到的值都不同,是由于赋值一次后指针的位置便改变了,

跟pos=a.begin();然后用pos插入到链表是一样的道理

my thinking: 题要多做才能熟练

#include<stdio.h>
#include <vector>
#include <queue>
#include<string.h>
#include <iostream>
using namespace std;

 int r0,r1,r2,c0,c1,c2,a,b,dir;
 char str1[10],str2[10],str3[10],str4[10];
 const char * dirs = "NESW";   //N开始顺时针 
const char * turns = "FLR";  
 int walked[10][10][10];    
int dr[]={-1,0,1,0};
int dc[]={0,1,0,-1};
 struct Node{ 
  int r,c,dir;
 Node(int rr,int cc,int dirr){     //这不是一个函数,这是一个变量赋值 
 r=rr;
 c=cc;
 dir=dirr;
 }
 Node(){};
 }; 
 Node p[10][10][4];
 queue<Node>q;
 int has_edge[10][10][10][10]; 
 int turn_id(char b){return strchr(turns,b)-turns;}
 int dir_id(char b){return strchr(dirs,b)-dirs;}
 void print(Node u){
	vector<Node>nodes;
	while(1){
		nodes.push_back(u);
		if(walked[u.r][u.c][u.dir]==0) break;
		u=p[u.r][u.c][u.dir];
		//printf("%d%d%d  ",u.r,u.c,u.dir); 
		//因为储存在地址里,每取一次地址就向前一步 
	}
	nodes.push_back(Node(r0,c0,dir));
	int cnt=0;
	for(int i=nodes.size();i>=0;i--){
		cout << "(" << nodes[i].r << "," << nodes[i].c << ")";
	}
} 
Node walk(Node &u,int c){
int dir1=u.dir;
if(c==1)dir1=(dir1+3)%4;
if(c==2)dir1=(dir1+1)%4;
return Node(u.r+dr[dir1],u.c+dc[dir1],dir1);
}
 void solve(){
Node u(r1,c1,dir);   //定义一个u,其为自定义结构体,赋初值r1,c1,dir 
Node v;
memset(walked,-1,sizeof(walked));
walked[u.r][u.c][u.dir]=0;
q.push(u);
while(!q.empty()){
    u=q.front();
q.pop();
r1=u.r;
c1=u.c;
if(r1==r2&&c1==c2) return print(u);
for(int j=0;j<3;j++){
v=walk(u,j);
if(walked[v.r][v.c][v.dir]<0&&has_edge[u.r][u.c][u.dir][j]){
walked[v.r][v.c][v.dir]=1;
p[v.r][v.c][v.dir]=u;
q.push(v);
}
}
}
}
int read(){
while(scanf("%s%d%d%s%d%d",str1,&r0,&c0,str2,&r2,&c2)!=6)return false;
printf("%s\n",str1); 
dir=dir_id(str2[0]); //输入包括SAMPLE这个字符,然后是起始点与终点  
r1=r0+dr[dir];  //根据方向,走第一步,上面已经将dir的值给转换为数字了,这里就不用再转换了 
c1=c0+dc[dir];
while(scanf("%d",&a)==1&&a){    //输入数字,判断是否为0来判断是否还有点的信息没给出 
scanf("%d",&b);
while(scanf("%s",str3)&&str3[0]!='*'){ //通过*判断是否输入的字符结束 
int length=strlen(str3);
for(int i=1;i<length;i++){        //由于第一个字符是方向,所以只用输入后面的几个该方向能走的左右进去 
has_edge[a][b][dir_id(str3[0])][turn_id(str3[i])]=1;
}
}
  }
 return true;
}
int main(){
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
while(read()){
	solve();	
}
return 0;
} 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值