描述:
走迷宫,其中:
符号 | 消耗的时间 | 消耗的体力 |
. | 1 | 1 |
w | 2 | 2 |
m | 3 | 1 |
x | +∞ | +∞ |
输入:
0 < N、M < 20
Map
P(体力)
输出:
ans
————————————————————集训5.2的分割线————————————————————
思路:只是增加了一种状态:体力,将其纳入vis数组当中即可。注意不要回到起点。找到T不要退出BFS,要搜完整个队列,维护一个时间最短的答案。
代码如下:
/*
ID: j.sure.1
PROG:
LANG: C++
*/
/****************************************/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <string>
#include <iostream>
using namespace std;
/****************************************/
#define LIM (nx >= 0 && nx < n && ny >= 0 && ny < m)
const int N = 25;
int n, m, sx, sy, ex, ey, P, minX = 2e9;
const int d[][2] = {{0, -1}, {1, 0}, {0, 1}, {-1, 0}};
char mat[N][N];
bool vis[N][N][1205];
struct Node
{
int x, y;
int hp, step;
};
queue <Node> q;
void bfs()
{
Node t;
t.x = sx; t.y = sy; t.hp = P; t.step = 0;
q.push(t);
while(!q.empty()) {
t = q.front();
q.pop();
for(int dd = 0; dd < 4; dd++) {
Node nt;
int &nx = nt.x = t.x + d[dd][0];
int &ny = nt.y = t.y + d[dd][1];
if(!LIM || mat[nx][ny] == 'x' || mat[nx][ny] == 'S')
continue;
int &np = nt.hp = t.hp, &ns = nt.step = t.step;
bool ok = false;
switch(mat[nx][ny])
{
case '.': np--; ns++; break;
case 'w': np-=2; ns+=2; break;
case 'm': np--; ns+=3; break;
case 'T': np--; ns++; ok = true; break;
}
if(!vis[nx][ny][np] && np > 0) {
vis[nx][ny][np] = true;
q.push(nt);
//printf("[%d, %d]->[%d, %d] at hp = %d & t = %d\n", t.x, t.y, nx, ny, np, ns);
if(ok) minX = min(minX, ns);
}
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("Intelligence.in", "r", stdin);
// freopen(".out", "w", stdout);
#endif
while(~scanf("%d%d", &n, &m), n||m) {
getchar();
memset(vis, 0, sizeof(vis));
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
scanf("%c", &mat[i][j]);
switch(mat[i][j])
{
case 'S': sx = i; sy = j; break;
case 'T': ex = i; ey = j; break;
}
}
getchar();
}
scanf("%d", &P);
P = P < 1200 ? P : 1200;
bfs();
if(minX == 2e9)
puts("No");
else
printf("%d\n", minX);
}
return 0;
}