关于图的广度优先搜索—————洛谷1332
这边讲一下一般的解题思路,一般来说,我们做题都是将复杂化为简单。所以一般切题,我们都是看是否能够构造一个邻接矩阵。
对于邻接矩阵,但凡有一点算法基础都能知道它其中的一个作用就是用来描述数据之间的相互关系,而恰恰是一个点,我觉着就是最重要的一个点,因为可以描述每一个数据间的关系,所以,我们可以在一般给出数据间的相互关系以后,就进行构造邻接矩阵,然后利用队列的先进先的特点(每一次的队列都是对一层的数据),然后循环。大部分简单的问题就都可以解决了。
这边为了方便讲解,博主这边特别的去找了一个题目去做,顺带丢到这边,方便大家理解
题目是洛谷的一道题,题目如下:
P1332 血色先锋队 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
这道题完完全全的就是我刚刚说的那个方法,这道题用这个方法是最完美的!!!
然后这边再把这个题目给贴一下方便讲解:
题目背景
巫妖王的天灾军团终于卷土重来,血色十字军组织了一支先锋军前往诺森德大陆对抗天灾军团,以及一切沾有亡灵气息的生物。孤立于联盟和部落的血色先锋军很快就遭到了天灾军团的重重包围,现在他们将主力只好聚集了起来,以抵抗天灾军团的围剿。可怕的是,他们之中有人感染上了亡灵瘟疫,如果不设法阻止瘟疫的扩散,很快就会遭到灭顶之灾。大领主阿比迪斯已经开始调查瘟疫的源头。原来是血色先锋军的内部出现了叛徒,这个叛徒已经投靠了天灾军团,想要将整个血色先锋军全部转化为天灾军团!无需惊讶,你就是那个叛徒。在你的行踪败露之前,要尽快完成巫妖王交给你的任务。
题目描述
军团是一个 nn 行 mm 列的矩阵,每个单元是一个血色先锋军的成员。感染瘟疫的人,每过一个小时,就会向四周扩散瘟疫,直到所有人全部感染上瘟疫。你已经掌握了感染源的位置,任务是算出血色先锋军的领主们感染瘟疫的时间,并且将它报告给巫妖王,以便对血色先锋军进行一轮有针对性的围剿。
输入格式
第 11 行:四个整数 nn,mm,aa,bb,表示军团矩阵有 nn 行 mm 列。有 aa 个感染源,bb 为血色敢死队中领主的数量。
接下来 aa 行:每行有两个整数 xx,yy,表示感染源在第 xx 行第 yy 列。
接下来 bb 行:每行有两个整数 xx,yy,表示领主的位置在第 xx 行第 yy 列。
输出格式
第 11 至 bb 行:每行一个整数,表示这个领主感染瘟疫的时间,输出顺序与输入顺序一致。如果某个人的位置在感染源,那么他感染瘟疫的时间为 00。
然后输入输出我就不贴了。
解题思路:
开一个二维的类数组,这个类是用来存储每一个数据的x与y的坐标的,还有一个是每一个数据的最早被感染的时间。还要设置一个boolean类型的数组,这个数组是用来存储数据的状态的,也就是看每一个数据是否有被访问到。
然后利用一个bfs的方法,方法在上文中我有进行一个讲解,也就是利用队列的那个,主要是利用bfs每一次遍历到这个位置的时候,我把这个位置的这个最小值进行一个更新,然后再利用那个boolean数组进行判断是否有被更新过,如果有被更新,则不加入这个队列。如此往复。
具体代码如下。
import java.util.*;
import java.io.*;
public class Main {
/**
*
* @author 19015
*
*/
static class FastScanner{
BufferedReader buf;
StringTokenizer stk;
public FastScanner() {
buf = new BufferedReader(new InputStreamReader(System.in),16584);
eat("");
}
public void eat(String fa) {
stk = new StringTokenizer(fa);
}
public String nextLine() {
try {
return buf.readLine();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
return null;
}
}
public boolean hasNext() {
while(!stk.hasMoreTokens()) {
String s = nextLine();
if(s == null) {
return false;
}
eat(s);
}
return true;
}
public String next() {
hasNext();
return stk.nextToken();
}
public int nextInt() {
return Integer.parseInt(next());
}
}
static FastScanner in = new FastScanner();
public static void main(String[] args) {
// TODO 自动生成的方法存根
while(in.hasNext()) {
int x = in.nextInt();
int y = in.nextInt();
int a = in.nextInt();
int b = in.nextInt();
Datatemp[][] xy = new Datatemp[x][y];
for(int i=0;i<x;i++) {
for(int j=0;j<y;j++) {
xy[i][j] = new Datatemp(i,j);
}
}
boolean[][] xybol = new boolean[x][y];
Queue tempchu = new LinkedList();
Queue tempmo = new LinkedList();
for(int i=0;i<a;i++) {
int tempx = in.nextInt()-1;
int tempy = in.nextInt()-1;
tempchu.add(new Datatemp(tempx,tempy));
xybol[tempx][tempy] = true;
}
for(int i=0;i<b;i++) {
tempmo.add(new Datatemp(in.nextInt()-1,in.nextInt()-1));
}
fan(xy,xybol,tempchu);
while(!tempmo.isEmpty()) {
Datatemp temp = (Datatemp) tempmo.poll();
System.out.println(xy[temp.x][temp.y].shu);
}
}
}
static void fan(Datatemp[][] xy,boolean[][] xybol,Queue tempchu) {
int[][] shu = {{1,0},{0,1},{-1,0},{0,-1}};
while(!tempchu.isEmpty()) {
Datatemp temp = (Datatemp) tempchu.poll();
for(int i=0;i<shu.length;i++) {
if(temp.x+shu[i][0]>=0&&temp.x+shu[i][0]<xy.length&&temp.y+shu[i][1]>=0&&temp.y+shu[i][1]<xy[0].length&&!xybol[temp.x+shu[i][0]][temp.y+shu[i][1]]) {
xy[temp.x+shu[i][0]][temp.y+shu[i][1]].shu=temp.shu+1;
xybol[temp.x+shu[i][0]][temp.y+shu[i][1]]=true;
tempchu.add(xy[temp.x+shu[i][0]][temp.y+shu[i][1]]);
}
}
}
}
}
class Datatemp{
int x;
int y;
int shu;
public Datatemp(int x,int y) {
this.x = x;
this.y = y;
shu = 0;
}
}
如果对你有帮助的话,还请点一个赞,这将会是我写作最大的支持!!!
谢谢!!