HDU5040 Instrusive,bfs+优先队列

1.题目叙述:

Instrusive

Time Limit: 3000/1500 MS(Java/Others)    Memory Limit: 262144/262144 K(Java/Others)
Total Submission(s): 1828    Accepted Submission(s): 545


Problem Description

The legendarymercenary Solid Matt gets a classic mission: infiltrate a military base.

The military base can be seen as an N * N grid. Matt's target is in one of thegrids and Matt is now in another grid.

In normal case, Matt can move from a grid to one of the four neighbor grids ina second. But this mission is not easy.

Around the military base there are fences, Matt can't get out of the base.

There are some grids filled with obstacles and Matt can't move into thesegrids.

There are also some surveillance cameras in the grids. Every camera is facingone of the four direction at first, but for every second, they will rotate 90degree clockwisely. Every camera's sight range is 2, which means that if Mattis in the same grid as the camera, or in the grid that the camera is facing, hewill be seen immediately and the mission will fail.

Matt has a special equipment to sneak: a cardbox. Matt can hide himself in thecard box and move without being noticed. But In this situation, Matt will haveto use 3 seconds to move 1 grid. Matt can also just hide in the cardbox withoutmoving. The time to hide and the time to get out of the cardbox can be ignored.

Matt can't take the risk of being noticed, so he can't move without cardboxinto a grid which is now insight of cameras or from a grid which is now insightof cameras. What's more, Matt may be in the cardbox at the beginning.

As a live legend, Matt wants to complete the mission in the shortest time.

 

 

Input

The first line ofthe input contains an integer T, denoting the number of testcases. Then T testcases follow.

For each test cases, the first line contains one integer:N(1<=N<=500)

In the following N lines, each line contains N characters, indicating thegrids.

There will be the following characters:

● '.' for empty 
● '#' for obstacle 
● 'N' for camera facing north 
● 'W' for camera facing west 
● 'S' for camera facing south 
● 'E' for camera facing east 
● 'T' for target 
● 'M' for Matt

 

 

Output

For each testcase, output one line "Case #x: y", where x is the case number(starting from 1) and y is the answer.

If Matt cannot complete the mission, output '-1'.

 

 

Sample Input

2

3

M..

.N.

..T

3

M..

###

..T

 

 

Sample Output

Case #1: 5

Case #2: -1

 

 

Source

2014 ACM/ICPCAsia Regional Beijing Online

 

 

Recommend

hujie   |   Wehave carefully selected several similar problems for you:  6014 6013 6012 6011 6010 

2.题目大意:一个n*n的矩阵,#表示墙,M表示人Matt,T表示目标,M要到T点去,#不可以走,路途有摄像头,如果被摄像头发现任务就是败了,摄像头可以看到两个格子的区域,一是自身所在区域,二是它面对方向的位子,摄像头可以转动,1秒转动一次,有四个方向N,S,W,E,表示 上北,下南,作西,右东,Matt有一个神秘盒子,他可以躲到里面不让摄像头发现,在盒子中移动每一格要花费3秒,不带盒子每移动一格花费1秒,也可以在盒子待着不动;问Matt到达T花费最短时间是多少,如果不能完成任务输出-1;

3.思路解决:

bfs搜索+优先队列,用一个三维数组表示状态,因为一个位子有四种状态,也就是四个时间点,(所有摄像头都转,每4秒一个周期啊),也就是Matt最多在一个位子呆4秒,进行bfs时,要走的下一点位置要考虑4种情况:1 有摄像头,2被摄像头照射,3空地且不被摄像头照射,4是# 墙不可以通过;  策略:遇到情况1,要走,时间加3,第二种情况,要停等待一秒,时间加1位置不变,情况3,走,时间加1 ,情况4可以直接跳过不操作;

对于摄像头转向问题,用时间%4就可以计算出当前摄像头方向了;对于四种情况直接开一个int数组,[110],初始化为-1,然后用W,E,S,N的ASCII作为下标,然后赋值也是相当方便的;考虑四个方向赋问题,可以结合搜索顺序,使得搜索顺序与方向代表值一一对应,举一个例子,我第一次向下S搜索,那么我要让‘N'赋值为0,也就是当搜索顺序值与方向值相等时刚好该位置被摄像图照射;

4.Ac代码:

#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
#define N 505
#define INF 0x3f3f3f3f
using namespace std;
char mp[N][N];
int vis[N][N];
int dir[4][2] = { {0, 1}, {1, 0}, {-1, 0}, {0, -1} };
int n, ans, sx, sy, ex, ey;
struct node
{
	int x, y, time;
	friend bool operator< (node a, node b)
	{
		return a.time > b.time;
	}
};
bool check(int x, int y, int time)
{
	if (mp[x][y] != '.') 
		return 0;

	if (x - 1 >= 0 && mp[x - 1][y] != '.')
	{
		switch (time)
		{
		case 0:
			if (mp[x - 1][y] == 'S') 
				return 0; 
			break;
		case 1:
			if (mp[x - 1][y] == 'E') 
				return 0; 
			break;
		case 2:
			if (mp[x - 1][y] == 'N') 
				return 0; 
			break;
		case 3:
			if (mp[x - 1][y] == 'W') 
				return 0; 
			break;
		}
	}

	if (x + 1 < n && mp[x + 1][y] != '.')
	{
		switch (time)
		{
		case 0:
			if (mp[x + 1][y] == 'N') 
				return 0; 
			break;
		case 1:
			if (mp[x + 1][y] == 'W') 
				return 0; 
			break;
		case 2:
			if (mp[x + 1][y] == 'S') 
				return 0; 
			break;
		case 3:
			if (mp[x + 1][y] == 'E') 
				return 0; 
			break;
		}
	}

	if (y - 1 >= 0 && mp[x][y - 1] != '.')
	{
		switch (time)
		{
		case 0:
			if (mp[x][y - 1] == 'E') 
				return 0; 
			break;
		case 1:
			if (mp[x][y - 1] == 'N') 
				return 0; 
			break;
		case 2:
			if (mp[x][y - 1] == 'W') 
				return 0; 
			break;
		case 3:
			if (mp[x][y - 1] == 'S') 
				return 0; 
			break;
		}
	}

	if (y + 1 < n && mp[x][y + 1] != '.')
	{
		switch (time)
		{
		case 0:
			if (mp[x][y + 1] == 'W') 
				return 0; 
			break;
		case 1:
			if (mp[x][y + 1] == 'S') 
				return 0; 
			break;
		case 2:
			if (mp[x][y + 1] == 'E') 
				return 0; 
			break;
		case 3:
			if (mp[x][y + 1] == 'N') 
				return 0; 
			break;
		}
	}
	return 1;
}
void bfs()
{
	node cur, now;
	priority_queue
       
       
         q; cur.x = sx; cur.y = sy; cur.time = 0; vis[sx][sy] = 0; q.push(cur); while (!q.empty()) { cur = q.top(); q.pop(); if (cur.x == ex && cur.y == ey) ans = min(ans, cur.time); for (int i = 0; i < 4; i++) { int dx = cur.x + dir[i][0]; int dy = cur.y + dir[i][1]; int time = cur.time + 1; if (mp[dx][dy] == '#' || dx < 0 || dx >= n || dy < 0 || dy >= n) continue; if (mp[dx][dy] == '.') { int flag = 0; for (int j = 0; j < 3; j++) { int t = (j + time - 1) % 4; if (check(dx, dy, t) && check(dx - dir[i][0], dy - dir[i][1], t) && time + j < vis[dx][dy]) { time += j; vis[dx][dy] = time; now.x = dx; now.y = dy; now.time = time; q.push(now); flag = 1; break; } } if (!flag) //躲在盒子里 { time += 2; if (time < vis[dx][dy]) { vis[dx][dy] = time; now.x = dx; now.y = dy; now.time = time; q.push(now); } } } else // 探照灯 { time += 2; if (time < vis[dx][dy]) { vis[dx][dy] = time; now.x = dx; now.y = dy; now.time = time; q.push(now); } } } } } int main() { int t, kase = 1; scanf("%d", &t); while (t--) { scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%s", mp[i]); for (int j = 0; j < n; j++) if (mp[i][j] == 'M') { sx = i; sy = j; mp[i][j] = '.'; } else if (mp[i][j] == 'T') { ex = i; ey = j; mp[i][j] = '.'; } } memset(vis, INF, sizeof(vis)); ans = INF; bfs(); printf("Case #%d: %d\n", kase++, ans == INF ? -1 : ans); } return 0; } 
       
      
      
     
     
    
    
   
   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值