zoj1649 Rescue

本文介绍了如何使用BFS策略解决ZOJ1649救援问题。原来的DFS方法导致超时,改用BFS并优化,通过让天使寻找朋友的方式,寻找最少步数解救天使。关键在于每次更新最短步数节点并检查是否找到朋友。
摘要由CSDN通过智能技术生成

本题是多个朋友 "r" 去牢房解救天使 "a" 的故事,"#"是墙,"."是路,路的话走一格需要一步的时间,"x"是守卫,需要先杀死守卫再走过去,耗费两步的时间,问哪一个朋友能在最少步数把天使救出来。

本来很天真,用DFS写了一个,果断TLE了。

后来用BFS写,并且写的时候有一个取巧的地方,就是让天使去寻找朋友,而不是让朋友寻找天使,大概思路是每次把最少步数的节点赋给 节点 t ,然后判断该点是否为 "r",若是,直接break,若否,则把最少步数节点pop出优先队列,然后以 t 为基准向四个方向扩展,直到找出 "r"为止。

先贴一下超时代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<limits.h>

int m, n, min;
int x[4] = {1, 0, -1, 0};
int y[4] = {0, 1, 0, -1};
int sum[201][201];
char s[201][201];

void dfs(int r, int c, int step)
{
	if(r < 0 || c < 0 || r >= n || c >= m || step >= sum[r][c])
		return;
	sum[r][c] = step;
	if(s[r][c] == 'r')
	{
		min = min < step ? min : step;
		return;
	}
	for(int i = 0; i < 4; i++)
	{
		if(s[r + x[i]][c + y[i]] == '.')
			dfs(r + x[i], c + y[i], step + 1);
		else if(s[r + x[i]][c + y[i]] == 'x')
			dfs(r + x[i], c + y[i], step + 2);
		else if(s[r + x[i]][c + y[i]] == 'r')
			dfs(r + x[i], c + y[i], step + 1);
	}
}

int main(void)
{
	int i, j, flag;
	while(scanf("%d%d", &n, &m) != EOF)
	{
		flag = 0;
		min = INT_MAX;
		memset(sum, 1, sizeof sum);
		memset(s, 0, sizeof s);
		for(i = 0; i < n; i++)
			scanf("%s", s[i]);
		for(i = 0; i < n; i++)
		{
			for(j = 0; j < m; j++)
			{
				if(s[i][j] == 'a')
				{
					dfs(i, j, 0);
					flag = 1;
					break;
				}
			}
			if(flag)
				break;
		}
		if(min == INT_MAX)
			printf("Poor ANGEL has to stay in the prison all his life.\n");
		else
			printf("%d\n", min);
	}
}
</pre><p></p><p><span style="font-family:Microsoft YaHei;font-size:18px;">AC代码:</span></p><p><span style="font-family:Microsoft YaHei;font-size:18px;"></span><pre class="cpp" name="code">#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<queue>

using namespace std;

struct node
{
	int x, y, step;
	friend bool operator < (node a, node b)
	{
		return a.step > b.step;
	}
};

int main(void)
{
	int i, j, n, m, min, flag;
	int b[201][201];//标记是否已搜索过
	int r[4] = {1, 0, -1, 0};//行方向
	int c[4] = {0, 1, 0, -1};//列方向
	char s[201][201];
	node t, tt;
	while(scanf("%d%d", &n, &m) != EOF)
	{
		flag = 0;
		memset(b, 0, sizeof b);
		for(i = 0; i < n; i++)
		{
			scanf("%s", s[i]);
			for(j = 0; j < m; j++)
			{
				if(s[i][j] == 'a')
				{
					t.x = i;
					t.y = j;
					b[t.x][t.y] = 1;
					t.step = 0;
				}
			}
		}
		priority_queue<node> q;//步数小的优先级高,在队列顶端
		q.push(t);
		while(!q.empty())
		{
			t = q.top();
			if(s[t.x][t.y] == 'r')
			{
				flag = 1;
				min = t.step;
				break;
			}
			q.pop();//一定要把步数最少元素弹出,否则搜索无法进行
			for(i = 0; i < 4; i++)
			{
				if(t.x+r[i]>=0&&t.x+r[i]<n&&t.y+c[i]>=0&&t.y+c[i]<m&&!b[t.x+r[i]][t.y+c[i]])
				{
					if(s[t.x + r[i]][t.y + c[i]] == '.')
					{
						tt.x = t.x + r[i];
						tt.y = t.y + c[i];
						tt.step = t.step + 1;
						q.push(tt);
						b[t.x + r[i]][t.y + c[i]] = 1;
					}
					else if(s[t.x + r[i]][t.y + c[i]] == 'x')
					{
						tt.x = t.x + r[i];
						tt.y = t.y + c[i];
						tt.step = t.step + 2;
						q.push(tt);
						b[t.x + r[i]][t.y + c[i]] = 1;
					}
					else if(s[t.x + r[i]][t.y + c[i]] == 'r')
					{
						tt.x = t.x + r[i];
						tt.y = t.y + c[i];
						tt.step = t.step + 1;
						q.push(tt);
						b[t.x + r[i]][t.y + c[i]] = 1;
					}
				}
			}
		}
		if(flag)
			printf("%d\n", min);
		else
			printf("Poor ANGEL has to stay in the prison all his life.\n");
	}	
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值