kuangbing题单(1)简单搜索UVA 11624 Fire!

先附上题目链接
这题做的有点迷茫,由于对时间复杂度的计算一直不是很熟练.这题最开始的想法用BFS的时候记录一下时间.当层数加深一层的时候就让火势先蔓延一次.用一个vector来存火焰格子即可(后面改用了自己实现的vector).但是TLE了好多发之后…放弃了这个方法.决定先预处理一下火势蔓延到各个方块的时间.只要当前时间比火势蔓延的时间小,就可以走,否则视为障碍物.如此就不会TLE了.但一时半会也没想出来我最先处理的方式有啥大方向上的错误…希望有大佬能帮我解答一下…
这是TLE的code:

#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <stack>
#include <string.h>
#include <algorithm>
#include <set>
#include <vector>
using namespace std;
const int INF = 0x3f3f3f3f;
const int mn = 1e3 + 10;
typedef long long ll;
int n, m;
int cnt;
struct node {
	int r, c, cost;
};
node J;
char maze[mn][mn];
bool vis[mn][mn];
int dr[4] = { 1,0,0,-1 };
int dc[4] = { 0,1,-1,0 };
node fire[mn*mn];
bool inside(int r, int c) {
	if (r >= 0 && r < n && c >= 0 && c < m) return true;
	return false;
}
int fireup(int r, int c) {
	for (int i = 0; i < 4; ++i) {
		int cr = r + dr[i], cc = c + dc[i];
		if (inside(cr, cc)) {
			if (maze[cr][cc] == '#') continue;
			if(maze[cr][cc] == 'F') continue;
			maze[cr][cc] = 'F';
			node x;x.r=cr;x.c=cc;x.cost = 0;
			fire[cnt++] = x;
		}
	}
	return 0;
}
bool bfs() {
	queue<node> q;
	q.push(J);
	vis[J.r][J.c] = 1;
	if (cnt) {
		int len = cnt;
		for (int i = 0; i < len; ++i) fireup(fire[i].r, fire[i].c);
	}
	int last = 0;
	while (!q.empty()) {
		node cur = q.front();
		q.pop();
		if (cur.r == 0 || cur.c == 0 || cur.r == n - 1 || cur.c == m - 1) {
			printf("%d\n",cur.cost+1);
			return true;
		}
		if (cur.cost == last + 1 && cnt) {
			int len = cnt;
			last = cur.cost;
			for (int i = 0; i < len; ++i) fireup(fire[i].r, fire[i].c);
		}
		for (int i = 0; i < 4; ++i) {
			int nr = cur.r + dr[i], nc = cur.c + dc[i];
			if (!inside(nr, nc)) continue;
			if (maze[nr][nc] == '#') continue;
			if (maze[nr][nc] == 'F') continue;
			if (vis[nr][nc]) continue;
			vis[nr][nc] = 1;
			node x;x.r=nr;x.c=nc;x.cost = cur.cost+1;
			q.push(x);
		}
	}
	return false;
}
int main() {
	int t;
	scanf("%d",&t);
	while (t--) {
		scanf("%d%d",&n,&m);
		cnt=0;
		for (int i = 0; i < n; ++i) {
			scanf("%s",maze[i]);
			for (int j = 0; j < m; ++j) {
				if (maze[i][j] == 'J') {
					J.r=i;
					J.c=j;
					J.cost=0;
				}
				if (maze[i][j] == 'F') {
					node x;x.r=i;x.c=j;x.cost = 0;
					fire[cnt++] = x;
				}
			}
		}
		memset(vis, 0, sizeof(vis));
		if(!bfs()) printf("IMPOSSIBLE\n");
	}

	return 0;
}

这是AC代码(因为是由上面代码魔改后的产物,所以还有不少优化的地方.以后再搞吧)

#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <stack>
#include <string.h>
#include <algorithm>
#include <set>
#include <vector>
using namespace std;
const int INF = 0x3f3f3f3f;
const int mn = 1e3 + 10;
typedef long long ll;
int n, m;
int cnt;
struct node {
	int r, c, cost;
};
node J;
char maze[mn][mn];
bool vis[mn][mn];
int firetime[mn][mn];
int dr[4] = { 1,0,0,-1 };
int dc[4] = { 0,1,-1,0 };
node fire[mn*mn];
bool inside(int r, int c) {
	if (r >= 0 && r < n && c >= 0 && c < m) return true;
	return false;
}
bool bfs() {
	queue<node> q;
	q.push(J);
	vis[J.r][J.c] = 1;
	while (!q.empty()) {
		node cur = q.front();
		q.pop();
		if (cur.r == 0 || cur.c == 0 || cur.r == n - 1 || cur.c == m - 1) {
			printf("%d\n",cur.cost+1);
			return true;
		}
		for (int i = 0; i < 4; ++i) {
			int nr = cur.r + dr[i], nc = cur.c + dc[i];
			if (!inside(nr, nc)) continue;
			if (maze[nr][nc] == '#') continue;
			if (vis[nr][nc]) continue;
			if(firetime[nr][nc] <= cur.cost+1) continue;
			vis[nr][nc] = 1;
			node x;x.r=nr;x.c=nc;x.cost = cur.cost+1;
			q.push(x);
		}
	}
	return false;
}
int main() {
	int t;
	scanf("%d",&t);
	while (t--) {
		scanf("%d%d",&n,&m);
		cnt=0;
		memset(firetime,0x3f,sizeof(firetime));
		memset(vis,0,sizeof(vis));
		for (int i = 0; i < n; ++i) {
			scanf("%s",maze[i]);
			for (int j = 0; j < m; ++j) {
				if (maze[i][j] == 'J') {
					J.r=i;
					J.c=j;
					J.cost=0;
				}
				if (maze[i][j] == 'F') {
					node x;x.r=i;x.c=j;x.cost = 0;
					fire[cnt++] = x;
					vis[i][j] = 1;
					firetime[i][j] = 0;
				}
			}
		}
		int len = cnt;
		queue<node> q1;
		for(int i=0;i<len;++i) q1.push(fire[i]);
		while(!q1.empty()){
			node cur = q1.front();
			q1.pop();
			for (int i = 0; i < 4; ++i) {
				int cr = cur.r + dr[i], cc = cur.c + dc[i];
				if (inside(cr, cc)) {
					if (maze[cr][cc] == '#') continue;
					if(vis[cr][cc]) continue;
					vis[cr][cc] = 1;
					node x;x.r=cr;x.c=cc;x.cost = cur.cost+1;
					firetime[cr][cc] = x.cost;
					q1.push(x);
				}
			}
		}
		memset(vis, 0, sizeof(vis));
		if(!bfs()) printf("IMPOSSIBLE\n");
	}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值