一.题目链接:
ZOJ-3478
二.题目大意:
给你一个 10 × 15 的图,图中包括以下符号.
'H' :终点
'X' :墙
'O' :蜘蛛网
'.' :空地
再给出两只异性企鹅各自的起点坐标.
只可以选取一只企鹅进行操作.
一只企鹅进行运动时,另一只企鹅的运动与这只企鹅左右对称运动.
企鹅运动无限制,当企鹅要走进墙时,则这只企鹅不动.
当一只企鹅走进蜘蛛网时,此企鹅不再移动.
直到另一只企鹅到达 此企鹅 的临方格并花费 11 点时间,才可以将此企鹅救到另一只企鹅的位置.
普通移动时,花费 5 时间.
当操作企鹅被困时,移动花费 3 时间.
当非操作企鹅被困时,移动花费 2 时间.
问两只企鹅是否能走到终点
如果不能,则输出 -1
否则,输出最小花费时间.
三.分析:
BFS + 优先队列优化 + 松弛原理 即可
注意:当此企鹅被困在蜘蛛网时,另一只企鹅即使与此企鹅相邻,也并一定要将此企鹅救出来 因为这里一直WA
四.代码实现:
#include <set>
#include <map>
#include <ctime>
#include <queue>
#include <cmath>
#include <stack>
#include <vector>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define eps 1e-6
#define pi acos(-1.0)
#define ll long long int
using namespace std;
const int inf = 0x3f3f3f3f;
struct node
{
int x1, y1;
int x2, y2;
int step;
};
char mp[20][20];
int vis[20][20][20][20];
int Move[2][4][2] = {-1, 0, 1, 0, 0, -1, 0, 1, -1, 0, 1, 0, 0, 1, 0, -1};
struct cmp
{
bool operator()(node a, node b)
{
return a.step > b.step;
}
};
node fun(node cur, int dir, int i)
{
node tmp = cur;
if(dir == 1)
{
tmp.x2 += Move[1][i][0];
tmp.y2 += Move[1][i][1];
if(tmp.x2 < 0 || tmp.x2 >= 10 || tmp.y2 < 0 || tmp.y2 >= 15 || mp[tmp.x2][tmp.y2] == 'X')
tmp = cur;
return tmp;
}
else if(dir == 2)
{
tmp.x1 += Move[0][i][0];
tmp.y1 += Move[0][i][1];
if(tmp.x1 < 0 || tmp.x1 >= 10 || tmp.y1 < 0 || tmp.y1 >= 15 || mp[tmp.x1][tmp.y1] == 'X')
tmp = cur;
return tmp;
}
else if(dir == 3)
{
tmp.x1 += Move[0][i][0];
tmp.y1 += Move[0][i][1];
tmp.x2 += Move[1][i][0];
tmp.y2 += Move[1][i][1];
if(tmp.x1 < 0 || tmp.x1 >= 10 || tmp.y1 < 0 || tmp.y1 >= 15 || mp[tmp.x1][tmp.y1] == 'X')
{
tmp.x1 = cur.x1;
tmp.y1 = cur.y1;
}
if(tmp.x2 < 0 || tmp.x2 >= 10 || tmp.y2 < 0 || tmp.y2 >= 15 || mp[tmp.x2][tmp.y2] == 'X')
{
tmp.x2 = cur.x2;
tmp.y2 = cur.y2;
}
return tmp;
}
}
int bfs(node cur)
{
memset(vis, -1, sizeof(vis));
cur.step = 0;
vis[cur.x1][cur.y1][cur.x2][cur.y2] = 1;
priority_queue <node, vector<node>, cmp> q;
q.push(cur);
node p, t;
while(!q.empty())
{
p = q.top();
q.pop();
if(p.x1 == p.x2 && p.y1 == p.y2 && mp[p.x1][p.y1] == 'H')
return p.step;
if(mp[p.x1][p.y1] == 'O' && mp[p.x2][p.y2] == 'O')
continue;
if(mp[p.x1][p.y1] == 'O')
{
if((int)abs(p.x1 - p.x2) + (int)abs(p.y1 - p.y2) == 1)
{
t = p;
t.x1 = t.x2;
t.y1 = t.y2;
t.step += 11;
if(vis[t.x1][t.y1][t.x2][t.y2] == -1 || vis[t.x1][t.y1][t.x2][t.y2] > t.step)
{
vis[t.x1][t.y1][t.x2][t.y2] = t.step;
q.push(t);
}
}
for(int i = 0; i < 4; ++i)
{
t = p;
t = fun(t, 1, i);
t.step += 3;
if(vis[t.x1][t.y1][t.x2][t.y2] == -1 || vis[t.x1][t.y1][t.x2][t.y2] > t.step)
{
vis[t.x1][t.y1][t.x2][t.y2] = t.step;
q.push(t);
}
}
}
else if(mp[p.x2][p.y2] == 'O')
{
if((int)abs(p.x1 - p.x2) + (int)abs(p.y1 - p.y2) == 1)
{
t = p;
t.x2 = t.x1;
t.y2 = t.y1;
t.step += 11;
if(vis[t.x1][t.y1][t.x2][t.y2] == -1 || vis[t.x1][t.y1][t.x2][t.y2] > t.step)
{
vis[t.x1][t.y1][t.x2][t.y2] = t.step;
q.push(t);
}
}
for(int i = 0; i < 4; ++i)
{
t = p;
t = fun(t, 2, i);
t.step += 2;
if(vis[t.x1][t.y1][t.x2][t.y2] == -1 || vis[t.x1][t.y1][t.x2][t.y2] > t.step)
{
vis[t.x1][t.y1][t.x2][t.y2] = t.step;
q.push(t);
}
}
}
else
{
for(int i = 0; i < 4; ++i)
{
t = p;
t = fun(t, 3, i);
t.step += 5;
if(vis[t.x1][t.y1][t.x2][t.y2] == -1 || vis[t.x1][t.y1][t.x2][t.y2] > t.step)
{
vis[t.x1][t.y1][t.x2][t.y2] = t.step;
q.push(t);
}
}
}
}
return inf;
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
for(int i = 0; i < 10; ++i)
{
getchar();
for(int j = 0; j < 15; ++j)
scanf("%c", &mp[i][j]);
}
struct node cur;
scanf("%d %d %d %d", &cur.x1, &cur.y1, &cur.x2, &cur.y2);
getchar();
cur.x1--;
cur.y1--;
cur.x2--;
cur.y2--;
int ans1 = bfs(cur);
swap(cur.x1, cur.x2);
swap(cur.y1, cur.y2);
int ans2 = bfs(cur);
int ans = min(ans1, ans2);
if(ans == inf)
printf("-1\n");
else
printf("%d\n", ans);
}
return 0;
}