• UVa 1601 万圣节后的早晨


    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4476

    题意:给出w*h的网格,相当于迷宫,有大写字母和小写字母,算出小写字母走到大写字母状态时的最少步数。

    思路:建立新图,然后再bfs。

      1 #include<iostream>
      2 #include<string>
      3 #include<cstring>
      4 #include<queue>
      5 using namespace std;
      6 
      7 const int maxn = 16 * 16;
      8 
      9 char map[20][20];
     10 int w, h, n;
     11 int cnt; //非#结点个数
     12 int x[maxn], y[maxn];
     13 int s[3], t[3];  //记录初末位置
     14 int deg[maxn];  //记录每个格子相连的格子数
     15 int G[maxn][maxn];  //记录每个格子可以走的位置
     16 int new_map[20][20]; //新图
     17 int d[maxn][maxn][maxn]; //记录步数
     18 
     19 int dx[] = { 0, 1, -1, 0, 0 };
     20 int dy[] = { 0, 0, 0, 1, -1 };
     21 
     22 int ID(int x, int y, int z)   //二进制压缩存储,方便进出队列
     23 {
     24     return (x << 16) | (y << 8) | z;
     25 }
     26 
     27 bool judge(int a, int b, int a2, int b2)
     28 {
     29     return a2 == b2 || (a2 == b && b2 == a);
     30 }
     31 
     32 void bfs()
     33 {
     34     queue<int> q;
     35     memset(d, -1, sizeof(d));
     36     q.push(ID(s[0], s[1], s[2]));  //二进制压缩后再进队
     37     d[s[0]][s[1]][s[2]] = 0;
     38     while (!q.empty())
     39     {
     40         int u = q.front();
     41         q.pop();
     42         int a = (u >> 16) & 0xff; //得到压缩前的数据
     43         int b = (u >> 8) & 0xff;
     44         int c = u & 0xff;
     45         if (a==t[0] && b==t[1] && c==t[2]) //得到目标状态
     46         {
     47             cout << d[a][b][c] << endl;
     48             return;
     49         }
     50         for (int i = 0; i < deg[a]; i++)
     51         {
     52             int a2 = G[a][i];
     53             for (int j = 0; j < deg[b]; j++)
     54             {
     55                 int b2 = G[b][j];
     56                 if (judge(a, b, a2, b2))  continue; //删去不符合条件的走法
     57                 for (int k = 0; k < deg[c]; k++)
     58                 {
     59                     int c2 = G[c][k];
     60                     if (judge(a, c, a2, c2))  continue;
     61                     if (judge(b, c, b2, c2))  continue;
     62                     if (d[a2][b2][c2] != -1) continue;
     63                     d[a2][b2][c2] = d[a][b][c] + 1;
     64                     q.push(ID(a2, b2, c2));
     65                 }
     66             }
     67         }
     68     }
     69 }
     70 
     71 
     72 int main()
     73 {
     74     //freopen("D:\txt.txt", "r", stdin);
     75     while (cin>>w>>h>>n && n)
     76     {
     77         getchar();
     78         cnt = 0;   //记录非#结点个数
     79         memset(map, 0, sizeof(map));
     80         memset(deg, 0, sizeof(deg));
     81         for (int i = 0; i < h; i++)
     82         {
     83             fgets(map[i], 20, stdin);
     84             for (int j = 0; j < w; j++)
     85             {
     86                 if (map[i][j] != '#')
     87                 {
     88                     x[cnt] = i;
     89                     y[cnt] = j;
     90                     new_map[i][j] = cnt; //建图记录结点
     91                     if (map[i][j] >= 'a' && map[i][j] <= 'c')  s[map[i][j] - 'a'] = cnt;
     92                     if (map[i][j] >= 'A' && map[i][j] <= 'C')  t[map[i][j] - 'A'] = cnt;
     93                     cnt++;
     94                 }
     95             }
     96         }
     97 
     98         for (int i = 0; i < cnt; i++)
     99         {
    100             for (int k = 0; k < 5; k++)
    101             {
    102                 int xx = x[i] + dx[k];
    103                 int yy = y[i] + dy[k];
    104                 if (map[xx][yy] != '#')  G[i][deg[i]++] = new_map[xx][yy]; //如果可以走,则将第i个点的第deg[i]个方向的下一个格子记录
    105             }
    106         }
    107 
    108         //如果不满三个鬼,强行添加结点使之构成三个结点
    109 
    110         if (n <= 2) //添加虚拟结点
    111         {
    112             deg[cnt] = 1; G[cnt][0] = cnt; s[2] = t[2] = cnt++;
    113         }
    114         if (n <= 1)
    115         {
    116             deg[cnt] = 1; G[cnt][0] = cnt; s[1] = t[1] = cnt++;
    117         }
    118 
    119         bfs();
    120     }
    121     return 0;
    122 }
  • 相关阅读:
    Java基础教程——Object类
    Java之从头开始编写简单课程信息管理系统
    动手动脑之文件流
    doc四则运算
    Java异常处理的方法
    动手动脑-异常处理
    动手动脑-Java的继承与多态
    跟踪某个类中创建对象的个数
    动手动脑--类与对象
    动手动脑
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/6337291.html
Copyright © 2020-2023  润新知