L3-037 夺宝大赛 - java

L3-037 夺宝大赛


Java (javac)
时间限制
800 ms
内存限制
256 MB
其他编译器
时间限制
400 ms
内存限制
64 MB
栈限制
8192 KB


题目描述:

夺宝大赛的地图是一个由 n × m n \times m n×m 个方格子组成的长方形,主办方在地图上标明了所有障碍、以及大本营宝藏的位置。参赛的队伍一开始被随机投放在地图的各个方格里,同时开始向大本营进发。所有参赛队从一个方格移动到另一个无障碍的相邻方格(“相邻”是指两个方格有一条公共边)所花的时间都是 1 个单位时间。但当有多支队伍同时进入大本营时,必将发生火拼,造成参与火拼的所有队伍无法继续比赛。大赛规定:最先到达大本营并能活着夺宝的队伍获得胜利。
假设所有队伍都将以最快速度冲向大本营,请你判断哪个队伍将获得最后的胜利。

输入格式:
输入首先在第一行给出两个正整数 m m m n n n ( 2 < m , n ≤ 100 ) (2 < m, n \le 100) 2<m,n100,随后 m m m 行,每行给出 n n n 个数字,表示地图上对应方格的状态: 1 1 1 表示方格可通过; 0 0 0 表示该方格有障碍物,不可通行; 2 2 2 表示该方格是大本营。题目保证只有 1 1 1 个大本营。
接下来是参赛队伍信息。首先在一行中给出正整数 k ( 0 < k < m × n / 2 ) k(0 < k < m \times n / 2) k0<k<m×n/2,随后 k k k 行,第 i ( 1 ≤ i ≤ k ) i(1 \le i \le k) i1ik行给出编号为 i i i 的参赛队的初始落脚点的坐标,格式为 x y。这里规定地图左上角坐标为 1 1,右下角坐标为 n m,其中 n 为列数,m 为行数。注意参赛队只能在地图范围内移动,不得走出地图。题目保证没有参赛队一开始就落在有障碍的方格里。

输出格式:
在一行中输出获胜的队伍编号和其到达大本营所用的单位时间数量,数字间以 1 个空格分隔,行首尾不得有多余空格。若没有队伍能获胜,则在一行中输出 No winner.

输入样例 1:
5 7
1 1 1 1 1 0 1
1 1 1 1 1 0 0
1 1 0 2 1 1 1
1 1 0 0 1 1 1
1 1 1 1 1 1 1
7
1 5
7 1
1 1
5 5
3 1
3 5
1 4
输出样例 1:
7 6
样例 1 说明:
七支队伍到达大本营的时间顺次为:7、不可能、5、3、3、5、6,其中队伍 4 和 5 火拼了,队伍 3 和 6 火拼了,队伍 7 比队伍 1 早到,所以获胜。

输入样例 2:
5 7
1 1 1 1 1 0 1
1 1 1 1 1 0 0
1 1 0 2 1 1 1
1 1 0 0 1 1 1
1 1 1 1 1 1 1
7
7 5
1 3
7 1
1 1
5 5
3 1
3 5
输出样例 2:
No winner.


给定一张地图,在给定k个队伍,问第一个到达大本营且没有冲突的队伍是哪队。输出队伍编号以及到达时间。如果都冲突,输出No winner.


emmmmmmm

先求从大本营开始到达每个点的步数是多少?

然后使用数组,存储每个步数上的队伍编号是多少。

  • 如果当前位置值为0,那么表示当前步数没有队伍;
  • 如果当前位置值为-1,那么表示当前步数有多个队伍同时到达,会产生冲突。
  • 否则就表示,当前步数队伍到达的编号

import java.io.*;
import java.util.*;

public class Main
{
	static int dxy[][] =
	{
			{ -1, 0 },
			{ 0, 1 },
			{ 1, 0 },
			{ 0, -1 } };

	static int N = (int) 1e2 + 10;
	static int map[][] = new int[N][N]; // 存储地图
	static int d[][] = new int[N][N]; // 存储从大本营到每个点的步数
	static int res[] = new int[N * N]; // 存储步数的编号

	static int n, m;

    // 判断当前位置是否在地图中
	static boolean check(int x, int y)
	{
		return (1 <= x && x <= n) && (1 <= y && y <= m);
	}

	static void bfs(int startX, int startY)
	{
		LinkedList<edge> li = new LinkedList<edge>();
		li.add(new edge(startX, startY));

		while (li.size() > 0)
		{
			edge t = li.poll();
			int x = t.x;
			int y = t.y;

			for (int i = 0; i < 4; i++)
			{
				int dx = x + dxy[i][0];
				int dy = y + dxy[i][1];
                // 如果当前点在地图上,以及当前点可以走,以及当前点没有走过
				if (check(dx, dy) && map[dx][dy] != 0 && d[dx][dy] == 0)
				{
					d[dx][dy] = d[x][y] + 1; // 更新步数
					li.add(new edge(dx, dy));
				}
			}
		}
	}

	public static void main(String[] args)
	{
		n = sc.nextInt();
		m = sc.nextInt();

		int x = 0, y = 0;
		for (int i = 1; i <= n; i++)
		{
			for (int j = 1; j <= m; j++)
			{
				map[i][j] = sc.nextInt();
                // 当前点是大本营
				if (map[i][j] == 2)
				{
					x = i;
					y = j;
				}
			}
		}

		bfs(x, y); // 计算从大本营开始,到达每个点的步数是多少

		int k = sc.nextInt();
		for (int i = 1; i <= k; i++)
		{
			// 注意先输入列,在输入行
			y = sc.nextInt();
			x = sc.nextInt();

			int t = d[x][y]; // 大本营达到当前点的步数
			// 如果当前大本营能走到
			if (t > 0)
			{
			    // 如果当前步数没走过
				if (res[t] == 0) 
				    res[t] = i; // 当前步数的编号设为i
				// 如果当前点走过
				else 
				    res[t] = -1; // 那么当前步数就会产生冲突
			}
		}

		boolean f = true; // 是否有队伍没有获胜
		for (int i = 1; i <= n * m; i++)
		{
		    // 如果当前步数的编号存在,则当前队伍获胜
			if (res[i] > 0)
			{
				out.println(res[i] + " " + i);
				f = false;
				break;
			}
		}
		// 没有队伍获胜,则输出No winner.
		if (f) out.println("No winner.");

		out.flush();
		out.close();
	}

	static class edge
	{
		int x, y;

		public edge(int x, int y)
		{
			this.x = x;
			this.y = y;
		}
	}

	static Scanner sc = new Scanner(System.in);
	static PrintWriter out = new PrintWriter(System.out);

}

LinkedList

bfs
bfs


如果有说错的 或者 不懂的 尽管提 嘻嘻

一起进步!!!


闪现

  • 31
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

谢谢 啊sir

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值