UVA 816 Abbott's Revenge 紫书

紫书的这道题, 作者说是很重要。

但看着题解好长, 加上那段时间有别的事, 磨了几天没有动手。

最后,这道题我打了五遍以上 ,有两次被BUG卡了,找了很久才找到。

思路紫书上有,就缺少输入和边界判断两个部分。不是因为紫书,应该也不会找到这个WF题吧,所以其余思路就不说了。 一些注释在代码中有。

代码:

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <cstring>
  4 #include <vector>
  5 #include <queue>
  6 using namespace std;
  7 
  8 const int MAXN = 10;
  9 const char* dirs = "NESW";
 10 const char* turns = "FLR";
 11 int dir_id(char c) {return strchr(dirs, c)-dirs;}
 12 int turn_id(char c) {return strchr(turns, c)-turns;}
 13 const int dr[] = {-1, 0, 1, 0};
 14 const int dc[] = {0, 1, 0, -1};
 15 
 16 struct Node
 17 {
 18     int r;
 19     int c;
 20     int dir;
 21     Node(int rr=0, int cc=0, int d=0):r(rr), c(cc), dir(d) {}
 22 };
 23 
 24 int has_edge[MAXN][MAXN][4][3];
 25 int d[MAXN][MAXN][4];//判断是否遍历过 
 26 Node p[MAXN][MAXN][4];
 27 int r0, c0, r1, c1, r2, c2, dir;
 28 
 29 
 30 Node walk(const Node& u, int turn)
 31 {
 32     int dir=u.dir;
 33     if(turn==1)   dir = (dir+3)%4;//逆时针
 34     if(turn==2)      dir = (dir+1)%4;//顺时针
 35     return Node(u.r+dr[dir], u.c+dc[dir], dir); 
 36 }
 37 
 38 bool inside(int r, int c)//判断是否出界 
 39 {
 40     return r>=1 && r<=9 && c>=1 && c<=9;
 41 }
 42 
 43 bool read_case()
 44 {
 45     char s1[99], s2[99];//储存名字, 储存方向
 46     if(scanf("%s%d%d%s%d%d", s1, &r0, &c0, s2, &r2, &c2)!=6)   return false;//输入不正确
 47     printf("%s\n", s1);
 48     memset(has_edge, 0, sizeof(has_edge));
 49     
 50     dir = dir_id(s2[0]);
 51     r1 = r0+dr[dir];
 52     c1 = c0+dc[dir];
 53     
 54     for(; ;)
 55     {
 56         int r, c;
 57         scanf("%d", &r);
 58         if(r==0)   break;
 59         scanf("%d", &c);
 60         while(scanf("%s", s2)==1 && s2[0]!='*')
 61         {
 62             int len=strlen(s2);
 63             for(int i=1; i<len; i++)
 64                 has_edge[r][c][dir_id(s2[0])][turn_id(s2[i])]=1;//将可走的地方赋1 
 65         }
 66     }    
 67     return true;     
 68 }
 69 
 70 void print_ans(Node u)
 71 {
 72     vector<Node> nodes;
 73     for(; ;)//输入 
 74     {
 75         nodes.push_back(u);
 76         if(d[u.r][u.c][u.dir]==0)   break;
 77         u = p[u.r][u.c][u.dir];
 78     }
 79     nodes.push_back(Node(r0, c0, dir));//起点存入
 80     
 81     int cnt=0;
 82     for(int i=nodes.size()-1; i>=0; i--)//倒着输出 
 83     {
 84 //        cout<<"#i"<<endl;
 85         if(cnt%10 == 0)   printf(" ");
 86         printf(" (%d,%d)", nodes[i].r, nodes[i].c);
 87         if(++cnt % 10 ==0)   printf("\n");
 88     }
 89     if(nodes.size()%10!=0)   printf("\n"); 
 90 }
 91 
 92 void solve()
 93 {
 94     queue<Node> q;
 95     memset(d, -1, sizeof(d));
 96     Node u(r1, c1, dir);
 97     d[u.r][u.c][u.dir]=0;
 98     q.push(u);
 99     while(!q.empty())
100     {
101         Node now = q.front();   q.pop();
102         if(now.r==r2 && now.c==c2)
103         {
104             print_ans(now);
105             return;
106         }
107         
108         for(int i=0; i<3; i++)
109         {
110             Node v = walk(now, i);
111             if(has_edge[now.r][now.c][now.dir][i] && d[v.r][v.c][v.dir]<0 && inside(v.r, v.c))
112             {
113                 d[v.r][v.c][v.dir] = d[now.r][now.c][now.dir]+1;
114                 p[v.r][v.c][v.dir] = now;
115                 q.push(v);
116             }
117         }    
118     }
119     printf("  No Solution Possible\n");
120 }
121 
122 int main()
123 {
124     while(read_case())
125         solve();
126     
127     return 0;
128 }

毕竟完成了一题WF题,虽然开始的思路不是自己想的,但还是感觉有一丝丝成就感,哈哈。

猜你喜欢

转载自www.cnblogs.com/watsoncao/p/10737674.html