acautomaton
acautomaton
发布于 2023-06-30 / 62 阅读
0
0

牛客小白月赛75-D-矩阵

题目描述

现有一个大小为n × m的二维矩阵,每个元素si,j可能是字符'0', '1'。
阿宁一开始站在(1,1),目标走到(n,m)。
假设当前在(x,y)一个相邻的位置(x',y'),上下左右相邻。可以进行一下其中一个行为,花费一个单位时间:

  1. 如果sx,y是'0',sx',y'是'1',可以从(x,y)走到(x',y')。

  2. 如果sx,y是'1',sx',y'是'0',可以从(x,y)走到(x',y')。

  3. 将sx',y'变成'1'。

  4. 将sx',y'变成'0'。

问阿宁从(1,1)走到(n,m)需要最少多少单位时间?

输入描述

第一行输入两个正整数n, m。
接下来输入n行,每行m个字符,字符仅包含'0'、'1'。
1 ≤ n,m ≤ 103

输出描述

输出一个整数。

题解

简单BFS。其中点到起点的距离的存储方式需要稍作改变,需要存储点处于两种状态时到起点的最小距离。同样地,在将点放入优先队列时需要记录该点的状态。更新最小距离时使用松弛思想。

import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Scanner;

public class Main {
    public static final int[] dx = {0, 1, 0, -1}, dy = {1, 0, -1, 0};
    private static class Point implements Comparable<Point>{
        public int x;
        public int y;
        public int status;  //该点状态,0或1
        public int distance;  //该点距离起点的距离

        public Point(int x, int y, int status, int distance) {
            this.x = x;
            this.y = y;
            this.status = status;
            this.distance = distance;
        }

        @Override
        public int compareTo(Point o) {
            return Integer.compare(this.distance, o.distance);
        }
    }
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int m = scanner.nextInt();
        int[][] map = new int[1010][1010];
        for (int i = 1; i <= n; i ++) {
            String s = scanner.next();
            for (int j = 1; j <= m; j ++) {
                map[i][j] = Integer.parseInt(String.valueOf(s.charAt(j - 1)));
            }
        }
        int[][][] dis = new int[n + 1][m + 1][2];  //点(x,y)处于状态0或1时距离起点的距离
        for (int i = 1; i <= n; i ++) {
            for (int j = 1; j <= m; j ++) {
                dis[i][j] = new int[]{Integer.MAX_VALUE, Integer.MAX_VALUE};
            }
        }
        dis[1][1][map[1][1]] = 0;  //起点距离为0
        Queue<Point> queue = new PriorityQueue<>();
        queue.add(new Point(1, 1, map[1][1], 0));
        while (!queue.isEmpty()) {
            Point point = queue.poll();
            for (int i = 0; i < 4; i ++) {
                int nextX = point.x + dx[i], nextY = point.y + dy[i];
                if (nextX >= 1 && nextX <= n && nextY >= 1 && nextY <= m) {
                    int nextStatus = map[nextX][nextY];
                    if (nextStatus != point.status) {  //相邻点的状态不同
                        int newDistance = point.distance + 1;
                        if (newDistance < dis[nextX][nextY][nextStatus]) {  //松弛
                            dis[nextX][nextY][nextStatus] = newDistance;
                            queue.add(new Point(nextX, nextY, nextStatus, newDistance));
                        }
                    }
                    else {  //相邻点的状态相同
                        int newDistance = point.distance + 2;
                        int newStatus = 1 - nextStatus;
                        if (newDistance < dis[nextX][nextY][newStatus]) {
                            dis[nextX][nextY][newStatus] = newDistance;
                            queue.add(new Point(nextX, nextY, newStatus, newDistance));
                        }
                    }
                }
            }
        }
        System.out.println(Math.min(dis[n][m][0], dis[n][m][1]));
    }
}

评论