Google中国2014校园招聘笔试Round B China New Grad Test Problem D. Dragon Maze

Problem

You are the prince of Dragon Kingdom and your kingdom is in danger of running out of power. You must find power to save your kingdom and its people. An old legend states that power comes from a place known as Dragon Maze. Dragon Maze appears randomly out of nowhere without notice and suddenly disappears without warning. You know where Dragon Maze is now, so it is important you retrieve some power before it disappears.

Dragon Maze is a rectangular maze, an N x M grid of cells. The top left corner cell of the maze is (0,0) and the bottom right corner is (N-1, M-1). Each cell making up the maze can be either a dangerous place which you never escape after entering, or a safe place that contains a certain amount of power. The power in a safe cell is automatically gathered once you enter that cell, and can only be gathered once. Starting from a cell, you can walk up/down/left/right to adjacent cells with a single step.

Now you know where the entrance and exit cells are, that they are different, and that they are both safe cells. In order to get out of Dragon Maze before it disappears, you must walk from the entrance cell to the exit cell taking as few steps as possible. If there are multiple choices for the path you could take, you must choose the one on which you collect as much power as possible in order to save your kingdom.

Input

The first line of the input gives the number of test cases, T. T test cases follow.

Each test case starts with a line containing two integers N and M, which give the size of Dragon Maze as described above. The second line of each test case contains four integers enx, eny, exx, exy, describing the position of entrance cell (enx, eny) and exit cell (exx, exy). Then N lines follow and each line has M numbers, separated by spaces, describing the N x M cells of Dragon Maze from top to bottom. Each number for a cell is either -1, which indicates a cell is dangerous, or a positive integer, which indicates a safe cell containing a certain amount of power.

Output

For each test case, output one line containing "Case #x: y", where x is the case number (starting from 1). If it's possible for you to walk from the entrance to the exit, y should be the maximum total amount of power you can collect by taking the fewest steps possible. If you cannot walk from the entrance to the exit, y should be the string "Mission Impossible." (quotes for clarity). Please note that the judge requires an exact match, so any other output like "mission impossible." or "Mission Impossible" (which is missing the trailing period) will be judged incorrect.

Limits

The amount of power contained in each cell will not exceed 10,000.
1 ≤ T ≤ 30.
0 ≤ enx, exx < N.
0 ≤ eny, exy < M.

Small dataset

1 ≤ N, M ≤ 10.

Large dataset

1 ≤ N, M ≤ 100.

Sample


Input 
 

Output 
 
2
2 3
0 2 1 0
2 -1 5
3 -1 6
4 4
0 2 3 2
-1 1 1 2
1 1 1 1
2 -1 -1 1
1 1 1 1
Case #1: Mission Impossible.
Case #2: 7

类型:图论   难度:2

题意:一张n*m的图,图中-1表示不能走,其余格子内为正数,表示每格的能量,给出起点(sx,sy),终点(ex,ey),能向上下左右四个方向走,求最短路径(最少步数)上的能量和,若有多条路径,选能量和最大的。(注意是在最短路径中选能量最大的,不是最大能量路径选最短的)

分析:一开始习惯性的写了dfs的递归解法,但是发现不仅边界不好控制,而且很容易出错,时间复杂度还高。。。后来才发现bfs的思路更简单,且搜索次数更少,即mz矩阵存储图,用一个队列存储每一层的节点,按和起点距离由近到远依次入队,flag矩阵标记是否遍历,初始化为0,step矩阵标记步数,初始化为-1,pw矩阵记录从起点到当前点的能量和,初始化为-1,算法步骤如下:

(1)起点入队,标记step[sx][sy]为0,表示第0步,flag[sx][sy]为1,表示已遍历,pw[sx][sy]记为起点能量值

(2)若队列为空,返回-1,结束,否则进入(3)

(3)队头now出队,若是终点(ex,ey),返回pw[ex][ey],结束,否则进入(4)。

(4)遍历队头的四个方向的邻点next,若邻点next能量值是-1,或已经被遍历,则遍历下一个方向。

否则,更新步数,step[next.x][next.y] = min(step[next.x][next.y], step[now.x][now.y]+1),

若步数被更新了,再更新能量和,pw[next.x][next.y] = max(pw[next.x][next.y], mz[next.x][next.y] + pw[now.x][now.y])。

若是初次遍历next,next入队。

(5)返回(2)

 

由于只遍历了图中和起点连通的区域,复杂度不超过O(mn)

 

代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<vector>
using namespace std;

const int MAX = 110;
int n,m;
int sx,sy,ex,ey;
int mz[MAX][MAX];
int step[MAX][MAX],pw[MAX][MAX];
bool flag[MAX][MAX];
const int pa[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};

typedef struct 
{
	int x,y;
}point;
vector<point> qu;

int mmax(int i,int j)
{
	return (i>j)?i:j;
}

int mmin(int i,int j)
{
	if(i<0) return j;
	if(j<0) return i;
	return (i<j)?i:j;
} 

int cal(int x, int y)
{
	if(mz[x][y] < 0) return -1;
	
	point tmp;
	tmp.x = x;
	tmp.y = y;
	qu.push_back(tmp);
	
	step[x][y] = 0;
	pw[x][y] = mz[x][y];
	
	while(!qu.empty())
	{
		point now;
		now = qu.front();
		qu.erase(qu.begin());
		flag[now.x][now.y] = 1;
		
		if(now.x == ex && now.y == ey)
			break;
		
		for(int i=0; i<4; i++)
		{
			point next;
			next.x = now.x + pa[i][0];
			next.y = now.y + pa[i][1];
			
			if(mz[next.x][next.y]<0 || flag[next.x][next.y])
				continue;
			
			if(step[next.x][next.y]<0 || step[now.x][now.y]+1 <= step[next.x][next.y])
			{
				if(step[next.x][next.y]<0) 
					qu.push_back(next);
				step[next.x][next.y] = step[now.x][now.y]+1;
				if(pw[next.x][next.y] < mz[next.x][next.y] + pw[now.x][now.y])
					pw[next.x][next.y] = mz[next.x][next.y] + pw[now.x][now.y];
			}
		}
	}
	
	return pw[ex][ey];
}

int main()
{
	freopen("D-large-practice.in","r",stdin);
	freopen("D-large-practice.out","w",stdout);
	
	int t;
	scanf("%d",&t);
	
	for(int cnt=1; cnt<=t; cnt++)
	{
		scanf("%d%d%d%d%d%d",&n,&m,&sx,&sy,&ex,&ey);
		sx++;
		sy++;
		ex++;
		ey++;
		memset(mz,-1,sizeof(mz));
		memset(step,-1,sizeof(step));
		memset(pw,-1,sizeof(pw));
		memset(flag,0,sizeof(flag));
		qu.clear();
		
		for(int i=1; i<=n; i++)
			for(int j=1; j<=m; j++)
			{
				scanf("%d",&mz[i][j]);
			}
				
		int ans = cal(sx,sy);
		if(ans < 0) printf("Case #%d: Mission Impossible.\n",cnt);
		else printf("Case #%d: %d\n",cnt,ans);
	}
}


 

 

 

 

你可能感兴趣的:(Google,图论,校园招聘,笔试)