7139 流星雨

题目描述

      贝茜听说了一个骇人听闻的消息:一场流星雨即将袭击整个农场,由于流星 体积过大,它们无法在撞击到地面前燃烧殆尽,届时将会对它撞到的一切东西 造成毁灭性的打击。很自然地,贝茜开始担心自己的安全问题。以FJ牧场中最聪明的奶牛的名誉起誓,她一定要在被流星砸到前,到达一个安全的地方(也就是说,一块不会被任何流星砸到的土地)。如果将牧场放入一个直角坐标系中, 贝茜现在的位置是原点,并且,贝茜不能踏上一块被流星砸过的土地。 

      根据预报,一共有M颗流星(1 <= M <= 50,000)会坠落在农场上,其中第i颗 流星会在时刻T_i (0 <= T_i <= 1,000)砸在坐标为(X_i, Y_i) (0 <= X_i <= 300;0 <= Y_i <= 300)的格子里。流星的力量会将它所在的格子 ,以及周围4个相邻的格子都化为焦土,当然贝茜也无法再在这些格子上行走。 

 贝茜在时刻0开始行动,它只能在第一象限中,平行于坐标轴行动,每1个时刻中,她能移动到相邻的(一般是4个) 格子中的任意一个,当然目标格子要没有被烧焦才行。如果一个格子在时刻t被 流星撞击或烧焦,那么贝茜只能在t之前的时刻在这个格子里出现。 请你计算一下,贝茜最少需要多少时间才能到达一个安全的格子。

输入

第1行: 1个正整数:M 

第2..M+1行: 第i+1行为3个用空格隔开的整数:X_i,Y_i,以及T_i

输出

输出1个整数,即贝茜逃生所花的最少时间。如果贝茜无论如何都无法在流星雨中存活下来,输出-1

样例输入输出

样例输入 #1

4
0 0 2
2 1 2
1 1 2
0 3 5

样例输出 #1

5

分析

如果我们观察在t=5时的牧场,可以发现离贝茜最近的安全的格子是(3,0) ——不过由于早在第二颗流星落地时,贝茜直接跑去(3,0)的路线就被封死了。离贝茜第二近的安全格子为(4,0),但它的情况也跟(3,0)一样。再接下来的格子就是在(0,5)-(5,0)这条直线上。在这些格子中,(0,5),(1,4)以及(2,3)都能在 5个单位时间内到达。

方法:预处理+直接广搜


代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<typename T>inline void read(T &FF){
	T RR=1;FF=0;char CH=getchar();
	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
	FF*=RR;
}
template<typename T>inline void write(T x){
	if(x<0)putchar('-'),x*=-1;
	if(x>9)write(x/10);
	putchar(x%10+48);
}
template<typename T>inline void writen(T x){
	write(x);
	puts("");
}
int n,a[1010][1010],h[1010][1010],xx;
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
void work(int x,int y,int t){
	a[x][y]=min(a[x][y],t);
	for(int i=0;i<4;i++){
		int tx=x+dx[i],ty=y+dy[i];
		if(tx>=0&&ty>=0)a[tx][ty]=min(a[tx][ty],t);
	}
}
queue<int>x;
queue<int>y;
queue<int>s;
int main(){
	memset(a,0x3f,sizeof(a));xx=a[0][0];
	read(n);
	for(int i=1;i<=n;i++){
		int x,y,t;
		read(x),read(y),read(t);
		work(x,y,t);
	}h[0][0]=1;
	x.push(0);
	y.push(0);
	s.push(0);
	while(x.size()){
		for(int i=0;i<4;i++){
			int tx=x.front()+dx[i],ty=y.front()+dy[i];
			if(tx>=0&&ty>=0&&s.front()+1<a[tx][ty]&&!h[tx][ty]){
				h[tx][ty]=1;
				if(a[tx][ty]==xx){
					cout<<s.front()+1;
					return 0;
				}
				x.push(tx);
				y.push(ty);
				s.push(s.front()+1);
			}
		}
		x.pop();
		y.pop();
		s.pop();
	}puts("-1");
	return 0;
}

拓展(广搜和深搜)

转载于 蛇皮皮蛋 的原创文章

原文链接:https://blog.csdn.net/qq_37598011/article/details/98879072

我摘录了部分内容你们可以选择性地看看:

广搜

广度优先搜索算法主要解决两个问题:

从节点A出发有到节点B的路径吗?
从节点A出发到节点B的最短路径是哪条?
 实现方式:

    它的实现方式可以用队列的数据结构去理解(先进先出),每次取出一个节点都将这个节点相邻的节点加入队列尾部,直到找到需要寻找的节点。(这里需要注意的是循环依赖的问题,通常每取出一个节点就将其放入一个数组中,然后每次入队时都判断一下是否已使用过这个节点了)

实现:

首先我会生成一颗二叉树,然后根据广搜,一层一层的遍历:

class Node(object):
    """初始化一个节点,需要为节点设置值"""
 
    def __init__(self, val):
        self.val = val
        self.left = None
        self.right = None
 
 
class BinaryTree(object):
    """
    创建二叉树,完成
    - 添加元素
    - 广度遍历
    """
 
    def __init__(self):
        self.root = None
        pass
 
    # 添加元素
    def addNode(self, val):
        # 创建队列结构存储结点
        nodeStack = [self.root]
 
        # 如果根结点为空
        if self.root == None:
            self.root = Node(val)
            print("添加根节点{0}成功!".format(self.root.val))
            return
 
        # 模拟生成一颗二叉树,本身只持有root节点
        while len(nodeStack) > 0:
            # 队列元素出列
            p_node = nodeStack.pop()
 
            # 如果左子结点为空
            if p_node.left == None:
                p_node.left = Node(val)
                print("添加左:{0} ".format(p_node.left.val))
                return
 
            # 如果右子节点为空
            if p_node.right == None:
                p_node.right = Node(val)
                print("添加右:{0} ".format(p_node.right.val))
                return
 
            # 入队
            nodeStack.insert(0, p_node.left)
            nodeStack.insert(0, p_node.right)
 
    # 广度优先遍历
    def BFS(self):
        nodeStack = [self.root];
 
        # 只要队列不为空
        while len(nodeStack) > 0:
            my_node = nodeStack.pop()
            print("-->", my_node.val)
 
            if my_node.left is not None:
                nodeStack.insert(0, my_node.left)
 
            if my_node.right is not None:
                nodeStack.insert(0, my_node.right)
 
 
 
def main():
    # 生成一个二叉树
    bt = BinaryTree()
    bt.addNode(0)
    bt.addNode(1)
    bt.addNode(2)
    bt.addNode(3)
    bt.addNode(4)
    bt.addNode(5)
    bt.addNode(6)
    bt.addNode(7)
    bt.addNode(8)
    bt.addNode(9)
 
    print("广度遍历-->")
    bt.BFS()
 
 
if __name__ == '__main__':
    main()

结论:广度优先搜索的适用场景适用于深度不深且权值相同的图,搜索的结果为最短路径或者最小权值和。

深搜

深度优先搜索
深度优先搜索算法解决的问题有:

通过便利所有节点路径找到最小权重路径
 实现方式:

    它的实现方式可以用栈的数据结构去理解(先进后出),每次出栈时,都将它相邻的节点,压入栈头。直到该条路径都便利完了,它会回溯到上个节点然后继续这个步骤。(这里需要注意的是循环依赖的问题,通常每取出一个节点就将其放入一个数组中,然后每次入队时都判断一下是否已使用过这个节点了)

结论:深度优先搜索的适用于针对深度很深或者深度不确定的图或者权值不相同的图,优势在于节省资源,但想要得到最优解需要完整遍历后比对所有路径选取最优解。

不喜勿喷,初心是想让你们在看题的同时学到东西

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值