hihocoder [offer收割机]编程练习赛57 C 逃离迷宫5(最短路,dp)

题目链接

逃离迷宫5

分析

其实很简单,它限制了每个点的状态并且整条路径只能够修改一次,那么我很很容易的出一个dp状态更新方程:

u > v , 其中, d i s t [ u ] [ 0 / 1 ] ,那么我们有

if grid[v]==’#’: d i s t [ v ] [ 1 ] = m i n ( d i s t [ v ] [ 1 ] , d i s t [ u ] [ 0 ] + 1 ) , 这个点必须要更改
if grid[v]==’.’: d i s t [ v ] [ 0 ] = m i n ( d i s t [ v ] [ 0 ] , d i s t [ u ] [ 0 ] + 1 )
d i s t [ v ] [ 1 ] = m i n ( d i s t [ v ] [ 1 ] , m i n ( d i s t [ u ] [ 0 / 1 ] ) + 1 )

总结

开始用了一个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]));
                    }
                }
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/dylan_frank/article/details/80158850
今日推荐