1 #include <cstdio> 2 #include <queue> 3 #include <set> 4 #include <cstring> 5 #include <string> 6 #define N 205 7 using namespace std; 8 int r, c, k; 9 char mp[N][N]; //地图位置 10 int tag[N][N]; //标志位,判断是否重复走 11 int door[N*N][2] = {}; //传送门位置 12 int door_cnt = 0; //有多少道传送门 13 int sx, sy, ex, ey; //起点和终点 14 int dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1}; //方向 15 typedef struct Node{ //每一个状态的结构体 16 int x, y, step; //位置和步数 17 //set<int> s; //开始是使用set保存宝石种类,发现0 > -1 为假,遂改为复杂形态 18 int ecnt; //宝石数量 19 bool e[5] = {}; //5种宝石是否被发现 20 Node(int x, int y, int step, int ecnt):x(x), y(y), step(step), ecnt(ecnt){}; //构造函数 21 }node; 22 23 bool judge(node nx){ //判断是否往下走 24 if(nx.x >= 0 && nx.x < r && nx.y >= 0 && nx.y < c && mp[nx.x][nx.y] != '#' && 25 nx.ecnt > tag[nx.x][nx.y]){ 26 return true; 27 } 28 return false; 29 } 30 int bfs(){ 31 node cur(sx, sy, 0, 0), next(sx, sy, 0, 0); //当前状态和下一下状态 32 queue<node> q; //队列 33 q.push(cur); 34 while(!q.empty()){ 35 cur = q.front(); 36 q.pop(); 37 if(cur.x == ex && cur.y == ey && cur.ecnt >= k){ //满足结束条件,返回 38 //printf("%d ", cur.s.size()); 39 return cur.step; 40 } 41 //printf("%d %d %d %d ", cur.x, cur.y, cur.ecnt, cur.step); 42 //getchar(); 43 for(int i = 0; i < 4; i++){ //上下左右试探 44 next.x = cur.x + dir[i][0]; 45 next.y = cur.y + dir[i][1]; 46 next.step = cur.step + 1; 47 next.ecnt = cur.ecnt; 48 memcpy(next.e, cur.e, 5); //计算下一步的所有数据 49 //printf("tag:%d %d %d ", next.ecnt > tag[next.x][next.y], next.ecnt, tag[next.x][next.y]); 50 if(judge(next)){ //判断是否可以继续往下走 51 tag[next.x][next.y] = next.ecnt; 52 if(isdigit(mp[next.x][next.y])){ //是否是宝石 53 int e_cnt = 0; 54 next.e[mp[next.x][next.y]-48] = true; 55 for(int j = 0; j < 5; j++){ 56 if(next.e[j]){ 57 e_cnt++; 58 } 59 } 60 next.ecnt = e_cnt; 61 q.push(next); 62 }else if(mp[next.x][next.y] == '$'){ //是否是传送门 63 for(int j = 0; j < door_cnt; j++){ 64 next.x = door[j][0]; 65 next.y = door[j][1]; 66 q.push(next); 67 } 68 }else if(mp[next.x][next.y] == 'E' || mp[next.x][next.y] == '.'){//正常道路 69 q.push(next); 70 } 71 } 72 } 73 } 74 return -1; 75 } 76 int main(){ 77 int t; 78 scanf("%d", &t); 79 while(t--){ 80 memset(tag, -1, sizeof(tag)); //初始化标志位 81 memset(mp, 0, sizeof(mp)); //初始化地图 82 door_cnt = 0; //传送门初始化 83 scanf("%d %d %d", &r, &c, &k); //地图大小和需要的宝石种类 84 getchar(); 85 for(int i = 0; i < r; i++){ //记录初始位置,结束位置和所有传送门 86 scanf("%s", mp[i]); 87 for(int j = 0; j < c; j++){ 88 switch(mp[i][j]){ 89 case 'S': 90 sx = i; 91 sy = j; 92 break; 93 case 'E': 94 ex = i; 95 ey = j; 96 break; 97 case '$': 98 door[door_cnt][0] = i; 99 door[door_cnt][1] = j; 100 door_cnt++; 101 break; 102 } 103 } 104 } 105 int cnt = bfs(); // bfs暴搜 106 if(cnt == -1){ 107 printf("oop!"); 108 }else{ 109 printf("%d ", cnt); 110 } 111 } 112 return 0; 113 }