程设2021期末题H:哥斯拉大战金刚

原题:http://cxsjsx.openjudge.cn/2021finalpractise/H/

描述

众所周知,哥斯拉和金刚是时代仇敌,大战一触即发。金刚为了打败哥斯拉,要先前往地心空洞获得战斧。金刚现在所在之处可以被视为一个n*m的网格图,S表示金刚目前的位置,T表示地心空洞的入口,X表示障碍物,.表示平地。在前往地心空洞之前,金刚必须先获得一系列打开地心空洞的钥匙(在地图上通过数字1,2,…,k表示),并且获得i类钥匙的前提是金刚已经获得了1,2,…,i-1类钥匙,金刚在拿到地图上所有种类的钥匙之后即可前往地心空洞的入口。另外,同一种类的钥匙可能有多把,金刚只需获得其中任意一把即可。金刚每一步可以朝上下左右四个方向中的一个移动一格,值得注意的是,哥斯拉为了阻挠金刚的计划,还在地图上设置了q个陷阱(在网格图中用G表示),金刚第一次进入某个陷阱需要花费额外的一步来破坏陷阱(这之后该陷阱即可被视为平地)。为了更好的掌握全局,请你帮金刚计算到达地心空洞入口所需要花费的最少步数。输入数据保证有解。

输入

第一行输入两个整数n,m,表示网格图的大小。
接下来n行,每行输入m个字符,表示地图
1 ≤ n,m ≤ 100
1 ≤ k ≤ 9
1 ≤ q ≤ 7

输出

输出一行包含一个整数,表示金刚到达地心空洞入口所需要花费的最少步数。

样例输入

5 5
XX13X
X.GXX
S...T
XXGXX
....2

样例输出

24 

解法

思路:广搜题,属于较为复杂的一种,既要收集钥匙也要破坏陷阱。

状态包括:x,y坐标,keys表示现在收集的钥匙种数,fighted表示是否已经消灭陷阱,steps记录此时的步数,layout是陷阱的分布(用short变量表示)。

去重:xy坐标+钥匙+陷阱分布

地图上的标识有

  • '.':平地;'X':障碍,不能通过;'T':终点;'S':起点;‘G’:陷阱;1~9的数字:钥匙
  • 起点和没有拿完钥匙的终点,不能拿的钥匙,破坏完的陷阱都当做平地处理

代码如下:

  1 #include <iostream>
  2 #include <queue>
  3 #include <cstring>
  4 #include <vector>
  5 #include <algorithm>
  6 using namespace std;
  7 struct point {
  8      int x, y;
  9      short keys;
 10      short fighted;
 11      int steps;
 12      short layout;
 13      point(int inx,int iny,short k,short f,int s, short l):x(inx),y(iny),keys(k),fighted(f),steps(s),layout(l){}
 14 };
 15 char flags[105][105][10][130];
 16 int n, m;
 17 int k, q;
 18 char maze[105][105];
 19 vector<pair<int, int> >traps;
 20 int dx[4] = { -1,1,0,0 };
 21 int dy[4] = { 0,0,-1,1 };
 22 int findTraps(int x, int y) {
 23     for (int i = 0; i < q; i++) {
 24         if (traps[i].first == x && traps[i].second == y)
 25             return i;
 26     }
 27 }
 28 int main() {
 29     cin >> n >> m;
 30     int startx, starty;
 31     q = 0;
 32     k = 0;
 33     for (int i = 0; i < n; i++) {
 34         for (int j = 0; j < m; j++) {
 35             cin >> maze[i][j];
 36             if (maze[i][j] == 'S') {
 37                 startx = i;
 38                 starty = j;
 39             }
 40             if (maze[i][j] == 'G') {
 41                 q++;
 42                 traps.push_back(make_pair(i, j));
 43             }
 44             if (maze[i][j] > '0'&&maze[i][j] <= '9')
 45                 k = max(k, maze[i][j] - '0');
 46         }
 47     }
 48     queue<point>myqueues;
 49     short oriLayout = (1 << q) - 1;
 50     myqueues.push(point(startx, starty, 0, 0, 0,oriLayout));
 51     memset(flags, 0, sizeof(flags));
 52     flags[startx][starty][0][oriLayout] = 1;
 53     while (!myqueues.empty()) {
 54         point top = myqueues.front();
 55         myqueues.pop();
 56         if (maze[top.x][top.y] == 'T'&&top.keys==k) {
 57             cout << top.steps << endl;
 58             break;
 59         }
 60         if (maze[top.x][top.y] == 'G'&&top.fighted == 0) {
 61             int index = findTraps(top.x, top.y);
 62             short layout = top.layout&(~(1 << index));
 63             myqueues.push(point(top.x, top.y, top.keys, 1, top.steps + 1, layout));
 64             flags[top.x][top.y][top.keys][layout] = 1;
 65             continue;
 66         }
 67         for (int i = 0; i < 4; i++) {
 68             int tx = top.x + dx[i];
 69             int ty = top.y + dy[i];
 70             if (tx < 0 || tx >= n || ty < 0 || ty >= m)
 71                 continue;
 72             if (maze[tx][ty] == 'X')
 73                 continue;
 74             else if (maze[tx][ty] == 'G') {
 75                 if (flags[tx][ty][top.keys][top.layout])
 76                     continue;
 77                 int index = findTraps(tx, ty);
 78                 if ((top.layout >> index) & 1) //还没打
 79                     myqueues.push(point(tx, ty, top.keys, 0, top.steps + 1, top.layout));
 80                 else
 81                     myqueues.push(point(tx, ty, top.keys, 1, top.steps + 1, top.layout));
 82                 flags[tx][ty][top.keys][top.layout] = 1;
 83             }
 84             else if (maze[tx][ty] == '.'||maze[tx][ty]=='S'||maze[tx][ty]=='T') {
 85                 if (flags[tx][ty][top.keys][top.layout])
 86                     continue;
 87                 myqueues.push(point(tx, ty, top.keys, 0, top.steps + 1, top.layout));
 88                 flags[tx][ty][top.keys][top.layout] = 1;
 89             }
 90             else {
 91                 int key = maze[tx][ty] - '0';
 92                 if (key == top.keys + 1) {
 93                     if (flags[tx][ty][key][top.layout])
 94                         continue;
 95                     myqueues.push(point(tx, ty, key, 0, top.steps + 1, top.layout));
 96                     flags[tx][ty][key][top.layout] = 1;
 97                 }
 98                 else {
 99                     if (flags[tx][ty][top.keys][top.layout])
100                         continue;
101                     myqueues.push(point(tx, ty, top.keys, 0, top.steps + 1, top.layout));
102                     flags[tx][ty][top.keys][top.layout] = 1;
103                 }
104             }
105         }
106     }
107     return 0;
108 }

 

posted @ 2021-07-21 11:17  永远是个小孩子  阅读(459)  评论(0编辑  收藏  举报