Uva1601-the Morning after Halloween (unidirectional + bidirectional BFS)

Source: Internet
Author: User

Give a maximum 16x16 maze map and up to 3 ghost start and target locations, so that at least a few rounds of movement can make three ghost reach the target location. Each round of movement, each ghost can take one step, can also stay in place, it is important to note that any two ghost can not be in the same position, so also can not appear any two ghost to wear, that is, the original is AB, after the move is BA. Each maze diagram ' # ' denotes a wall, ' ' denotes a clearing, a lowercase letter indicates the starting position of ghost, and an uppercase letter indicates the target location for ghost, such as ' a ' should go to ' a '. Ensure that there is a ' # ' in any 2x2 space.

It looks like a maze of numbers, BFS. If you do so decisively will time out, because in each state can walk too much, 3 ghost words, each has 5 directions to go, 3 add up to remove the place still there are 124 kinds of walk, and the least number of steps calculated is not necessarily less, the third group of steps as many as 77 steps, space Open, Time spent much. So this problem must be optimized.

The first is to try to avoid the illegal way to search. This time is a detail in the title, to ensure that there is a ' # ' in any 2x2 space, that is, there are quite a few of the 124 steps that can be left illegal. Every time it's pressed into the queue and then it's not legal to eliminate it, it wastes a lot of time, so that's the optimized entry. The method used here is to convert the maze diagram into a diagram, with the adjacency table to save, so that when the search only walk can go to the point, save the Walk ' # ' to exclude the time.

Secondly, it can also improve the efficiency in the judgement of the weight. At first I used the structure to store ghost's position, but also dynamically adjust the number of ghost, and then find a way to use the hash, the result of a very slow and extremely inefficient example can not run out. In fact, according to any 2x2 have ' # ' This detail, you can roughly estimate the entire maze can walk in the open space not more than 200, 3 ghost words built a three-dimensional array, 200x200x200=8000000, completely open. In addition to considering the number of ghost problems, the idea here is to put the unwanted ghost into an isolated point, and then make it the same starting position and target location, so as to avoid the need to dynamically adjust the circumstances of the trouble.

By the top two, you can already complete the problem of a.

Well, then the idea is to get "input → build →bfs". The idea is very simple, write code poor is really a problem, all kinds of cards collapse all kinds of wrong, alas ...

In fact, this is only part of the optimization, if you want to improve efficiency, you need to use two-way BFS. But considering the level of the slag ... Go from One Direction to the next, and then start changing the two directions.

#include <cstdio> #include <cstring> #include <cctype> #include <list> #include <algorithm >using namespace Std;int W, H, N;char pic[20][20]; input int num[20][20]; position in input → number of nodes in Figure int vis[200][200][200]; Tagged array int connect[200][200]; adjacency table int all; Number of nodes in the graph int que[10000000][4]; BFS queue int goal[4];    Target State of inline void BFS () {//Initialize memset (VIS, 0, sizeof (VIS));    int fro = 0, rear = 1;    VIS[QUE[0][1]][QUE[0][2]][QUE[0][3]] = true; while (fro < rear) {int &step = que[fro][0], &a = que[fro][1], &b = que[fro][2], &c = que[fro][3        ];        if (a = = Goal[1] && b = = Goal[2] && c = = Goal[3]) {goal[0] = step; return;}            for (int i = 0, T1; I <= connect[a][0]; ++i) {T1 = (i = = 0? a:connect[a][i]);                for (int j = 0, T2; j <= Connect[b][0]; ++j) {t2 = (j = = 0? b:connect[b][j]); for (int k = 0, T3; k <= connect[c][0]; ++k) {t3 = (K = = 0?                    C:connect[c][k]); Judge conflict-----if (T1 && t2 && t1 = = t2) | | (T1 && t3 && t1 = = T3) | | (T2 && t3 && t2 = = T3)) Continue Cannot overlap if (T1 && t2 && T1 = = b && t2 = = a) continue; T1,T2 cannot wear if (T1 && t3 && t1 = = c && T3 = a) continue; T1,T3 cannot wear if (T2 && t3 && t2 = = c && T3 = b) Continue; T2,T3 cannot be worn//----------if (!vis[t1][t2][t3]) {VIS[T1][T2]                        [T3] = 1;                        QUE[REAR][0] = step + 1, que[rear][1] = t1, que[rear][2] = t2, que[rear][3] = t3;                    ++rear;    }}}} ++fro;    }}int Main () {int _t = 0;    while (scanf ("%d%d%d", &w, &h, &n) && w && h && N) {//Read input-----    Gets (pic[0]);    for (int i = 0; I! = h; ++i) gets (Pic[i]);        ----------//Build Diagram-----//Initialize memset (connect, 0, sizeof (connect)) based on input;        all = 0; Get the number for (int i = 0; I! = h; ++i) for (int j = 0; J! = W; ++j) {if (pic[i][j]! = ' # ') num[i][j] = ++all            ;        else num[i][j] = 0; }//build diagram for (int i = 0; I! = h; ++i) for (int j = 0; J! = W; ++j) if (Num[i][j]) {int &pos = n            UM[I][J];            if (Num[i + 1][j]) connect[pos][++connect[pos][0]] = num[i + 1][j];            if (Num[i-1][j]) connect[pos][++connect[pos][0]] = num[i-1][j];            if (Num[i][j + 1]) connect[pos][++connect[pos][0]] = num[i][j + 1];        if (Num[i][j-1]) connect[pos][++connect[pos][0]] = num[i][j-1]; }//----------//Find the initial state and the target State (measured the letter range only between ABC so lazy to write it)//initialize que[0][0] = que[0][1] = que[0][2] = que [0]        [3] = 0;        Goal[0] = goal[1] = goal[2] = goal[3] = 0;   Looking for the initial state     for (int i = 0; I! = h; ++i) for (int j = 0; J! = W; ++j) if (Islower (Pic[i][j])) {if (pic[i][j] = = ' a ') que[            0][1] = Num[i][j];            if (pic[i][j] = = ' B ') que[0][2] = Num[i][j];        if (pic[i][j] = = ' C ') que[0][3] = Num[i][j]; }//Find the target State for (int i = 0; I! = h; ++i) for (int j = 0; J! = W; ++j) if (Isupper (Pic[i][j])) {if (P            IC[I][J] = = ' A ') goal[1] = Num[i][j];            if (pic[i][j] = = ' B ') goal[2] = Num[i][j];        if (pic[i][j] = = ' C ') goal[3] = Num[i][j];        }//----------BFS ();    printf ("%d\n", goal[0]); }}

What is the two-way BFS? is to search from two directions, while searching from the beginning to the end, searching backwards from the end point and then indirectly from both ends. In the algorithm is the implementation of the two-way search alternately, when the search for the same state, the road is opened, the number of steps is the number of BFS steps on both sides.

The advantages of two-way BFS, is to avoid the one-way bfs step too much of the combined explosion of the situation, is the possibility too much, the road is long, to the back of the fork more and more, "explosion", and the two-way search can delay the combination of a certain degree of explosion, but also greatly improve the efficiency. Of course, even if two-way, if the algorithm is poorly written, it will be hopeless ... So before this problem card to die ah ...

But in writing, you need to pay attention to two-way BFS is how a two-way approach. Some comrades mistakenly think that the two-way BFS is an alternating node search, that is, searching for a point, and then searching backwards a point, search the same point to hit the path. But in some cases this can be a mistake. For example, the following diagram (the slag mouse to draw, not to spray ...) ):

 Above is a ring, with two-way BFS search if the node is alternately searched, it may be wrong. If adding a node to the queue is the first to add the smallest words, starting from the starting point, the queue is 1,,4, and then search from the end, the queue is 3, 5. And then the search, the search 1, the search 5, and then inverted search, from 3 found 5, is already found in the state, and then concluded that the shortest short-circuit length is 4. However, it is clear that the correct answer should be the beginning →4→5→ end point, the length is 3.

What about that? The right approach is one layer at a-level. In this way, 1 and 4 were searched from the starting point, 3 and 5 were found at the end point, and 1 and 4 were found from 2 and 5, and then 5 were connected.

Now know the two-way BFS is what and how to search two-way, then the last one-way version of the change into two-way.

about how to achieve a layer of search, I am here to practice is to remember the number of steps, that is, this is the first layer of search, the next layer of searching for the node before continuing in this direction of BFS, when the next layer of the node, the search terminates. I do not know if this method is good enough to welcome the great God.

Say this question POJ also have, I changed into two-way BFS results mle, it seems to have to change the queue to STL line AH ... But it's good that UVA directly uses the array as a.

From one-way BFS to two-way BFS, the time is reduced from 3.6 seconds to 2.4 seconds

#include <cstdio> #include <cstring> #include <cctype> #include <list> #include <algorithm >using namespace Std;int w,h,n;char pic[20][20];///input int num[20][20];///The position in the input, the number of the node in the figure int connect[200][200];/ adjacency table int all;///The number of nodes in the graph int start[4];///start state int goal[4];///target State int que_fro[1000000][4], que_back[1000000][4];/// BFS queue int vis_fro[200][200][200], vis_back[200][200][200];///tag array bool Bfs_fro (const int &_step, int &fro, int & Amp;rear) {while (Fro < rear) {int &step = Que_fro[fro][0],&a =que_fro[fro][1], &b=que_fro[fro][2]        ,&c=que_fro[fro][3];        if (step>_step) break;        if (Vis_back[a][b][c]) return true;            for (int i=0,t1;i<=connect[a][0];++i) {t1= (i==0?a:connect[a][i]);                for (int j=0,t2; j<=connect[b][0];++j) {t2= (j==0?b:connect[b][j]);                    for (int k=0,t3;k<=connect[c][0];k++) {t3= (k==0?c:connect[c][k]);              Judging conflict----      if ((t1&&t2&&t1==t2) | | | (T1&AMP;&AMP;T3&AMP;&AMP;T1==T3) | | (T2&AMP;&AMP;T3&AMP;&AMP;T2==T3))                    continue;///cannot wear if ((t1&&t2&&t1==b&&t2==a)) Continue;///t1,t2 cannot wear if ((t1&&t3&&t1==c&&t3==a)) CONTINUE;///T1,T3 is not able to wear if (t2&&t3&& AMP;T2==C&AMP;&AMP;T3==B)) Continue;///t2,t3 cannot wear//------------if (!vis_fro[t1][t2] [T3])                        {vis_fro[t1][t2][t3]=1;                        QUE_FRO[REAR][0]=STEP+1,QUE_FRO[REAR][1]=T1,QUE_FRO[REAR][2]=T2,QUE_FRO[REAR][3]=T3;                    ++rear;    }}}} ++fro; } return false;} BOOL Bfs_back (const int &_step, int &fro, int &rear) {while (Fro < rear) {int &step = Que_back [Fro]        [0],&a =que_back[fro][1], &b=que_back[fro][2],&c=que_back[fro][3]; if (Step>_step) BreaK        if (Vis_fro[a][b][c]) return true;            for (int i=0,t1;i<=connect[a][0];++i) {t1= (i==0?a:connect[a][i]);                for (int j=0,t2; j<=connect[b][0];++j) {t2= (j==0?b:connect[b][j]);                    for (int k=0,t3;k<=connect[c][0];k++) {t3= (k==0?c:connect[c][k]); Judge conflict----if (T1&AMP;&AMP;T2&AMP;&AMP;T1==T2) | | (T1&AMP;&AMP;T3&AMP;&AMP;T1==T3) | | (T2&AMP;&AMP;T3&AMP;&AMP;T2==T3))                    continue;///cannot wear if ((t1&&t2&&t1==b&&t2==a)) Continue;///t1,t2 cannot wear if ((t1&&t3&&t1==c&&t3==a)) CONTINUE;///T1,T3 is not able to wear if (t2&&t3&& AMP;T2==C&AMP;&AMP;T3==B)) Continue;///t2,t3 cannot be worn on//------------if (!vis_back[t1][t2                        ][T3]) {vis_back[t1][t2][t3]=1; Que_back[rear][0]=step+1,que_back[rear][1]=t1,que_back[rear][2]=t2,que_back[Rear]                        [3]=t3;                    ++rear;    }}}} ++fro; } return false;}    int BFS () {//Initialize memset (vis_fro,0,sizeof (Vis_fro)), memset (vis_back,0,sizeof (vis_back));    int Fro_fro (0), Fro_back (0), Rear_fro (1), rear_back (1);    Vis_fro[start[1]][start[2]][start[3]]=true, Vis_back[goal[1]][goal[2]][goal[3]]=true;    int Step_fro = 0, step_back=0;    QUE_FRO[0][0]=START[0],QUE_FRO[0][1]=START[1],QUE_FRO[0][2]=START[2],QUE_FRO[0][3]=START[3];    QUE_BACK[0][0]=GOAL[0],QUE_BACK[0][1]=GOAL[1],QUE_BACK[0][2]=GOAL[2],QUE_BACK[0][3]=GOAL[3]; Two-way BFS search while (Fro_fro < Rear_fro) | | (Fro_back < Rear_back))        {/////Previous search for a layer if (Bfs_fro (Step_fro, Fro_fro, Rear_fro)) return step_fro+step_back;        else step_fro++;        Search from the back to the first layer if (Bfs_back (step_back,fro_back,rear_back)) return Step_fro + step_back;    else step_back++; } return-1;} int main () {while (scanf ("%d%d%d",&w,&h,&N) &&w&&h&&n) {///Read input gets (pic[0]);        for (int i=0;i!=h;i++) gets (Pic[i]);        --------///Build Diagram memset (connect,0,sizeof (connect) based on input initialization;        all=0;            Get the number for (int i=0;i!=h;i++) for (int j=0;j!=w;j++) {if (pic[i][j]!= ' # ') num[i][j] = ++all;        else num[i][j]=0;            }///create diagram for (int i=0;i!=h;i++) for (int j=0;j!=w;j++) if (Num[i][j]) {int &pos = num[i][j];            if (Num[i+1][j]) connect[pos][++connect[pos][0]]=num[i+1][j];            if (Num[i-1][j]) connect[pos][++connect[pos][0]]=num[i-1][j];            if (num[i][j+1]) connect[pos][++connect[pos][0]]=num[i][j+1];        if (Num[i][j-1]) connect[pos][++connect[pos][0]]=num[i][j-1];        }///----------///search for initial status and target status (test the letter range only between ABC)///Initialize start[0]=start[1]=start[2]=start[3]=0;        goal[0]=goal[1]=goal[2]=goal[3]=0; Look for the initial state for (int i=0;i!=h;i++) for (int j=0; j!=w;j++) if (Islower (Pic[i][j])) {if (pic[i][j]== ' a ') start[1]=num[i][j];            if (pic[i][j]== ' B ') start[2]=num[i][j];        if (pic[i][j]== ' C ') start[3]=num[i][j]; }///Look for the target State for (int i=0;i!=h;i++) for (int j=0;j!=w;++j) if (Isupper (Pic[i][j])) {if (pic[i][j]== ' A '            ) Goal[1]=num[i][j];            if (pic[i][j]== ' B ') goal[2]=num[i][j];        if (pic[i][j]== ' C ') goal[3]=num[i][j];    } printf ("%d\n", BFS ()); }}
Original link: http://blog.csdn.net/crazysillynerd/article/details/42681579


Uva1601-the Morning after Halloween (unidirectional + bidirectional BFS)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.