这道题目很麻烦,题意需要好好理解;
说一下我从这道题中学到的东西:
1》求最短路径时,一定要注意起点是哪一个,然后将起点入队,去走这个起点能够到达的下一个点,并入队。注意vis的使用
2》打印最短路径的时候,先用指针指向last,然后将这个点并入vector,而后将指针指向parent,继续vector,直到刚进去的那个节点是起点为止。
3》对于东西南北方向的计算,即:向左转向右转与方向的关系
4》如果输入的时候循环比较多的话,直接写到分开写到各个函数中,因为循环的break只能跳出一层循环,而函数的return可以跳出整个循环。
下面贴出代码:
//最短路径的关键在于为每一个位置(状态)找到它对应的父节点,从父节点可以找到它的上一个节点的位置信息 //如果是使用二维数组表示的u/v的这种类型的图,那非常的简单,就是在G[v]中找到v的上一个节点u,然后P[u]=v //但此题比较的复杂 //向左转就减一下,向右转就加一下。 #include<cstdio> #include<iostream> #include<string> #include<cstring> #include<queue> using namespace std; const int maxn = 10; //前两个是横纵坐标,第三个是进入这个点时的状态,第四个是转动的方向0直走,1右转,2左转 char G[maxn][maxn][4][3]; char vis[maxn][maxn][4]; int r_start,c_start,r_last,c_last; struct node { int row; int col; int dir; node(int a = 0,int b = 0,int dir = 0):row(a),col(b),dir(dir){} }; node parent[maxn][maxn][4]; node fir; node last; node start; string name; int dir_id(char dir) { if(dir == 'N') return 0; if(dir == 'E') return 1; if(dir == 'S') return 2; if(dir == 'W') return 3; } bool read_in() { memset(G,0,sizeof(G)); memset(vis,0,sizeof(vis)); cin>>name; if(name == "END") { return false; } char dir[5]; scanf("%d%d%s%d%d",&r_start,&c_start,dir,&r_last,&c_last); fir.col = c_start; fir.row = r_start; fir.dir = dir_id(dir[0]); //G[fir.row][fir.col][fir.dir][0] = 1;//直走是可以的 last.row = r_last; last.col = c_last; for(;;) { int r,c; scanf("%d",&r); if(r == 0) return true; scanf("%d",&c); for(;;) { scanf("%s",dir); //printf("%s\n",dir); if(dir[0] == '*') break; int len = strlen(dir); for(int i = 1;i < len;i++) { if(dir[i] == 'L') G[r][c][dir_id(dir[0])][2] = 1; else if(dir[i] == 'R') G[r][c][dir_id(dir[0])][1] = 1; else if(dir[i] == 'F') G[r][c][dir_id(dir[0])][0] = 1; } } } } node walk(node u,int turn) {//先转向,再走 int dir = u.dir; if(turn == 1) dir = (dir+1)%4; else if(turn == 2) dir = (dir+3)%4; if(dir==0)//面向北方 { node v(u.row-1,u.col,dir); return v; } if(dir==1)//面向东 { node v(u.row,u.col+1,dir); return v; } if(dir==2)//面向南 { node v(u.row+1,u.col,dir); return v; } if(dir==3)//面向西方 { node v(u.row,u.col-1,dir); return v; } } bool min_road() { queue<node>Q; start=walk(fir,0); parent[start.row][start.col][start.dir] = fir; vis[start.row][start.col][start.dir] = 1; Q.push(start); while(!Q.empty()) { node u = Q.front(); if(u.row == r_last && u.col == c_last) { last = u; return true; } Q.pop(); for(int i = 0;i<3;i++) { if(G[u.row][u.col][u.dir][i] == 1) { node v(walk(u,i)); if(!vis[v.row][v.col][v.dir]) { //printf("%d %d %d \n",v.row,v.col,v.dir); vis[v.row][v.col][v.dir] = 1; Q.push(v); parent[v.row][v.col][v.dir] = u; } } } } return false; } int main() { #ifdef local freopen("input.txt","r",stdin); freopen("out.txt","w",stdout); #endif while(read_in()) { cout<<name<<endl; if(min_road()) { vector<node>V; node u = last; for(;;)//将指针u进vector,判断u是不是起点,如果是,结束,如果不是将指针指向u的parent { V.push_back(u);//从最后开始 //printf("(%d %d)\n",u.row,u.col); if(u.row == start.row&&u.col == start.col&&u.dir==start.dir) break; u = parent[u.row][u.col][u.dir]; } V.push_back(fir); for(int i = V.size() - 1,j = 0;i >= 0;i--,j++) { if(j % 10 == 0) printf(" "); printf(" (%d,%d)",V[i].row,V[i].col); if(j % 10 == 9||!i) printf("\n"); } } else { printf(" No Solution Possible\n"); } } return 0; }