6044:鸣人和佐助 (Java BFS)

题目链接
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

带限制的最短路径可以用BFS,击败大蛇丸的手下相当于直接破坏迷宫的障碍行走。在不能破坏障碍的时候,我们使用vis数组来标记一个位置是否访问过,当允许破坏障碍T次时,每个位置事实上有T中情况,需要标记每种情况是否访问过。
@ # x # +
x # x # #
x # x # #
x x x # #
假设T=1,那么正确的路线的长度显然是10,在搜索过程中,我们可以选择破坏(1,2)的墙,到达(1,3),但是此时无法再破墙;沿着正确的路径走,会再次经过(1,3),但是此时的状态是与之前不可行时候的状态不一样,即用破墙次数来区分,因此为vis增加一个维度标记破墙次数即可。

import java.util.*;

class Pos{
	public int x;
	public int y;
	public int t;
	public Pos(int x,int y,int t) {
		this.x=x;
		this.y=y;
		this.t=t;
	}
}

public class Main{
	public static int M;
	public static int N;
	public static int T;
	public static char[][] G=new char[205][205];
	public static int ans=0x3f3f3f3f;
	public static int[] dx= {0,0,1,-1};
	public static int[] dy= {1,-1,0,0};
	public static boolean[][][] vis=new boolean[205][205][10];
	public static int[][][] dis=new int[205][205][10];
	public static void main(String[] Args) {
		Scanner sc=new Scanner(System.in);
		M=sc.nextInt();
		N=sc.nextInt();
		T=sc.nextInt();
		sc.nextLine();//要吸收Enter
		for(int i=0;i<205;i++) {
			for(int j=0;j<205;j++) {
				Arrays.fill(vis[i][j], false);
				Arrays.fill(dis[i][j],0x3f3f3f3f);
			}
		}
		Pos st=new Pos(0,0,0);
		Pos dst=new Pos(0,0,0);
		for(int i=0;i<M;i++) {
			String tmp=sc.nextLine();
			for(int j=0;j<N;j++) {
				G[i][j]=tmp.charAt(j);
				if(G[i][j]=='@') {
					st=new Pos(i,j,T);
				}else if(G[i][j]=='+') {
					dst=new Pos(i,j,0);
				}
			}	
		}
		LinkedList<Pos> q=new LinkedList<Pos>();
		vis[st.x][st.y][st.t]=true;
		Arrays.fill(dis[st.x][st.y],0);
		q.addLast(st);
		boolean flag=false;
		while(!q.isEmpty()) {
			Pos tmp=q.removeFirst();
			for(int i=0;i<4;i++) {
				int x=tmp.x+dx[i];
				int y=tmp.y+dy[i];
				int t=tmp.t;
				if(x<0 || x>=M || y<0 || y>=N || vis[x][y][t]) {
					continue;
				}else if(G[x][y]=='+') {
					dis[x][y][t]=dis[tmp.x][tmp.y][tmp.t]+1;
					flag=true;
					break;
				}else if(G[x][y]=='*') {
					vis[x][y][t]=true;
					dis[x][y][t]=dis[tmp.x][tmp.y][tmp.t]+1;
					q.addLast(new Pos(x,y,t));
				}else if(G[x][y]=='#' && t>0) {
					t-=1;
					vis[x][y][t]=true;
					dis[x][y][t]=dis[tmp.x][tmp.y][tmp.t]+1;
					q.addLast(new Pos(x,y,t));
				}
			}
			if(flag) {
				break;
			}
		}
		for(int i=0;i<10;i++) {
			ans=Math.min(ans, dis[dst.x][dst.y][i]);
		}
		if(ans==0x3f3f3f3f) {
			ans=-1;
		}
		System.out.print(ans);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值