• POJ 3083 -- Children of the Candy Corn(DFS+BFS)TLE


    POJ 3083 -- Children of the Candy Corn(DFS+BFS)

    题意:

    给定一个迷宫,S是起点,E是终点,#是墙不可走,.可以走

    1)先输出左转优先时,从S到E的步数

    2)再输出右转优先时,从S到E的步数

    3)最后输出S到E的最短步数

     

    解题思路:

    前两问DFS,转向只要控制一下旋转方向就可以

    首先设置前进方向对应的数字

    向上——N——0

    向右——E——1

    向下——S——2

    向左——W——3

    比如说右转优先,即为向右,向前,向左,向后,即逆时针方向for(int i=1;i>=-2;i--)

    左转优先,即为向左,向前,向右,向后,即顺时针方向for(int i=-1;i<=3;i++)

    第三问最短路,BFS

    普通递归(TLE)

      1 #include<iostream>
      2 #include<cstring>
      3 #include<queue>
      4 #include<cstdio>
      5 using namespace std;
      6 int r,c;///行r,列c
      7 int r0,c0,r3,c3;///r0,c0用来标记入口,r3,c3用来标记出口
      8 const char *dirs = "NESW";
      9 const int maxn = 41;
     10 char square[maxn][maxn];
     11 const int dr[] = {-1,0,1,0};
     12 const int dc[] = { 0,1,0,-1};
     13 struct node{
     14 int row,col,deep;
     15 int dir;///0123对应NESW
     16 node(int row=0,int col=0,int dir=0,int deep=0):row(row),col(col),dir(dir),deep(deep){}
     17 };
     18 bool inside(int xx,int yy)
     19 {
     20     return xx>=1 && xx<=r && yy>=1 && yy<=c;
     21 }
     22 
     23 bool flag1;
     24 int step1;
     25 void dfs1(node *way,int x,int y,int d,int step)
     26 {///左转优先
     27     way[step].row = x;
     28     way[step].col = y;
     29     way[step].dir = d;
     30     if(x==r3 && y==c3)///走到出口
     31     {
     32         step1 = step;
     33         flag1 = true;
     34         return;
     35     }
     36     for(int i=-1;i<=3;i++)
     37     {
     38         int tempDir = (way[step].dir + 4 + i)%4;///进行旋转
     39         int xx = way[step].row + dr[tempDir];
     40         int yy = way[step].col + dc[tempDir];
     41         if(inside(xx,yy) && square[xx][yy]!='#')
     42         {///没有出界,可以行走
     43             dfs1(way,xx,yy,tempDir,step+1);
     44         }
     45         if(flag1)
     46             return;
     47     }
     48     return;
     49 }
     50 
     51 int step2;bool flag2;
     52 void dfs2(node *way,int x,int y,int d,int step)
     53 {///右转优先
     54     way[step].row = x;
     55     way[step].col = y;
     56     way[step].dir = d;
     57     if(x==r3 && y==c3)///走到出口
     58     {
     59         step2 = step;
     60         flag2 = true;
     61         return;
     62     }
     63     for(int i=1;i>=-2;i--)
     64     {
     65         int tempDir = (way[step].dir + 4 + i)%4;///进行旋转
     66         int xx = way[step].row + dr[tempDir];
     67         int yy = way[step].col + dc[tempDir];
     68         if(inside(xx,yy) && square[xx][yy]!='#')
     69         {///没有出界,可以行走
     70             dfs2(way,xx,yy,tempDir,step+1);
     71         }
     72         if(flag2)
     73             return;
     74     }
     75     return;
     76 }
     77 node d[maxn][maxn][4];
     78 
     79 void bfs(int x,int y,int d)
     80 {
     81     queue<node> q;
     82     node u(x,y,d,1);///入口结点
     83     q.push(u);
     84     while(!q.empty())
     85     {
     86         node u = q.front();q.pop();
     87         if(u.row == r3 && u.col == c3)
     88         {
     89             cout<<u.deep<<endl;
     90             return;
     91         }
     92         for(int i=0;i<=3;i++)
     93         {
     94             int tempDir = (u.dir +i)%4;///进行旋转
     95             int xx = u.row + dr[tempDir];
     96             int yy = u.col + dc[tempDir];
     97             if(inside(xx,yy) && square[xx][yy]!='#')
     98             {///没有出界,可以行走
     99                 node v(xx,yy,tempDir,u.deep+1);
    100                 q.push(v);
    101             }
    102         }
    103     }
    104 }
    105 
    106 int startDir()
    107 {///计算从入口进入之后的方向
    108     if(r0 == 1) return 2;
    109     else if(r0 == r) return 0;
    110     else if(c0 == 1) return 1;
    111     else return 3;
    112 }
    113 int main()
    114 {
    115     int n;
    116     cin>>n;
    117     while(n--)
    118     {
    119         cin>>c>>r;///输入为先输入列数,在输入行数
    120         char temp;
    121         for(int i=1;i<=r;i++)
    122             for(int j=1;j<=c;j++)
    123             {
    124                 temp = getchar();
    125                 while(temp == '
    ') temp = getchar();
    126                 square[i][j] = temp;
    127                 if(temp == 'S'){r0 = i;c0 = j;}
    128                 if(temp == 'E'){r3 = i;c3 = j;}
    129             }
    130         node *way = new node[maxn*maxn];
    131         ///求解左转优先
    132         flag1 = false;step1 = 1;
    133         int startdir = startDir();
    134         dfs1(way,r0,c0,startdir,1);
    135         if(flag1) cout<<step1<<" ";
    136         ///求解右转优先
    137         flag2 = false;step2 = 1;
    138         dfs2(way,r0,c0,startdir,1);
    139         if(flag2) cout<<step2<<" ";
    140         ///求解最短路径
    141         bfs(r0,c0,startdir);
    142     }
    143     return 0;
    144 }

     最终成功代码

    Time Limit Exceeded原因:POJ对STL兼容性不高,使用queue超时

    其次,DFS使用尾递归形式,遇到可行解,直接向下一层搜索

    最后,BFS不能走重复路线,否则会陷入死循环,Runtime Error

    仅此告诫自己

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 using namespace std;
      5 int r,c;///行r,列c
      6 int r0,c0,r3,c3;///r0,c0用来标记入口,r3,c3用来标记出口
      7 
      8 const int maxn = 42;
      9 char square[maxn][maxn];
     10 const int dr[] = {-1,0,1,0};
     11 const int dc[] = { 0,1,0,-1};
     12 
     13 struct node{
     14 int row,col,deep;
     15 int dir;///0123对应NESW
     16 node(int row=0,int col=0,int dir=0,int deep=0):row(row),col(col),dir(dir),deep(deep){}
     17 };
     18 bool inside(int xx,int yy)
     19 {
     20     return xx>=1 && xx<=r && yy>=1 && yy<=c;
     21 }
     22 int dfs12(int x,int y,int d)
     23 {///左转优先
     24     if(square[x][y] == 'E')
     25         return 1;
     26     int tempDir,xx,yy;
     27     for(int i=-1;i<=3;i++)
     28     {
     29         tempDir = (d + 4 + i)%4;///进行旋转
     30         xx = x + dr[tempDir];
     31         yy = y + dc[tempDir];
     32         if(inside(xx,yy) && square[xx][yy]!='#')
     33         {///没有出界,可以行走
     34             break;
     35         }
     36     }
     37     return dfs12(xx,yy,tempDir)+1;
     38 }
     39 int dfs22(int x,int y,int d)
     40 {///you转优先
     41     if(square[x][y] == 'E')
     42         return 1;
     43     int tempDir,xx,yy;
     44 
     45     for(int i=1;i>=-2;i--)
     46     {
     47         tempDir = (d + 4 + i)%4;///进行旋转
     48         xx = x + dr[tempDir];
     49         yy = y + dc[tempDir];
     50         if(inside(xx,yy) && square[xx][yy]!='#')
     51         {///没有出界,可以行走
     52             break;
     53         }
     54     }
     55     return dfs22(xx,yy,tempDir)+1;
     56 }
     57 
     58 node queue[1600];
     59 bool has_walk[maxn][maxn];
     60 void bfs(int x,int y,int d)
     61 {
     62     int head=0,tail=1;
     63     node u(x,y,d,1);
     64     has_walk[x][y] = false;
     65     queue[head] = u;///入口结点
     66     while(head<tail)
     67     {
     68         node u = queue[head++];
     69         if(u.row == r3 && u.col == c3)
     70         {
     71             cout<<u.deep<<endl;
     72             return;
     73         }
     74         for(int i=0;i<=3;i++)
     75         {
     76             int tempDir = (u.dir +i)%4;///进行旋转
     77             int xx = u.row + dr[tempDir];
     78             int yy = u.col + dc[tempDir];
     79             if(inside(xx,yy) && square[xx][yy]!='#' && has_walk[xx][yy])
     80             {///没有出界,可以行走,没有走过true
     81                 node v(xx,yy,tempDir,u.deep+1);
     82                 has_walk[xx][yy] = false;
     83                 queue[tail] = v;
     84                 tail++;
     85             }
     86         }
     87     }
     88 }
     89 
     90 int startDir()
     91 {///计算从入口进入之后的方向
     92     if(r0 == 1) return 2;
     93     else if(r0 == r) return 0;
     94     else if(c0 == 1) return 1;
     95     else return 3;
     96 }
     97 int main()
     98 {
     99     int n;
    100     while(cin>>n)
    101     while(n--)
    102     {
    103         cin>>c>>r;///输入为先输入列数,在输入行数
    104         memset(has_walk,true,sizeof(has_walk));///true表示当前格子没有走过,可以走
    105         char temp;
    106         for(int i=1;i<=r;i++)
    107             for(int j=1;j<=c;j++)
    108             {
    109                 temp = getchar();
    110                 while(temp == '
    ') temp = getchar();
    111                 square[i][j] = temp;
    112                 if(temp == 'S'){r0 = i;c0 = j;}
    113                 if(temp == 'E'){r3 = i;c3 = j;}
    114             }
    115         ///求解左转优先
    116         int startdir = startDir();
    117         cout<<dfs12(r0,c0,startdir)<<" ";
    118         ///求解右转优先
    119         cout<<dfs22(r0,c0,startdir)<<" ";
    120         ///求解最短路径
    121         bfs(r0,c0,startdir);
    122     }
    123     return 0;
    124 }

    最后给大家提供点测试样例:

    5
    8 8
    ########
    #......#
    #.####.#
    #.####.#
    #.####.#
    #.####.#
    #...#..#
    #S#E####
    9 5
    #########
    #.#.#.#.#
    S.......E
    #.#.#.#.#
    #########
    8 5
    ########
    #.#.#..#
    S......E
    #.#.#..#
    ########
    2 3
    ##
    SE
    ##
    8 8
    ######E#
    #......#
    #.####.#
    #.####.#
    #.####.#
    #.####.#
    #...#..#
    #S######
    结果:
    37 5 5
    17 17 9
    14 14 8
    2 2 2
    13 29 13
  • 相关阅读:
    单调栈模板
    Yet Another Broken Keyboard[双指针]
    经典递归集合
    [未完成]ECRound 80
    #614 C. NEKO's Maze Game[简易DFS,0|1转换]
    等差数列异或和模板
    线段树基础题
    前缀和&差分
    优先队列
    st表模板
  • 原文地址:https://www.cnblogs.com/yxh-amysear/p/8453849.html
Copyright © 2020-2023  润新知