看了好久的样例才看懂。

题意:有一个人要从(0,0)走到(n,m),图中有k个碉堡,每个碉堡可以向某个固定的方向每隔t秒放一次炮,炮弹不能穿越另一个碉堡,会被阻挡。人在移动的过程中不会被炮弹打到,也就是说只有炮弹和人在某个整数时间待在同一个位置人才会被打死。问人能否到达(n,m)。

思路:直接bfs即可,shot[t][x][y]表示在t时刻,是否有炮弹在(x,y)这个位置,可以预处理该数组。

注意:

1. 人不能穿越碉堡。

2. 炮弹每隔t秒发射一次,炮弹不能穿越其他碉堡。

3. 样例1中人必须在(2,0)这个位置待一秒避开炮弹才能继续走,所以总共需要8 + 1秒。

4.  剪枝:当前已经用了x能量,还剩w能量,距离终点dis,如果w < dis说明根本到不了终点,剪掉。距离是曼哈顿距离。

5. 输入的是m和n,代表m行,n列。后面的t表示间隔,v表示炮弹速度,x表示第x行,y表示第y列。

AC代码: 982ms

#include<cstdio>
#include<queue>
#include<vector>
#include<cmath>
#include<cstring>
using namespace std;
const int maxn = 100 + 3;
bool vis[1003][maxn][maxn], pic[maxn][maxn], shot[1003][maxn][maxn];
int n, m, k, d;

const int dx[] = {-1,1,0,0,0}; //上-下-左-右
const int dy[] = {0,0,-1,1,0};

struct castle {
	char dir;
	int t, v, x, y;
	castle() {
	}
	castle(char dir, int t, int v, int x, int y):dir(dir),t(t),v(v),x(x),y(y){
	}
};
vector<castle>vec;
void deal() {
	memset(shot, false, sizeof(shot));
	int len = k;
	for(int i = 0; i < len; ++i) {
		int x = vec[i].x, y = vec[i].y;
		int dir;
		switch(vec[i].dir) {
			case 'N': dir = 0; break;
			case 'S': dir = 1; break;
			case 'W': dir = 2; break;
			case 'E': dir = 3; break;
		}
		for(int j = 1;;++j) { //判断子弹到达的最远位置
			int px = x + j * dx[dir], py = y + j * dy[dir];
			if(px < 0 || py < 0 || px > n || py > m) break; //达到边界
			if(pic[px][py]) break; //有其他炮塔挡住
			if(j % vec[i].v == 0) { //子弹停留的坐标
				for(int h = j / vec[i].v; h <= d; h += vec[i].t) {
					shot[h][px][py] = true; //标记这个位置在j时刻会被子弹打到
				}
			}
		}
	}
}

struct Move{
	int time;
	int x, y;
	Move(){
	}
	Move(int time, int x, int y): time(time), x(x), y(y) {
	}
};

bool judge(int x, int y, int time) { //判断当前位置已用了time时间是否还有可能到达终点
	int man = abs(n - x) + abs(m - y); //曼哈顿距离
	if(d - time < man) return false;
	return true;
}

int bfs() {
	if(shot[0][0][0]) return -1;
	memset(vis, false, sizeof(vis));
	queue<Move>q;
	vis[0][0][0] = true;
	q.push(Move(0, 0, 0));
	while(!q.empty()) {
		Move p = q.front();
		q.pop();
		int x = p.x, y = p.y, t = p.time;
		if(!judge(x, y, t)) continue; //无法到达
		if(x == n  && y == m ) return p.time;
		for(int i = 0; i < 5; ++i) {
			int px = x + dx[i], py = y + dy[i];
			if(px < 0 || py < 0 || px > n || py > m) continue; //达到边界
			if(vis[t + 1][px][py] ||  pic[px][py] || shot[t + 1][px][py] || t + 1 > d) continue;
			vis[t + 1][px][py] = true;
			q.push(Move(t + 1, px, py));
		}
	}
	return -1;
}

int main() {
	while(scanf("%d%d%d%d", &n, &m, &k, &d) == 4) {
		getchar();
		memset(pic, false, sizeof(pic));
		vec.clear();
		char dir;
		int t, v, x, y;
		for(int i = 0; i < k; ++i) {
			scanf("%c%d%d%d%d", &dir, &t, &v, &x, &y);
			pic[x][y] = true; //标记碉堡位置
			vec.push_back(castle(dir, t, v, x, y));
			getchar(); //接收换行
		}
		deal();
		//for(int i = 0; i < 8; ++i) printf("%d\n", (int)shot[i][2][0]);
		int step = bfs();
		if(step == -1) printf("Bad luck!\n");
		else printf("%d\n", step);
	}

	return 0;
}

如有不当之处欢迎指出!

HDU - 3533 bfs [kuangbin带你飞]专题二的更多相关文章

  1. HDU - 2102 A计划 (BFS) [kuangbin带你飞]专题二

    思路:接BFS判断能否在限制时间内到达公主的位置,注意如果骑士进入传送机就会被立即传送到另一层,不会能再向四周移动了,例如第一层的位置(x, y, 1)是传送机,第二层(x, y, 2)也是传送机,这 ...

  2. HDU - 2612 bfs [kuangbin带你飞]专题一

    分别以两个人的家作为起点,bfs求得到每个KFC最短距离.然后枚举每个KFC,求得时间之和的最小值即可. 此题不符合实际情况之处:  通过了一个KFC再去另一个KFC可以吗? 出题人都没好好想过吗? ...

  3. HDU - 1495 bfs [kuangbin带你飞]专题一

    模拟倒水的过程,每次可以把第i个杯子的水向第j个杯子里面倒,这可能出现新的状态,不停的更新状态,指导某两个杯子的水等于S/2说明找到答案,如果所有状态搜索完毕仍然不能均分,则退出. 注意:如果S是奇数 ...

  4. HDU - 2181 dfs [kuangbin带你飞]专题二

    保存每个节点的下一个节点一直往下面走就行了,不能重复经过某个点,当经过的点达到20个而且当前节点的下一个节点是起点就打印答案. AC代码 #include<cstdio> #include ...

  5. 【算法系列学习三】[kuangbin带你飞]专题二 搜索进阶 之 A-Eight 反向bfs打表和康拓展开

    [kuangbin带你飞]专题二 搜索进阶 之 A-Eight 这是一道经典的八数码问题.首先,简单介绍一下八数码问题: 八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的 ...

  6. HDU - 3085 双向BFS + 技巧处理 [kuangbin带你飞]专题二

    题意:有两只鬼,一个男孩女孩被困在迷宫中,男孩每秒可以走三步,女孩只能1步,鬼可以两步且可以通过墙.问男孩女孩是否可以在鬼抓住他们之前会合? 注意:每秒开始鬼先移动,然后两人开始移动. 思路:以男孩和 ...

  7. HDU - 1067 Gap (bfs + hash) [kuangbin带你飞]专题二

    题意:    起初定28张卡牌的排列,把其中11,  21, 31, 41移动到第一列,然后就出现四个空白,每个空白可以用它的前面一个数的下一个数填充,例如43后面的空格可以用44填充,但是47后面即 ...

  8. HDU - 3567 Eight II (bfs预处理 + 康托) [kuangbin带你飞]专题二

    类似HDU1430,不过本题需要枚举X的九个位置,分别保存状态,因为要保证最少步数.要保证字典序最小的话,在扩展节点时,方向顺序为:down, left, right, up. 我用c++提交1500 ...

  9. HDU - 1241 dfs or bfs [kuangbin带你飞]专题一

    8个方向求联通块,经典问题. AC代码 #include<cstdio> #include<cstring> #include<algorithm> #includ ...

随机推荐

  1. Can’t open /dev/* exclusively. Mounted filesystem?解决

    1 错误提示:Can’t open /dev/* exclusively. Mounted filesystem? 做完软件RAID之后,根据鸟哥书上的操作,其实没有真正删除软件RAID,导致出现如下 ...

  2. VAssistX插件

    一.什么是VassistX? VassistX的全称是Visual Assist X,是whole tomato开发的一个非常好用的插件,可用于VC6.0及Visual Studio的各个版本(包括V ...

  3. Java - 二叉树递归与非递归

    树的定义具有递归特性,因此用递归来遍历比较符合特性,但是用非递归方式就比较麻烦,主要是递归和栈的转换. import java.util.Stack; /** * @author 李文浩 * @ver ...

  4. vs调试dll工程

    dll本身是没法运行的,必须在其它工程调用dll时候才会运行. 所以,调试dll首先要将调用dll的工程和dll工程联系起来. 解决方案中添加dll工程: 现在dll 和 应用程序两个工程就都在一个解 ...

  5. 蓝桥杯练习系统—基础练习 2n皇后问题

    问题描述 给定一个n*n的棋盘,棋盘中有一些位置不能放皇后.现在要向棋盘中放入n个黑皇后和n个白皇后, 使任意的两个黑皇后都不在同一行.同一列或同一条对角线上,任意的两个白皇后都不在同一行. 同一列或 ...

  6. BZOJ 4034: [HAOI2015]树上操作 [欧拉序列 线段树]

    题意: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a . 操作 3 :询问某个节点 x 到根的路径中所有点的点权和. 显然树链剖分可做 ...

  7. Codevs 3990 [中国剩余定理]

    模板题 注意如何得到[a,b]区间范围内的解 #include <iostream> #include <cstdio> #include <cstring> #i ...

  8. IT连创业系列:年终回顾录!

    一年不过一转眼,一光阴的青春又逝去了! 还有不到几天,就要进入新年快乐的祝福包围圈了. 在这归家之际,留文一篇,为这忙碌的一年创业留点回忆! IT连创业这一年走来: 大大小小的深坑,小小大大的困难,一 ...

  9. redux简明学习

    前面的话 这几天被redux折腾的够呛,看了很多视频,也看了很多资料.很多时候,感觉好像顿悟了,但实际上只是理解了其中的一个小概念而已.真正去做项目的时候,还是会卡壳.可能是学CSS和Javascri ...

  10. 利用Lua读写本地文件

    缘由 今天在使用Lua编写脚本时,需要用到读写文件的操作,很久没有使用Lua了,特写下此文来备忘一下. 简介 Lua对文件的操作与C对文件的操作基本一致,不管是参数还是方法.Lua中可以直接通过全局方 ...