• 搜索进阶题


    1.http://acm.hdu.edu.cn/showproblem.php?pid=1254    推箱子问题

    分析:由于箱子每次都只能推,而不能拉,所以我们知道,每次往方向 i 推的时候,人必然会站在一个确切的位置 p 。所以我们在每次推箱子的时候先bfs求出人是否可以到达 p 位置。若可以到达 p ,则往 p 的对面的推动一格,否则判断下一个方向。直到推到目标位置为止。然后我们得到下面的代码:

      1 //First Edit Time:    2014-11-02 17:06
      2 //Last Edit Time:    2014-11-02 18:20
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <queue>
      6 using namespace std;
      7 
      8 struct Pos
      9 {
     10     int bx, by;
     11     int px, py;
     12     int step;
     13 }Box, Person;
     14 
     15 int map[10][10], n, m;
     16 bool used[10][10][10][10];
     17 int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
     18 bool visited[10][10];
     19 
     20 bool Judge_Person (Pos a)
     21 {
     22     if(a.px<0 || a.px>m-1 || a.py<0 || a.py>n-1 || visited[a.px][a.py]
     23             || map[a.px][a.py]==1 || (a.px==Box.bx && a.py==Box.by))
     24         return false;
     25     return true;
     26 }
     27 
     28 bool Judge_Box (Pos a)
     29 {
     30     if(a.bx<0 || a.bx>m-1 || a.by<0 || a.by>n-1 || used[a.bx][a.by][Person.px][Person.py] || map[a.bx][a.by]==1)
     31         return false;
     32     return true;
     33 }
     34 
     35 Pos Find_p (Pos a, int i)
     36 {
     37     Pos P = a;
     38     if (i==0)
     39     {
     40         P.px = a.bx + dir[1][0];
     41         P.py = a.by + dir[1][1];
     42     }
     43     else if (i==1)
     44     {
     45         P.px = a.bx + dir[0][0];
     46         P.py = a.by + dir[0][1];
     47     }
     48     else if (i==2)
     49     {
     50         P.px = a.bx + dir[3][0];
     51         P.py = a.by + dir[3][1];
     52     }
     53     else if (i==3)
     54     {
     55         P.px = a.bx + dir[2][0];
     56         P.py = a.by + dir[2][1];
     57     }
     58     return P;
     59 }
     60 
     61 //
     62 bool bfs_person (Pos a)
     63 {
     64     memset (visited, 0, sizeof visited);
     65     if (!Judge_Person (a)) return false;
     66 
     67     Pos Pre, Cur;
     68     queue <Pos> Q;
     69     visited[Person.px][Person.py] = true;
     70 
     71     Q.push (Person);
     72     while (!Q.empty())
     73     {
     74         Pre = Q.front();
     75         Q.pop();
     76         for (int i=0; i<4; i++)
     77         {
     78             Cur.px = Pre.px + dir[i][0];
     79             Cur.py = Pre.py + dir[i][1];
     80             if (Judge_Person (Cur))
     81             {
     82                 visited[Cur.px][Cur.py] = true;
     83                 if (Cur.px==a.px && Cur.py==a.py)
     84                     return true;
     85                 Q.push (Cur);
     86             }
     87         }
     88     }
     89     return false;
     90 }
     91 
     92 int bfs_box ()
     93 {
     94     Pos Pre, Cur, P;
     95     queue <Pos> Q;
     96     memset (used, 0, sizeof used);
     97 
     98     used[Box.bx][Box.by][Person.px][Person.py] = true;
     99     Q.push (Box);
    100     while (!Q.empty ())
    101     {
    102         Pre = Q.front ();
    103         Q.pop();
    104         for (int i=0; i<4; i++)
    105         {
    106             Box = Pre;
    107 
    108             //找到推箱子的位置
    109             P = Find_p (Pre, i);
    110             
    111             if (bfs_person (P))
    112             {
    113                 Cur = Pre;
    114                 Person = P;
    115                 Cur.bx += dir[i][0];
    116                 Cur.by += dir[i][1];
    117                 Cur.step += 1;
    118                 if (Judge_Box (Cur))
    119                 {
    120                     used[Cur.bx][Cur.by][Person.px][Person.py] = true;
    121                     if (map[Cur.bx][Cur.by]==3)
    122                         return Cur.step;
    123                     Q.push (Cur);
    124                 }
    125             }
    126         }
    127     }
    128     return -1;
    129 }
    130 
    131 int main ()
    132 {
    133     int t;
    134     freopen ("test.in","r",stdin);
    135     scanf ("%d",&t);
    136     while (t--)
    137     {
    138         scanf ("%d%d",&m, &n);
    139         for (int i=0; i<m; i++)
    140             for (int j=0; j<n; j++)
    141             {
    142                 scanf ("%d",map[i]+j);
    143                 if (map[i][j]==2)
    144                     Box.bx=i, Box.by=j, Box.step=0;
    145                 else if (map[i][j]==4)
    146                     Person.px = i,Person.py = j;
    147             }
    148         int ans = bfs_box ();
    149         printf ("%d
    ",ans);
    150     }
    151     return 0;
    152 }
    View Code

      然后我就这样一直WA到死。后来问了学长才知道,其实我没有考虑到另一种情况:

    1
    5 3
    0 0 0
    0 0 0
    0 2 0
    1 4 1
    1 3 1

    在上面这种情况下,以上代码得到的答案是-1,因为上面的程序一开始就访问了他本应该去的位置 p ,导致最后要用到 p 的时候得到 p 不可到达的错误信息而是答案出错。

    改正之后的代码:

      1 //First Edit Time:    2014-11-02 17:06
      2 //Last Edit Time:    2014-11-02 18:20
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <queue>
      6 using namespace std;
      7 
      8 struct Pos
      9 {
     10     int bx, by;
     11     int px, py;
     12     int step;
     13 }Box, Person;
     14 
     15 int map[10][10], n, m;
     16 bool used[10][10][10][10];
     17 int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
     18 bool visited[10][10];
     19 
     20 bool Judge_Person (Pos a)
     21 {
     22     if(a.px<0 || a.px>m-1 || a.py<0 || a.py>n-1 || visited[a.px][a.py]
     23             || map[a.px][a.py]==1 || (a.px==Box.bx && a.py==Box.by))
     24         return false;
     25     return true;
     26 }
     27 
     28 bool Judge_Box (Pos a)
     29 {
     30     if(a.bx<0 || a.bx>m-1 || a.by<0 || a.by>n-1 || used[a.bx][a.by][Person.px][Person.py] || map[a.bx][a.by]==1)
     31         return false;
     32     return true;
     33 }
     34 
     35 Pos Find_p (Pos a, int i)
     36 {
     37     Pos P = a;
     38     if (i==0)
     39     {
     40         P.px = a.bx + dir[1][0];
     41         P.py = a.by + dir[1][1];
     42     }
     43     else if (i==1)
     44     {
     45         P.px = a.bx + dir[0][0];
     46         P.py = a.by + dir[0][1];
     47     }
     48     else if (i==2)
     49     {
     50         P.px = a.bx + dir[3][0];
     51         P.py = a.by + dir[3][1];
     52     }
     53     else if (i==3)
     54     {
     55         P.px = a.bx + dir[2][0];
     56         P.py = a.by + dir[2][1];
     57     }
     58     return P;
     59 }
     60 
     61 //
     62 bool bfs_person (Pos a)
     63 {
     64     memset (visited, 0, sizeof visited);
     65     if (!Judge_Person (a)) return false;
     66     if (a.px==Person.px && a.py==Person.py)  //改正之处。就是把那种情况特判了一下;
     67         return true;
     68     Pos Pre, Cur;
     69     queue <Pos> Q;
     70     visited[Person.px][Person.py] = true;
     71 
     72     Q.push (Person);
     73     while (!Q.empty())
     74     {
     75         Pre = Q.front();
     76         Q.pop();
     77         for (int i=0; i<4; i++)
     78         {
     79             Cur.px = Pre.px + dir[i][0];
     80             Cur.py = Pre.py + dir[i][1];
     81             if (Judge_Person (Cur))
     82             {
     83                 visited[Cur.px][Cur.py] = true;
     84                 if (Cur.px==a.px && Cur.py==a.py)
     85                     return true;
     86                 Q.push (Cur);
     87             }
     88         }
     89     }
     90     return false;
     91 }
     92 
     93 int bfs_box ()
     94 {
     95     Pos Pre, Cur, P;
     96     queue <Pos> Q;
     97     memset (used, 0, sizeof used);
     98 
     99     used[Box.bx][Box.by][Person.px][Person.py] = true;
    100     Q.push (Box);
    101     while (!Q.empty ())
    102     {
    103         Pre = Q.front ();
    104         Q.pop();
    105     //  printf ("Box:(%d, %d) ---- %d
    ",Pre.bx+1, Pre.by+1, Pre.step);
    106         for (int i=0; i<4; i++)
    107         {
    108             Box = Pre;
    109 
    110             //找到推箱子的位置
    111             P = Find_p (Pre, i);
    112         //    printf ("Person:(%d,%d)
    ",P.px+1,P.py+1);
    113             if (bfs_person (P))
    114             {
    115                 Cur = Pre;
    116                 Person = P;
    117                 Cur.bx += dir[i][0];
    118                 Cur.by += dir[i][1];
    119                 Cur.step += 1;
    120     //        printf ("Goto:(%d, %d)
    ",Cur.bx+1, Cur.by+1);
    121                 if (Judge_Box (Cur))
    122                 {
    123                     used[Cur.bx][Cur.by][Person.px][Person.py] = true;
    124                     if (map[Cur.bx][Cur.by]==3)
    125                         return Cur.step;
    126                     Q.push (Cur);
    127                 }
    128             }
    129         }
    130     }
    131     return -1;
    132 }
    133 
    134 int main ()
    135 {
    136     int t;
    137     freopen ("test.in","r",stdin);
    138     scanf ("%d",&t);
    139     while (t--)
    140     {
    141         scanf ("%d%d",&m, &n);
    142         for (int i=0; i<m; i++)
    143             for (int j=0; j<n; j++)
    144             {
    145                 scanf ("%d",map[i]+j);
    146                 if (map[i][j]==2)
    147                     Box.bx=i, Box.by=j, Box.step=0;
    148                 else if (map[i][j]==4)
    149                     Person.px = i,Person.py = j;
    150             }
    151         int ans = bfs_box ();
    152         printf ("%d
    ",ans);
    153     }
    154     return 0;
    155 }
    View Code

    2.http://acm.hdu.edu.cn/showproblem.php?pid=2553       N皇后问题

    分析:先明确这是求所有解的问题,所有可以用DFS解答。在N*N的矩阵中,放N个皇后,由于皇后不能在同一行同一列同一斜线,所以,我们单从行来看,在一行中不可能出现两个及以上的皇后。又由于必须得放N个皇后,所以每一行都必有且仅有一个皇后。那么问题的解就可以用一个N元向量 Xi  (i=1,2,3....N)来表示。我们把N个皇后从0--N编号。C[i]表示第 i 行放置的皇后的编号。然后对数轴0--N DFS一遍即可得到答案。为防TLE,先预处理一下。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cmath>
     4 using namespace std;
     5 
     6 int C[11], out[11], ans, n;
     7 
     8 void dfs (int cur)
     9 {
    10     if (cur==n)
    11     {
    12         ans++;
    13         return;
    14     }
    15     for (int i=0; i<n; i++)
    16     {
    17         bool ok = true;
    18         C[cur] = i;
    19         for (int j=0; j<cur; j++)
    20             if (C[cur]==C[j] || cur-j==C[cur]-C[j] || cur+C[cur]==C[j]+j)
    21             {
    22                 ok = false;break;
    23             }
    24         if (ok)
    25             dfs (cur+1);
    26     }
    27 }
    28 
    29 int main ()
    30 {
    31     for (int i=1; i<=10; i++)
    32     {
    33         ans = 0;
    34         n = i;
    35         dfs (0);
    36         out[i] = ans;
    37     }
    38     while (~scanf ("%d",&n) && n)
    39         printf ("%d
    ",out[n]);
    40     return 0;
    41 }
    View Code

    3.http://acm.hdu.edu.cn/showproblem.php?pid=2612

    题意:Y和M是好朋友,他们两个打算在任一家KFC餐厅(至少有一家kFC餐厅)会面,问你,他们两个总共最少要花费多久时间才能见面?也就是他们两个各自到达这家见面餐厅的时间之和最少是多少?

    分析:显然是求最优解无疑,我们首先应该可以确定用BFS求解相比DFS要好点。那么我们可能会想到在输入的时候每次标记出KFC的位子,然后一重循环,分别bfs出Y,M到到第 i 个KFC的时间,每次更新最短时间。但是这种在KFC很多的情况下,复杂度可能会很高而导致TLE。事实上,我们可以用两次BFS求出答案。首先,我们BFS出 Y 到所有KFC的时间,并记录下来。然后,我们再BFS 出 M 到所有kFC的时间,并且在到达KFC时,判断当前 M 的时间加上第一次 BFS Y 到达这个店的时间与最小值的大小关系,选出最小的即可:

    代码如下:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <queue>
     4 using namespace std;
     5 #define N 205
     6 #define INF 0x3f3f3f3f
     7 #define Min(a, b) (a < b ? a : b)
     8 
     9 struct Pos
    10 {
    11     int x, y;
    12     int step;
    13 }Y, M;
    14 char map[N][N];
    15 int used_y[N][N], used_m[N][N];
    16 int dir[][2]={1,0, -1,0, 0,1, 0,-1};
    17 int n, m;
    18 
    19 void bfs_y (Pos a)
    20 {
    21     Pos Pre, Cur;
    22     queue <Pos> Q;
    23     memset (used_y, 0, sizeof used_y);
    24 
    25     used_y[a.x][a.y] = 1;
    26     Q.push (a);
    27     while (!Q.empty ())
    28     {
    29         Pre = Q.front();
    30         Q.pop();
    31         if (map[Pre.x][Pre.y]=='@')
    32             used_y[Pre.x][Pre.y] = Pre.step;
    33         for (int i=0; i<4; i++)
    34         {
    35             Cur = Pre;
    36             Cur.x += dir[i][0];
    37             Cur.y += dir[i][1];
    38             Cur.step += 1;
    39             if (Cur.x<0||Cur.x>n-1 || Cur.y<0||Cur.y>m-1 || used_y[Cur.x][Cur.y] || map[Cur.x][Cur.y]=='#') continue;
    40             used_y[Cur.x][Cur.y] = 1;
    41             Q.push (Cur);
    42         }
    43     }
    44 }
    45 
    46 int bfs_m (Pos a)
    47 {
    48     Pos Pre, Cur;
    49     queue <Pos> Q;
    50     memset (used_m, 0, sizeof used_m);
    51 
    52     int ans = INF;
    53     used_m[a.x][a.y] = 1;
    54     Q.push (a);
    55     while (!Q.empty ())
    56     {
    57         Pre = Q.front();
    58         Q.pop();
    59         if (map[Pre.x][Pre.y]=='@')
    60             ans = Min(ans, (used_y[Pre.x][Pre.y]+Pre.step));
    61         for (int i=0; i<4; i++)
    62         {
    63             Cur = Pre;
    64             Cur.x += dir[i][0];
    65             Cur.y += dir[i][1];
    66             Cur.step += 1;
    67             if (Cur.x<0||Cur.x>n-1 || Cur.y<0||Cur.y>m-1 || used_m[Cur.x][Cur.y] || map[Cur.x][Cur.y]=='#') continue;
    68             used_m[Cur.x][Cur.y] = 1;
    69             Q.push (Cur);
    70         }
    71     }
    72     return ans;
    73 }
    74 
    75 int main()
    76 {
    77     while (~scanf ("%d%d",&n, &m) && n+m)
    78     {
    79         for (int i=0; i<n; i++)
    80             for (int j=0; j<m; j++)
    81             {
    82                 scanf (" %c",map[i]+j);
    83                 if (map[i][j]=='Y')
    84                     Y.x=i, Y.y=j, Y.step=0;
    85                 else if (map[i][j]=='M')
    86                     M.x=i, M.y=j, M.step=0;
    87             }
    88 
    89         bfs_y (Y);
    90         int ans = bfs_m (M);
    91         printf ("%d
    ",ans*11);
    92     }
    93     return 0;
    94 }
    View Code

    4.http://acm.hdu.edu.cn/showproblem.php?pid=1495   非常可乐

    分析:首先BFS求最优解,因为三个杯子之间相互倒水共六种情况:s->n, s->m, n->m, n->s, m->s, m->n;然后遍历六种情况即可,值得注意的是,一个 -= 被我写成+=,WA了N多次。

      1 //First Edit Time:    2014-11-05 20:54
      2 //Last Edit Time:    2014-11-05 20:55
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <queue>
      6 #define N 110
      7 using namespace std;
      8 
      9 struct Node
     10 {
     11     int x, y;
     12     int cup, step;
     13 };
     14 int s, n, m;
     15 bool used[N][N][N];
     16 
     17 void Move (Node &a, int i)
     18 {
     19     // 倒出的水取决于 Min(当前杯中剩余容量, 最多能倒出的水量)
     20     if (i==0)  //s -> x
     21     {
     22         int tmp = (n-a.x) < a.cup ? (n-a.x):a.cup;
     23         a.x += tmp;
     24         a.cup -= tmp;
     25     }
     26     else if (i==1) // s -> y
     27     {
     28         int tmp = (m-a.y) < a.cup ? (m-a.y):a.cup;
     29         a.y += tmp;
     30         a.cup -= tmp;
     31     }
     32     else if (i==2) // x -> s
     33     {
     34         int tmp =  (s-a.cup) < a.x ? (s-a.cup):a.x;
     35         a.cup += tmp;
     36         a.x -= tmp;
     37     }
     38     else if (i==3)  // y -> s
     39     {
     40         int tmp = (s-a.cup) < a.y ? (s-a.cup):a.y;
     41         a.cup += tmp;
     42         a.y -= tmp;
     43     }
     44     else if (i==4) // y -> x
     45     {
     46         int tmp = (n-a.x) < a.y ? (n-a.x) : a.y;
     47         a.x += tmp;
     48         a.y -= tmp;
     49     }
     50     else if (i==5)  // x -> y
     51     {
     52         int tmp = (m-a.y) < a.x ? (m-a.y) : a.x;
     53         a.y +=  tmp;
     54         a.x -= tmp;         //   -= 被写成 += wa无数,我也是醉了、
     55     }
     56 }
     57 
     58 int bfs ()
     59 {
     60     Node Pre, Cur;
     61     queue <Node> Q;
     62     memset (used, 0, sizeof used);
     63 
     64     used[s][0][0] = true;
     65     Pre.x=Pre.y=Pre.step = 0;
     66     Pre.cup = s;
     67     Q.push (Pre);
     68     while (!Q.empty())
     69     {
     70         Pre = Q.front();
     71         Q.pop();
     72      // printf ("(%d, %d, %d) ----- %d
    ",Pre.cup, Pre.x, Pre.y, Pre.step);
     73         if ((Pre.x==Pre.y && Pre.x+Pre.y==s)||(Pre.x==Pre.cup && Pre.x+Pre.cup==s) || (Pre.cup==Pre.y && Pre.cup+Pre.y==s))
     74             return Pre.step;
     75         for (int i=0; i<6; i++)
     76         {
     77             Cur = Pre;
     78             Move (Cur, i);
     79             Cur.step += 1;
     80     //    printf ("(%d, %d, %d)
    ",Cur.cup, Cur.x, Cur.y);
     81             if (!used[Cur.cup][Cur.x][Cur.y])
     82             {
     83                 used[Cur.cup][Cur.x][Cur.y] = true;
     84                 Q.push (Cur);
     85             }
     86         }
     87     }
     88     return -1;
     89 }
     90 int main ()
     91 {
     92     while (~scanf ("%d%d%d",&s, &n, &m) && s+n+m)
     93     {
     94       int ans;
     95       if (s&1) ans = -1;else ans = bfs ();
     96 
     97         if (ans == -1)
     98             puts ("NO");
     99         else
    100             printf("%d
    ",ans);
    101     }
    102     return 0;
    103 }
    View Code
  • 相关阅读:
    用AI思维给成本降温,腾讯WeTest兼容性测试直击底价!
    DOIS2019大会,腾讯 DevOps 测试中台探秘
    腾讯WeTest兼容服务再次升级,支持小程序兼容
    打造游戏金融小程序行业测试标准腾讯WeTest携各专家共探品质未来
    我对模板模式和策略模式的理解
    retrofit
    nginx--阿里云--success
    volatile--学习--未使用过
    linux---多线程---信号量--不懂
    sql优化---后面再看吧
  • 原文地址:https://www.cnblogs.com/khan724/p/4069932.html
Copyright © 2020-2023  润新知