第十一届蓝桥杯C组国赛B题-扩散-Java
题目:
题解:
DFS搜索速度过于缓慢,尝试BFS速度不错非常快。但是由于数组下表不可能有负数,因此,我们要先将这四个点坐标进行平移处理一下,保证在搜索过程中不会有负数的出现。
以源点(x,y)为中心,1分钟扩展一圈,那么2020分钟后上面点应该是(x,y+2020),右边的点应该是(x+2020,y),下边的点应该是(x,y-2020),左边的点应该是(x-2020,y)。那么我们先观察一下这些源点能够扩散到的四个顶点是什么:
public static void main(String[] args) {
int[][] p = {
{
0,0},{
2020,11},{
11,14},{
2000,2000}};
for(int i=0;i<4;i++) {
System.out.printf("
(%d,%d):
",p[i][0],p[i][1]);
System.out.printf(" 上:(%d,%d)
",p[i][0],p[i][1]+2020);
System.out.printf(" 右:(%d,%d)
",p[i][0]+2020,p[i][1]);
System.out.printf(" 下:(%d,%d)
",p[i][0],p[i][1]-2020);
System.out.printf(" 左:(%d,%d)
",p[i][0]-2020,p[i][1]);
}
运行结果:
(0,0): 上:(0,2020) 右:(2020,0) 下:(0,-2020) 左:(-2020,0) (2020,11): 上:(2020,2031) 右:(4040,11) 下:(2020,-2009) 左:(0,11) (11,14): 上:(11,2034) 右:(2031,14) 下:(11,-2006) 左:(-2009,14) (2000,2000): 上:(2000,4020) 右:(4020,2000) 下:(2000,-20) 左:(-20,2000)
我们不难发现x坐标最小是-2020,y的最大坐标为4040。那么我们可以将数学中直角坐标系转换为数组的二维坐标系,我习惯的数组坐标是这样,请大家理解:
黑色为数学中直角坐标系,红色为数组中二维坐标系。
由于x最小为-2020,我们可以x向右平移3000,那么就不会出现负数了,也就是x+3000;
由于y最大为4040,我们可以让它转换为从上向下的y,可以用一个5000来转换他,也就是5000-y。
至此,我们完成了坐标转换,输出一下看看:
public static void main(String[] args) {
int[][] p = {
{
0,0},{
2020,11},{
11,14},{
2000,2000}};
for(int i=0;i<4;i++) {
System.out.printf("
(%d,%d):
",p[i][0],p[i][1]);
System.out.printf("->(%d,%d)
",p[i][0]+3000,5000-p[i][1]);
}
}
运行结果:
(0,0): ->(3000,5000) (2020,11): ->(5020,4989) (11,14): ->(3011,4986) (2000,2000): ->(5000,3000)
那么我们就开始多源BFS吧!让四个点同时开始扩散!!!
import java.util.LinkedList;
import java.util.Queue;
public class Main {
// 记录是否到达过
public static boolean[][] vis = new boolean[10000][10000];
// 记录扩散点的个数
public static int cnt;
// 结点class
public static class Node {
int x,y,t;
public Node() {
}
public Node(int x, int y, int t) {
this.x = x;
this.y = y;
this.t = t;
}
}
public static void main(String[] args) {
int[][] p = {
{
0,0},{
2020,11},{
11,14},{
2000,2000}};
// 方向数组:上下左右
int[][] dir = {
{
-1,0},{
0,1},{
1,0},{
0,-1}};
// 计数初始为4,因为有4个源点
cnt = 4;
Queue<Node> q = new LinkedList<Node>();
// 将4个源点加入到队列中
q.add(new Node(3000, 5000, 0));
q.add(new Node(5020, 4989, 0));
q.add(new Node(3011, 4986, 0));
q.add(new Node(5000, 3000, 0));
// 标记4个源点已访问
vis[3000][5000] = true;vis[5020][4989] = true;
vis[3011][4986] = true;vis[5000][3000] = true;
// 开始BFS
while(!q.isEmpty()) {
Node head = q.poll();
for(int i=0;i<4;i++) {
// 遍历下一个可能的点
Node next = new Node();
next.x = head.x + dir[i][0];
next.y = head.y + dir[i][1];
next.t = head.t + 1; // 距离加一
// 判断是否没有走过 并且 距离小于2020
if(!vis[next.x][next.y] && next.t <= 2020) {
vis[next.x][next.y] = true; // 标记走过
cnt++; // 计数器加一
q.add(next); // 加入队列
}
}
}
System.out.println(cnt); // 完美输出
}
}
上一篇:
IDEA上Java项目控制台中文乱码
