题目:
宝宝和妈妈参加亲子游戏,在一个二维矩阵(N*N)的格子地图上,宝宝和妈妈抽签决定各自的位置,地图上每个格子有不同的糖果数量,部分格子有障碍物。
游戏规则是妈妈必须在最短的时间(每个单位时间只能走一步)到达宝宝的位置,路上的所有糖果都可以拿走,不能走障碍物的格子,只能上下左右走。
请问妈妈在最短到达宝宝位置的时间内最多拿到多少糖果(优先考虑最短时间到达的情况下尽可能多拿糖果)。
思路:
/** * 1、先创建一个含糖果点类(坐标、妈妈到达步数step、已获取的糖果数) * 2、创建一个位置数组points,并进行初始化 * 3、初始化妈妈的步数,并将妈妈的点对象加入队列 * 4、循环遍历队列,直到队列为空;从上、下、左、右(顺序不固定)分别找儿子的位置,如果妈妈走的下一个位置,与那个位置的路径相比更短,那就说明此时妈妈走的就是更优解,所以更新那个位置的步数和糖果数;如果路径相等,则取较大的糖果数对应的位置。并将下一个点位置放入队列中,继续扩张广度遍历。 * 5、如果妈妈找到儿子的位置,直接返回糖果数;否则返回-1,没有找到。 */
题解:
class CandyPoint{
int x,y,candy,step;
public CandyPoint(int x, int y, int candy, int step){
this.x = x;
this.y = y;
this.candy = candy;
this.step = step;
}
}
public class T01CandyGame {
//定义一个上、下、左、右位置的int[4][2]数组
public int[][] DIRECTIONS = {{0,1},{0,-1},{-1,0},{1,0}};
public int minPathAndMaxCandy(int[][] grid, CandyPoint mon, CandyPoint kid){
int n = grid.length;
CandyPoint[][] points = new CandyPoint[n][n];
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
points[i][j] = new CandyPoint(i,j,grid[i][j],Integer.MAX_VALUE);
}
}
//需要一个队列记录需访问的位置
Queue<CandyPoint> queue = new PriorityQueue<>(Comparator.comparingInt(a->a.candy));
//初始化,从妈妈位置开始遍历
mon.step=0;
queue.offer(mon);
//广度优先遍历糖果数组
while(!queue.isEmpty()){
CandyPoint current = queue.poll();
//妈妈找到儿子位置
if(current.x==kid.x && current.y==kid.y){
return current.candy;
}
for(int[] direction:DIRECTIONS){
int newX = current.x + direction[0];
int newY = current.y + direction[1];
if(newX>=0 && newX<n && newY >=0 && newY<n && grid[newX][newY]!=-1){
CandyPoint next = points[newX][newY];
//妈妈走到下一步,步数+1,糖果数累加
int newStep = current.step+1;
int newCandy = current.candy + grid[newX][newY]; //注意这里不能用next.candy,points数组中元素会重复访问,且元素的candy会叠加
//取较短的路径,或者路径相同,糖果数较多的位置
if(newStep<next.step || newStep==next.step && newCandy>next.candy){
next.candy = newCandy;
next.step = newStep;
queue.offer(next);
}
}
}
}
return -1;
}
}
马上要参加机考了,欢迎评论区交流,欢迎评论区提供其它解题思路(或代码)。