HDU - 5040 Instrusive 預處理 + bfs + 優先隊列

傳送門:HDU 5040

題意:給定一張圖,Matt要從M移動到T取偷東西,N,W,S,E表示這些位置有監控器,字母表示這些監控器的初始方向,並且每一秒順時針旋轉90度。現在Matt每移動一格需要花一秒,但是如果當前他所在的位置或者他要去的位置被監控器監視,那麼如果他要移動,就必須躲在箱子裏移動,時間需要花費3秒。或者也可以選擇不移動,躲在箱子裏1秒,問Matt最少花費多少時間移動到T。

思路:很明顯的bfs,就是題意很坑,一開始還以爲攝像頭第一秒照初始方向,最後才知道是從0秒開始計數的。。

我是預處理出來每個地方在第幾秒會被攝像頭照到(%4的循環),並狀壓存儲,然後就搜就行了,注意標記點的時候要進行3維標記,即記錄%4的每一種情況是否到過這個點。

代碼:

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int,int> P;
const int MAXN = 510;
int n, sr, sc, er, ec;
char mp[MAXN][MAXN];
int face[MAXN][MAXN];
void init()
{
	memset(face, 0, sizeof(face));
	for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= n; j++)
		{
			if(mp[i][j] == 'N')
			{
				face[i][j] = 15;
				face[i - 1][j] |= (1 << 0);
				face[i][j + 1] |= (1 << 1);
				face[i + 1][j] |= (1 << 2);
				face[i][j - 1] |= (1 << 3);
			}
			if(mp[i][j] == 'E')
			{
				face[i][j] = 15;
				face[i][j + 1] |= (1 << 0);
				face[i + 1][j] |= (1 << 1);
				face[i][j - 1] |= (1 << 2);
				face[i - 1][j] |= (1 << 3);
			}
			if(mp[i][j] == 'S')
			{
				face[i][j] = 15;
				face[i + 1][j] |= (1 << 0);
				face[i][j - 1] |= (1 << 1);
				face[i - 1][j] |= (1 << 2);
				face[i][j + 1] |= (1 << 3);
			}
			if(mp[i][j] == 'W')
			{
				face[i][j] = 15;
				face[i][j - 1] |= (1 << 0);
				face[i - 1][j] |= (1 << 1);
				face[i][j + 1] |= (1 << 2);
				face[i + 1][j] |= (1 << 3);
			}
		}
	}
}
struct node{
	int r, c, t;
	node(int _r = 0, int _c = 0, int _t = 0) : r(_r), c(_c), t(_t) {}
	bool operator < (node a) const
	{
		return t > a.t;
	}
};
priority_queue<node> que;
int go[4][2] = {1, 0, 0, 1, -1, 0, 0, -1};
bool vis[MAXN][MAXN][4];
inline bool valid(int i, int j)
{
	return (i <= n && i > 0 && j <= n && j > 0) && mp[i][j] != '#';
}
int bfs()
{
	while(!que.empty()) que.pop();
	memset(vis, 0, sizeof(vis));
	//int head, tail;
	//head = tail = 0;
	que.push(node(sr, sc, 0));
	while(!que.empty())
	{
		node u = que.top(), v; que.pop();
		if(u.r == er && u.c == ec) return u.t;
	//	cout << u.r << " " << u.c << " " << u.t << endl;
		if(!vis[u.r][u.c][(u.t + 1) & 3])//原地不動
		{
			vis[u.r][u.c][(u.t + 1) & 3] = 1;
			que.push(node(u.r, u.c, u.t + 1));
		}
		for(int i = 0; i < 4; i++)
		{
			v.r = u.r + go[i][0];
			v.c = u.c + go[i][1];
			v.t = u.t + 1;
			if(!valid(v.r, v.c)) continue;
			if(face[v.r][v.c] & (1 << (u.t & 3))) // 目標格子被監控 
			{
				v.t += 2;
				if(vis[v.r][v.c][v.t & 3]) continue;
				vis[v.r][v.c][v.t & 3] = 1;
				que.push(v);
			}
			else
			{
				if(face[u.r][u.c] & (1 << (u.t & 3))) // 當前格子被監控
				{
					v.t += 2;
					if(vis[v.r][v.c][v.t & 3]) continue;
					vis[v.r][v.c][v.t & 3] = 1;
					que.push(v);
				}
				else
				{
					if(vis[v.r][v.c][v.t & 3]) continue;
					vis[v.r][v.c][v.t & 3] = 1;
					que.push(v);
				}
			}
		}
	}
	return -1;
}
int main()
{
	int T, kase = 1;
	cin >> T;
	while(T--)
	{
		scanf("%d", &n);
		for(int i = 1; i <= n; i++)
		{
			scanf("%s", mp[i] + 1);
			for(int j = 1; j <= n; j++)
			{
				if(mp[i][j] == 'M')
				sr = i, sc = j;
				if(mp[i][j] == 'T')
				er = i, ec = j;
			}
		}
		init();
		int ans = bfs();
		printf("Case #%d: %d\n", kase++, ans);
	}	
 	return 0;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章