题目链接
分析
其实很简单,它限制了每个点的状态并且整条路径只能够修改一次,那么我很很容易的出一个dp状态更新方程:
设 , 其中, ,那么我们有
if grid[v]==’#’: , 这个点必须要更改
if grid[v]==’.’:
总结
开始用了一个vis来记录每个点的访问情况,wa了一发,可能是由于两种不同状态的更新没有及时导致,还是应该采用 “不动点”算法,没有收敛就继续更新下一个点,反正每个点至多出队两次而已,开销不大
code
import java.io.BufferedInputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.PriorityQueue;
import java.util.Scanner;
public class Main {
public static final int INF = 0x3f3f3f3f;
public static Scanner in = new Scanner(new BufferedInputStream(System.in));
public static void main(String[] args) {
int n = in.nextInt();
boolean[][] map = new boolean[n][n];
while (in.nextLine()=="");
for(int i=0 ; i<n ; ++i){
char[] tmp = in.nextLine().toCharArray();
for(int j=0 ; j<n ; ++j)
map[i][j] = (tmp[j]=='#');
}
int ans = new Solution(map).solve();
System.out.printf("%d",ans>=INF?-1:ans);
}
}
class Solution {
int N;
boolean[][] map;
int[][][] dist;
boolean[][] vis;
public Solution(boolean[][] map) {
super();
this.map = map;
N = map.length;
dist = new int[N][N][2];
vis = new boolean[N][N];
for(int i=0 ; i<N;++i)
for(int j=0 ; j<N ; ++j){
dist[i][j][0]=dist[i][j][1]=Main.INF;
vis[i][j]=vis[i][j]= false;
}
}
public int solve() {
int ret=0;
dijkstra();
ret = Math.min(dist[N-1][N-1][0], dist[N-1][N-1][1]);
return ret;
}
class Node implements Comparable<Node>{
int x,y;
int val;
public Node(int x, int y,int val) {
super();
this.x = x;
this.y = y;
this.val = val;
}
@Override
public int compareTo(Node o) {
// TODO Auto-generated method stub
return val - o.val;
}
}
int[] dx = new int[]{1,-1,0,0};
int[] dy = new int[]{0,0,1,-1};
private boolean isLegal(int x,int y) {
return x >=0 && x <N && y >=0 && y<N;
}
private void dijkstra() {
PriorityQueue<Node> Q = new PriorityQueue<>();
Q.add(new Node(0, 0,0));
dist[0][0][0] = dist[0][0][1] =0;
// vis[0][0] = true;
while (!Q.isEmpty()) {
Node now = Q.remove();
// if(vis[now.x][now.y])continue;
// vis[now.x][now.y] = true;
if(dist[now.x][now.y][0]<now.val && dist[now.x][now.y][1]<now.val)continue;
for(int i=0 ; i<4 ; ++i){
int nx = now.x + dx[i];
int ny = now.y + dy[i];
if(!isLegal(nx, ny))continue;
if(map[nx][ny]){//有障碍
if(dist[nx][ny][1] > dist[now.x][now.y][0]+1){
dist[nx][ny][1] = dist[now.x][now.y][0]+1;
Q.add(new Node(nx,ny,dist[nx][ny][1]));
}
}else{
int nv = Math.min(dist[now.x][now.y][0], dist[now.x][now.y][1]);
if(dist[nx][ny][1]>nv+1){
dist[nx][ny][1] = nv+1;
Q.add(new Node(nx, ny,dist[nx][ny][1]));
}
if(dist[nx][ny][0]>dist[now.x][now.y][0]+1){
dist[nx][ny][0]=dist[now.x][now.y][0]+1;
Q.add(new Node(nx, ny, dist[nx][ny][0]));
}
}
}
}
}
}