[UVA816] Abbott's Revenge BFS

一个细节处理很麻烦的题, 首先是答案输出需要注意: 除了每个迷宫名字输出不要缩进外,每行都要缩进两格,而且路径输出时,每行最多输出10个节点.

再一个就是虽然答案可以递归地打印出来,但可能会因为最短路很长而出错.所以改用vector保存路径.

深夜做本题时,出了不少奇妙的bug,比如 bad alloc, 简直神了. 后来发现是因为假如一步就可以到达终点,那么压进vector的那个点是没有前驱的,查这个错查了很久.说明还是考虑不周密.

另外,就是本题中变量名超级多,所以要遵循一些命名规则,至少保证自己看得懂.代码如下:

#include<bits/stdc++.h>
#define rep(i,a,n) for(i=a;i<=n;i++)
#define per(i,a,n) for(i=a;i>=n;i--)
#define maxn 10
using namespace std;
struct node{
	int dir,r,c;
	node(int dir=0, int r=0, int c=0): dir(dir),r(r), c(c) {}
};

const char* drt="NESW";
const char* trn = "FLR";
int hav_ege[maxn][maxn][5][4];//row,column,direction,turn, 0 symbolize no edge, 1 symbolize have edge
int vis[maxn][maxn][5];
int dr[5]={-1,0,1,0};
int dc[5]={0,1,0,-1};
node ans[maxn][maxn][5];
int r0,c0,re,ce;//starting point, starting direction, end point
char d0[100];
void prt_ans(node u);
int get_drt(char d);
int get_trn(char t);
bool read_maze();
node wlk(const node& u, int t);
bool isd(node u);
void slove();


int get_drt(char d){
	return strchr(drt,d)-drt;
}
int get_trn(char t){
	return strchr(trn,t)-trn;
}
bool read_maze(){
	char s[100];
	if(scanf("%s%d%d%s%d%d",s,&r0,&c0,d0,&re,&ce)!=6) return false;
	printf("%s\n",s);
	memset(hav_ege,0,sizeof(hav_ege));
	int r,c;
	for(;;){
		scanf("%d",&r);
		if(r==0) break;
		scanf("%d",&c);
		while(scanf("%s",s)==1&&s[0]!='*'){
			int d=get_drt(s[0]);
			int len=strlen(s);
			int i;
			rep(i,1,len-1){
				int t=get_trn(s[i]);
				hav_ege[r][c][d][t]=1;
			}
		}
	}
	return true;
}
node wlk(const node& u, int t){
	int d=u.dir;
	if(t==1) d=(d+3)%4;
	if(t==2) d=(d+1)%4;
	return node(d,u.r+dr[d],u.c+dc[d]);
}
bool isd(node u){
	if(u.r<=9&&u.r>=1&&u.c>=1&&u.c<=9) return true;
	else return false;
}
void slove(){
	queue<node> q;
	memset(vis,-1,sizeof(vis));
	int d=get_drt(d0[0]);
	int r1=r0+dr[d];
	int c1=c0+dc[d];
	node v(d,r1,c1);
	vis[v.r][v.c][v.dir]=0;
	q.push(v);
	while(!q.empty()){
		node u=q.front();q.pop();
		if(u.r==re&&u.c==ce){
			prt_ans(u);return ;
		}
		int i;
		rep(i,0,2){
			node nxt=wlk(u,i);
			if(hav_ege[u.r][u.c][u.dir][i]&&isd(nxt)&&vis[nxt.r][nxt.c][nxt.dir]<0){
				q.push(nxt);
				vis[nxt.r][nxt.c][nxt.dir]=vis[u.r][u.c][u.dir]+1;
				ans[nxt.r][nxt.c][nxt.dir]=u;
			}
		}
	}
	printf("  No Solution Possible\n");
}
void prt_ans(node u){
	vector<node> asw;
	while(vis[u.r][u.c][u.dir]!=0){
		asw.push_back(u);
		u=ans[u.r][u.c][u.dir];
	}
	asw.push_back(u);
	asw.push_back(node(get_drt(d0[0]),r0,c0));
	int cnt=0;
	int len=asw.size()-1;
	int i;
	per(i,len,0){
		if(cnt%10==0) printf(" ");
		printf(" (%d,%d)",asw[i].r,asw[i].c);
		if(++cnt%10==0)printf("\n");
	}
	if((len+1)%10!=0) printf("\n");
}
int main(){
	while(read_maze()){
		slove();
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值