算法

亲子游戏

2025-10-30  本文已影响0人  何以解君愁

 宝宝和妈妈参加亲子游戏,在一个二维矩阵(N*N)的格子地图上,宝宝和妈妈抽签决定各自的位置,地图上每个格子有不同的糖果数量,部分格子有障碍物。
 游戏规则是妈妈必须在最短的时间(每个单位时间只能走一步)到达宝宝的位置,路上的所有糖果都可以拿走,不能走障碍物的格子,只能上下左右走。
 请问妈妈在最短到达宝宝位置的时间内最多拿到多少糖果(优先考虑最短时间到达的情况下尽可能多拿糖果)。
 输入描述:第一行输入为N(N <= 50),N标识二维矩阵的大小 之后N行,每行有N个值,表格矩阵每个位置的值
 其中:
  -3:妈妈
  -2:宝宝
  -1:障碍
  >=0:糖果数(0表示没有糖果,但是可以走)
 输出描述:输出妈妈在最短到达宝宝位置的时间内最多拿到多少糖果,行末无多余空格

完成大部分的简单实现

import java.util.*;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[][] nn = new int[n][n];
        int[][] dp = new int[n][n]; // 记录到达每个位置的最大和
        boolean[][] visited = new boolean[n][n]; // 记录是否访问过
        
        // 初始化dp为最小值
        for(int i = 0; i < n; i++){
            Arrays.fill(dp[i], Integer.MIN_VALUE);
        }
        
        Queue<Integer> queue = new LinkedList<>();
        
        for(int i = 0; i < n; i++){
            for(int j = 0; j < n; j++){
                int m = sc.nextInt();
                nn[i][j] = m;
                if(m == -3){
                    // 起点,和为0
                    dp[i][j] = 0;
                    visited[i][j] = true;
                    queue.offer(i * n + j);
                }
            }
        }
        
        int total = -1;
        boolean found = false;
        
        while(!queue.isEmpty() && !found){
            int size = queue.size();
            
            for(int i = 0; i < size && !found; i++){
                int index = queue.poll();
                int row = index / n;
                int col = index % n;
                int currentSum = dp[row][col];
                
                // 上
                if(row - 1 >= 0 && nn[row - 1][col] != -1 && !visited[row - 1][col]){
                    int newSum = currentSum;
                    if(nn[row - 1][col] != -2){
                        newSum += Math.max(0, nn[row - 1][col]); // 只加非负值
                    }
                    
                    if(nn[row - 1][col] == -2){
                        total = Math.max(total, newSum);
                        found = true;
                    } else {
                        dp[row - 1][col] = newSum;
                        visited[row - 1][col] = true;
                        queue.offer((row - 1) * n + col);
                    }
                }
                
                // 下
                if(row + 1 < n && nn[row + 1][col] != -1 && !visited[row + 1][col]){
                    int newSum = currentSum;
                    if(nn[row + 1][col] != -2){
                        newSum += Math.max(0, nn[row + 1][col]);
                    }
                    
                    if(nn[row + 1][col] == -2){
                        total = Math.max(total, newSum);
                        found = true;
                    } else {
                        dp[row + 1][col] = newSum;
                        visited[row + 1][col] = true;
                        queue.offer((row + 1) * n + col);
                    }
                }
                
                // 左
                if(col - 1 >= 0 && nn[row][col - 1] != -1 && !visited[row][col - 1]){
                    int newSum = currentSum;
                    if(nn[row][col - 1] != -2){
                        newSum += Math.max(0, nn[row][col - 1]);
                    }
                    
                    if(nn[row][col - 1] == -2){
                        total = Math.max(total, newSum);
                        found = true;
                    } else {
                        dp[row][col - 1] = newSum;
                        visited[row][col - 1] = true;
                        queue.offer(row * n + col - 1);
                    }
                }
                
                // 右
                if(col + 1 < n && nn[row][col + 1] != -1 && !visited[row][col + 1]){
                    int newSum = currentSum;
                    if(nn[row][col + 1] != -2){
                        newSum += Math.max(0, nn[row][col + 1]);
                    }
                    
                    if(nn[row][col + 1] == -2){
                        total = Math.max(total, newSum);
                        found = true;
                    } else {
                        dp[row][col + 1] = newSum;
                        visited[row][col + 1] = true;
                        queue.offer(row * n + col + 1);
                    }
                }
            }
        }
        
        System.out.print(total);
    }
}

完全实现

import java.util.*;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[][] nn = new int[n][n];
        
        // 记录到达每个位置的最大和
        int[][] maxSum = new int[n][n];
        // 记录到达每个位置的最短距离
        int[][] dist = new int[n][n];
        
        // 初始化数组
        for(int i = 0; i < n; i++){
            Arrays.fill(maxSum[i], Integer.MIN_VALUE);
            Arrays.fill(dist[i], Integer.MAX_VALUE);
        }
        
        Queue<Integer> queue = new LinkedList<>();
        int startX = -1, startY = -1;
        
        for(int i = 0; i < n; i++){
            for(int j = 0; j < n; j++){
                nn[i][j] = sc.nextInt();
                if(nn[i][j] == -3){
                    startX = i;
                    startY = j;
                    // 初始化起点的距离和和值
                    maxSum[i][j] = 0;
                    dist[i][j] = 0;
                    queue.offer(i * n + j);
                }
            }
        }
        
        // 将total改为-1,minDist记录最短距离
        int total = -1;
        int minDist = Integer.MAX_VALUE; // 记录找到的最短距离
        
        while(!queue.isEmpty()){
            int index = queue.poll();
            int row = index / n;
            int col = index % n;
            int currentDist = dist[row][col]; // 当前距离
            int currentSum = maxSum[row][col]; //当前和值
            
            // 如果当前距离已经大于已知的最短距离,跳过
            if(currentDist > minDist) continue;
            
            // 上
            if(row - 1 >= 0 && nn[row - 1][col] != -1){
                int newRow = row - 1;
                int newCol = col;
                int newDist = currentDist + 1; // 使用当前距离计算新距离
                int newSum = currentSum; // 使用当前和值计算新和值
                
                if(nn[newRow][newCol] != -2){
                    newSum += Math.max(0, nn[newRow][newCol]);
                }
                
                if(nn[newRow][newCol] == -2){
                    // 处理终点逻辑,考虑多条最短路径
                    if(newDist < minDist){
                        minDist = newDist;
                        total = newSum;
                    } else if(newDist == minDist){
                        total = Math.max(total, newSum);
                    }
                    continue;
                }
                
                // 更新普通格子的逻辑
                if(newDist < dist[newRow][newCol]){
                    // 找到更短路径,更新距离和和值
                    dist[newRow][newCol] = newDist;
                    maxSum[newRow][newCol] = newSum;
                    queue.offer(newRow * n + newCol);
                } else if(newDist == dist[newRow][newCol] && newSum > maxSum[newRow][newCol]){
                    // 相同距离但和值更大,更新和值
                    maxSum[newRow][newCol] = newSum;
                    queue.offer(newRow * n + newCol);
                }
            }
            
            // 下
            if(row + 1 < n && nn[row + 1][col] != -1){
                int newRow = row + 1;
                int newCol = col;
                int newDist = currentDist + 1;
                int newSum = currentSum;
                
                if(nn[newRow][newCol] != -2){
                    newSum += Math.max(0, nn[newRow][newCol]);
                }
                
                if(nn[newRow][newCol] == -2){
                    if(newDist < minDist){
                        minDist = newDist;
                        total = newSum;
                    } else if(newDist == minDist){
                        total = Math.max(total, newSum);
                    }
                    continue;
                }
                
                if(newDist < dist[newRow][newCol]){
                    dist[newRow][newCol] = newDist;
                    maxSum[newRow][newCol] = newSum;
                    queue.offer(newRow * n + newCol);
                } else if(newDist == dist[newRow][newCol] && newSum > maxSum[newRow][newCol]){
                    maxSum[newRow][newCol] = newSum;
                    queue.offer(newRow * n + newCol);
                }
            }
            
            // 左
            if(col - 1 >= 0 && nn[row][col - 1] != -1){
                int newRow = row;
                int newCol = col - 1;
                int newDist = currentDist + 1;
                int newSum = currentSum;
                
                if(nn[newRow][newCol] != -2){
                    newSum += Math.max(0, nn[newRow][newCol]);
                }
                
                if(nn[newRow][newCol] == -2){
                    if(newDist < minDist){
                        minDist = newDist;
                        total = newSum;
                    } else if(newDist == minDist){
                        total = Math.max(total, newSum);
                    }
                    continue;
                }
                
                if(newDist < dist[newRow][newCol]){
                    dist[newRow][newCol] = newDist;
                    maxSum[newRow][newCol] = newSum;
                    queue.offer(newRow * n + newCol);
                } else if(newDist == dist[newRow][newCol] && newSum > maxSum[newRow][newCol]){
                    maxSum[newRow][newCol] = newSum;
                    queue.offer(newRow * n + newCol);
                }
            }
            
            // 右
            if(col + 1 < n && nn[row][col + 1] != -1){
                int newRow = row;
                int newCol = col + 1;
                int newDist = currentDist + 1;
                int newSum = currentSum;
                
                if(nn[newRow][newCol] != -2){
                    newSum += Math.max(0, nn[newRow][newCol]);
                }
                
                if(nn[newRow][newCol] == -2){
                    if(newDist < minDist){
                        minDist = newDist;
                        total = newSum;
                    } else if(newDist == minDist){
                        total = Math.max(total, newSum);
                    }
                    continue;
                }
                
                if(newDist < dist[newRow][newCol]){
                    dist[newRow][newCol] = newDist;
                    maxSum[newRow][newCol] = newSum;
                    queue.offer(newRow * n + newCol);
                } else if(newDist == dist[newRow][newCol] && newSum > maxSum[newRow][newCol]){
                    maxSum[newRow][newCol] = newSum;
                    queue.offer(newRow * n + newCol);
                }
            }
        }
        
        System.out.print(total == -1 ? -1 : total);
    }
}
上一篇 下一篇

猜你喜欢

热点阅读