bfs提高系列之陨石下落

P2895 [USACO08FEB] Meteor Shower S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

主要思路如下,

1:首先贝萨可以跑到牧场外,牧场牧场仅仅300*300那么大,

2:其次跑到牧场外不一定是最优解,可能牧场内某一点可能是最优的

整体思路是从起点的bfs,我们一开始记录一下所有会被陨石砸中的点,一旦我们bfs跑到一个点没被任何陨石砸中,那么我们就输出这个时间。同时我们要在每个时间段刷新一下下落的陨石,来判断这个格子能不能走。

来一波总思路吧

首先我们输入每个流星下落的地点和时间,把调用方法把所有可能会被变成不可走的点标记上,

接着我们把流行按照时间先后放入队列排好序。我们要知道我们要让流星先于我们一个时间单位坠落,也就是说我们在时间0的时候就要让时间1的流行陨落,为什么呢。你想呀,假如说你在时间0时走到了1号地点,现在时间为1了,这时我们在启动流星下落,万一流星下落到1号位置,你不就被砸死了吗,所以我们要在走前先把下一步流行落下。在开始走时,先落下0时辰的流行,在落1时间的流星。我们在落完流星后,我们开始往四周试探,如果这个点没被走过或者流星砸过,我们把它入优先队列的同时,判断一下他是不是最后的那个安全点,是就输出时间顺便把标记answer改为0,不是就接着走.记住流星不能超过牧场边界,而人可以,所以贝萨在走时没给他限制小于300。

最后如果answer始终没改变,那就证明贝萨没走出。输出-1

代码有注释:


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.math.MathContext;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeMap;
import java.util.TreeSet;
public class Main {	
  public static void main(String[] args) throws NumberFormatException, IOException  {
Scanner sc=new Scanner(System.in);
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String[] aStrings=br.readLine().split(" ");
int a=Integer.parseInt(aStrings[0]);
int b;
for(b=0;b<a;b++) {//预处理
	String[] bStrings=br.readLine().split(" ");
	int c=Integer.parseInt(bStrings[0]);
	int d=Integer.parseInt(bStrings[1]);
	int e=Integer.parseInt(bStrings[2]);
	ll1.add(new liuxing(c, d, e));
	jieguo[c][d]=1;
	chuliliuxing(c, d);//
}
Collections.sort(ll1);
LinkedList<liuxing> ll2=new LinkedList<>();
liuxing lx1=new liuxing(0, 0, 0);
ll2.add(lx1);
int f=0;
jiance(0);
visited[0][0]=1;
while(ll2.size()!=0) {
	liuxing lx2=ll2.remove();
	
	jiance(lx2.time+1);
	int b1=lx2.x;
	int c1=lx2.y;
	int d1=lx2.time;
	for(int a1=0;a1<4;a1++) {
		int x1=xx[a1]+b1;
		int y1=yy[a1]+c1;

		if(x1>=0&&y1>=0&&visited[x1][y1]==0) {
			visited[x1][y1]=1;
			//System.out.println("AAA"+x1+" "+y1+" " +d1);
			ll2.add(new liuxing(x1, y1, d1+1));
			if(jieguo[x1][y1]==0) {
				answer=0;
				//System.out.println(x1+" "+y1);
				System.out.println(d1+1);
				return;
			}
		}
	}
	
}
if(answer==Integer.MAX_VALUE) {
	System.out.println("-1");
}
}
  public static int answer=Integer.MAX_VALUE;
  public static LinkedList<liuxing> ll1=new LinkedList<>();
  public static int[][] jieguo=new int[350][350];//此数组记录最终被陨石点燃的点
  public static int[][] visited=new int[350][350];//此数组记录按时间不可走的点
  public static int[] xx= {-1,1,0,0};//四个方位
  public static int[] yy= {0,0,-1,1};
  public static void jiance(int a) {//此方法的作用是按照时间将四周的领域点燃来模拟流行下降的问题。
	  while(true) {
		  if(ll1.size()==0) {
			  break;
		  }
		  if(ll1.get(0).time!=a) {
			  break;
		  }
		  if(ll1.size()!=0) {
			  if(ll1.get(0).time==a) {
				  int c;
				  for(c=0;c<4;c++) {
					  int d=ll1.get(0).x+xx[c];
					  int e=ll1.get(0).y+yy[c];
					  if(d<0||d>300||e<0||e>300) {
						  continue;
					  }
					  visited[d][e]=1;
				  }
			  }
			  ll1.remove();
		  }
	  }
  }
  public static void chuliliuxing(int a,int b) {//主要记录流星下落后的点及其周围被点燃的点
	  int c;
	  for(c=0;c<4;c++) {
		  int d=a+xx[c];
		  int e=b+yy[c];
		  if(d<0||d>300||e<0||e>300) {//限制范围在农场之内。
			  continue;
		  }
		  jieguo[d][e]=1;
	  }
  }
}
class liuxing implements Comparable<liuxing>{//流行类,主要记录流行下落的地点时间,并按时间排序
int x;
int y;
int time;
	public liuxing(int x, int y, int time) {
	super();
	this.x = x;
	this.y = y;
	this.time = time;
}
	@Override
	public int compareTo(liuxing o) {
		// TODO Auto-generated method stub
		return this.time-o.time;
	}
	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值