题意:有一个N*M的图,图上有这样的几种情况:
- ‘#’,此点为不可达到的点
- 小写字母,此点有陷进,进去一次就会扣(小写字母-'a'+1)的血
- 大写字母,有怪兽,如果你走到了怪兽点的毗邻的一个点,怪兽就会冲过来打你了,然后怪兽就死了,于是你会扣(大写字母-'A'+1)的血
- 其他情况是安全的
题目要我们求的是:扣血最少的情况下的最短路径。
于是,就需要考虑一点,就是怪兽你打过一次就打死了,所以再经过这附近的点就不需要再打它了,又有很明显一点就是走回头路肯定不是最优的,所以肯定是走过不再回来了的。
根据以上的信息,我们如此处理:
分类讨论:怪物节点与非怪物节点。
如果它是怪物节点,那么我们需要跳过它,怪物节点有上下左右四个毗邻的方向点,那么每个方向的点向另外三个方向的点各自建一条路径长度为2的,扣血值为终点需要受到的怪兽伤害的值,其中需要避免在起点附近的怪兽造成的旧伤害。
否则,它是非怪物节点,那么直接考虑它到毗邻的非怪物节点的情况了,为什么不考虑它到毗邻的怪物节点的情况呢?上面已经考虑过了。所以,直接考虑为长度为1,扣血值为终点受到怪物伤害的值,这样的一条边。
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <string> 5 #include <cstring> 6 #include <algorithm> 7 #include <limits> 8 #include <vector> 9 #include <stack> 10 #include <queue> 11 #include <set> 12 #include <map> 13 #include <bitset> 14 #include <unordered_map> 15 #include <unordered_set> 16 #define lowbit(x) ( x&(-x) ) 17 #define pi 3.141592653589793 18 #define e 2.718281828459045 19 #define INF 0x3f3f3f3f 20 #define HalF (l + r)>>1 21 #define lsn rt<<1 22 #define rsn rt<<1|1 23 #define Lson lsn, l, mid 24 #define Rson rsn, mid+1, r 25 #define QL Lson, ql, qr 26 #define QR Rson, ql, qr 27 #define myself rt, l, r 28 #define pii pair<int, int> 29 #define MP(a, b) make_pair(a, b) 30 using namespace std; 31 typedef unsigned long long ull; 32 typedef unsigned int uit; 33 typedef long long ll; 34 const int dir[4][2] = 35 { 36 -1, 0, 37 0, -1, 38 0, 1, 39 1, 0 40 }; 41 const int maxN = 505; 42 int N, M; 43 char mp[maxN][maxN]; 44 inline bool In_Map(int x, int y) { return x >= 1 && y>= 1 && x <= N && y <= M && mp[x][y] ^ '#'; } 45 struct Edge 46 { 47 int nx, ny, hp, step; 48 Edge(int a=0, int b=0, int c=0, int d=0):nx(a), ny(b), hp(c), step(d) {} 49 }; 50 vector<Edge> to[maxN][maxN]; 51 void addEddge(int x, int y, int nx, int ny, int hp, int step) { to[x][y].push_back(Edge(nx, ny, hp, step)); } 52 void Creat_Graph() 53 { 54 for(int x=1; x<=N; x++) 55 { 56 for(int y=1; y<=M; y++) 57 { 58 if(!In_Map(x, y)) continue; 59 if(isupper(mp[x][y])) 60 { 61 for(int i=0, x1, y1; i<4; i++) 62 { 63 x1 = x + dir[i][0]; y1 = y + dir[i][1]; 64 if(!In_Map(x1, y1)) continue; 65 for(int j=0, x2, y2, hp; j<4; j++) 66 { 67 if(i == j) continue; 68 x2 = x + dir[j][0]; y2 = y + dir[j][1]; 69 if(!In_Map(x2, y2)) continue; 70 hp = 0; 71 for(int k=0, x3, y3; k<4; k++) 72 { 73 x3 = x2 + dir[k][0]; y3 = y2 + dir[k][1]; 74 if(!In_Map(x3, y3)) continue; 75 if(isupper(mp[x3][y3]) && abs(x3 - x1) + abs(y3 - y1) > 1) hp += mp[x3][y3] - 'A' + 1; 76 } 77 addEddge(x1, y1, x2, y2, hp, 2); 78 } 79 } 80 } 81 else 82 { 83 for(int i=0, x1, y1, hp; i<4; i++) 84 { 85 x1 = x + dir[i][0]; y1 = y + dir[i][1]; 86 if(!In_Map(x1, y1) || isupper(mp[x1][y1])) continue; 87 hp = 0; 88 for(int j=0, x2, y2; j<4; j++) 89 { 90 x2 = x1 + dir[j][0]; y2 = y1 + dir[j][1]; 91 if(!In_Map(x2, y2)) continue; 92 if(isupper(mp[x2][y2])) hp += mp[x2][y2] - 'A' + 1; 93 } 94 addEddge(x, y, x1, y1, hp, 1); 95 } 96 } 97 } 98 } 99 } 100 struct node 101 { 102 int x, y; pii val; 103 node(int a=0, int b=0, pii c=MP(0, 0)):x(a), y(b), val(c) {} 104 friend bool operator < (node e1, node e2) { return e1.val.first == e2.val.first ? e1.val.second > e2.val.second : e1.val.first > e2.val.first; } 105 } now; 106 priority_queue<node> Q; 107 int sx, sy, tx, ty; 108 pii dis[maxN][maxN]; 109 void Dijkstra() 110 { 111 while(!Q.empty()) Q.pop(); 112 for(int i=1; i<=N; i++) for(int j=1; j<=M; j++) dis[i][j] = MP(INF, INF); 113 dis[sx][sy] = MP(0, 0); 114 Q.push(node(sx, sy, MP(0, 0))); 115 int x, y, xx, yy; pii val, nex_val; 116 while(!Q.empty()) 117 { 118 now = Q.top(); Q.pop(); 119 x = now.x; y = now.y; val = now.val; 120 if(x == tx && y == ty) { printf("%d %d\n", now.val.first, now.val.second); return; } 121 if(dis[x][y] < now.val) continue; 122 for(Edge V : to[x][y]) 123 { 124 xx = V.nx; yy = V.ny; 125 nex_val.first = val.first + V.hp; 126 nex_val.second = val.second + V.step; 127 if(islower(mp[xx][yy])) nex_val.first += mp[xx][yy] - 'a' + 1; 128 if(dis[xx][yy] > nex_val) 129 { 130 dis[xx][yy] = nex_val; 131 Q.push(node(xx, yy, nex_val)); 132 } 133 } 134 } 135 } 136 int main() 137 { 138 int T; scanf("%d", &T); 139 while(T--) 140 { 141 scanf("%d%d", &N, &M); 142 scanf("%d%d%d%d", &sx, &sy, &tx, &ty); 143 for(int i=1; i<=N; i++) scanf("%s", mp[i] + 1); 144 for(int i=1; i<=N; i++) for(int j=1; j<=M; j++) to[i][j].clear(); 145 Creat_Graph(); 146 Dijkstra(); 147 } 148 return 0; 149 }