#1290 : Demo Day
-
4 8 ....bb.. ........ .....b.. ...bb...
样例输出
-
1
描述
You work as an intern at a robotics startup. Today is your company's demo day. During the demo your company's robot will be put in a maze and without any information about the maze, it should be able to find a way out.
The maze consists of N * M grids. Each grid is either empty(represented by '.') or blocked by an obstacle(represented by 'b'). The robot will be release at the top left corner and the exit is at the bottom right corner.
Unfortunately some sensors on the robot go crazy just before the demo starts. As a result, the robot can only repeats two operations alternatively: keep moving to the right until it can't and keep moving to the bottom until it can't. At the beginning, the robot keeps moving to the right.
rrrrbb.. ...r.... ====> The robot route with broken sensors is marked by 'r'. ...rrb.. ...bb...
While the FTEs(full-time employees) are busy working on the sensors, you try to save the demo day by rearranging the maze in such a way that even with the broken sensors the robot can reach the exit successfully. You can change a grid from empty to blocked and vice versa. So as not to arouse suspision, you want to change as few grids as possible. What is the mininum number?
输入
Line 1: N, M.
Line 2-N+1: the N * M maze.
For 20% of the data, N * M <= 16.
For 50% of the data, 1 <= N, M <= 8.
For 100% of the data, 1<= N, M <= 100.
输出
The minimum number of grids to be changed.
思路:动态规划。求出抵达每一个点最少的改变次数。抵达某一个点,只有可能从上面来,或者从左边来。
代码:
import java.util.Scanner;
public class DemoDay {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int M = sc.nextInt();
int[][] maze = new int[N + 1][M + 1];
for (int i = 1; i < N + 1; i++) {
String tempString = sc.next();
for (int j = 1; j < M + 1; j++) {
if (tempString.charAt(j - 1) == 'b')
maze[i][j] = 1;
else
maze[i][j] = 0;
}
}
sc.close();
int[][] score = new int[N + 1][M + 1];// 分數矩陣
int[][] direction = new int[N + 1][M + 1];// left 1;up 2;both 0 方向矩陣
// 初始化分數矩陣
for (int i = 1; i < N + 1; i++)
score[i][0] = N * M + 100;// 無線大
for (int i = 1; i < M + 1; i++)
score[0][i] = N * M + 100;// 無線大
// 初始化方向矩陣
for (int i = 1; i < N + 1; i++)
direction[i][0] = 2;// 向下
for (int i = 1; i < M + 1; i++)
direction[0][i] = 1;// 向左
for (int i = 1; i < N + 1; i++) {
for (int j = 1; j < M + 1; j++) {
int fromUp = 0;
int fromLeft = 0;
if (maze[i][j] == 1)//这个点有阻碍,需要变化才能到这个点,代价为1
score[i][j] = score[i][j] + 1;
if (j + 1 >= M + 1 || maze[i - 1][j + 1] == 1)//必须向下走,代价为0
fromUp = 0;
else if (direction[i - 1][j] == 1)//需要改变方向才能向下走,代价为1
fromUp = 1;
else if (direction[i - 1][j] == 2)//必须向下走,代价为0
fromUp = 0;
else if (direction[i - 1][j] == 0)//可以向下也可以向右边,代价为0
fromUp = 0;
if (i + 1 >= N + 1 || maze[i + 1][j - 1] == 1)//必须向右走,代价为0
fromLeft = 0;
else if (direction[i][j - 1] == 2)//需要改变方向才能向右走,代价为1
fromLeft = 1;
else if (direction[i][j - 1] == 1)//必须向右走,代价为0
fromLeft = 0;
else if (direction[i][j - 1] == 0)//可以向下也可以向右边,代价为0
fromLeft = 0;
int min = Math.min(fromUp + score[i - 1][j], fromLeft
+ score[i][j - 1]);//求最小的代价
score[i][j] = score[i][j] + min;
//计算方向
if (min == fromUp + score[i - 1][j])
direction[i][j] = 2;
if (min == fromLeft + score[i][j - 1])
direction[i][j] = 1;
if ((fromUp + score[i - 1][j]) == (fromLeft + score[i][j - 1]))
direction[i][j] = 0;
if (i == 1 && j == 1) {
score[i][j] = 0;
direction[i][j] = 1;
}
}
}
System.out.println(score[N][M]);
}
}