uva816 Abbott的复仇

这道题的和普通bfs的区别在于多增加一个参数,朝向。我们只需把朝向也作为一个参数加入结构体,直接进行三元bfs即可。在具体进行bfs的过程中
我们可以用一些mod运算配合数组解决转向问题。
#include<bits/stdc++.h> using namespace std; typedef long long ll; struct node { int x,y,dir;// 站在(r,c),面朝方向dir(0~3分别表示N, E, S, W) node(int x=0, int y=0, int dir=0):x(x),y(y),dir(dir) {} }father[10][10][4];//father[r][c][dir]表示了(r,c,dir)在BFS树中的父节点,记录三元组 int d[10][10][4];//用来累加起点到终点的距离 int has_edge[10][10][10][10];//中has_edge[r][c][dir][turn]表示当前状态是(r, c, dir),是否可以沿着转弯方向turn行走 const char* dirs="NESW";// 顺时针旋转 const char* turns="FLR";//直行左转右转 int dir_id(char c){return strchr(dirs,c)-dirs;}//返回c在dirs的位置 int turn_id(char c){return strchr(turns,c)-turns;}//同理 int x_0,x_1,y_0,y_1,x2,y2,dir;//起点终点和起点方向 const int dx[] = {-1, 0, 1, 0}; const int dy[] = {0, 1, 0, -1};//右上左下 node walk(const node &u,int turn) { int dir=u.dir; if(turn==1)dir=(dir+3)%4;//顺时针,表示左转 if(turn==2)dir=(dir+1)%4;//逆时针,表示右转 return node(u.x+dx[dir],u.y+dy[dir],dir); } //判断坐标是否出界 bool check(int x,int y) { return x>=1&&x<=9&&y>=1&&y<=9; } bool read_case() { char s1[100],s2[100]; //s1是指当前的流程,x0表示起始行,y0表示起始列,s2起始方向,x2表示目标行,y2表示目标列 if(scanf("%s%d%d%s%d%d",s1,&x_0,&y_0,s2,&x2,&y2)!=6)return false; printf("%s\n",s1); dir=dir_id(s2[0]);//方向在字符串dirs中的位置 x_1=x_0+dx[dir];//第一步之后的行坐标 y_1=y_0+dy[dir];//第二步之后的列坐标 memset(has_edge,0,sizeof has_edge); for(;;) { int x,y; scanf("%d",&x); if(x==0)break; scanf("%d",&y); while(scanf("%s",s1)==1&&s1[0]!='*')//三个方向分开输入 for(int i=1;i<=strlen(s1);++i) has_edge[x][y][dir_id(s1[0])][turn_id(s1[i])]=1; } return true; } void print_ans(node u) { // 从目标结点逆序追溯到初始结点 vector<node>nodes; for(;;) { nodes.push_back(u);//倒着建立答案顺序 if(d[u.x][u.y][u.dir]==0)break;//说明找到了终点 u=father[u.x][u.y][u.dir]; } nodes.push_back(node(x_0,y_0,dir));//加入起点 int cnt=0; for(int i=nodes.size()-1;i>=0;i--)//按输出格式输出 { if(cnt%10==0)printf(" "); printf(" (%d,%d)", nodes[i].x, nodes[i].y); if((++cnt)%10==0) printf("\n"); } if(nodes.size()%10!=0)printf("\n"); } void solve() { queue<node>q; memset(d,-1,sizeof d); node u(x_1,y_1,dir);//走了一步之后的坐标 d[u.x][u.y][u.dir]=0; q.push(u); while(!q.empty()) { node u=q.front(); q.pop(); if(u.x==x2&&u.y==y2){print_ans(u);return ;}//终点出口 for(int i=0;i<3;i++) {//一共有三种可能走法 node v=walk(u,i); //v是u坐标行走一步之后的坐标,走到终点没有初始化,has_edge值为0,不进入循环 if(has_edge[u.x][u.y][u.dir][i]&&check(v.x, v.y)&&d[v.x][v.y][v.dir]<0)//能走且不出界且没走过 { d[v.x][v.y][v.dir] = d[u.x][u.y][u.dir] +1;//累加1,最后得出起点到终点的距离 father[v.x][v.y][v.dir]=u;//表示v的父节点是u q.push(v); } } } printf(" No Solution Possible\n"); } int main() { while(read_case()) solve(); return 0; }

浙公网安备 33010602011771号