hdoj 5335 walk out(bfs+模拟)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39562952/article/details/81394077

思路:很容易想到,如果起点是1,那么后面一定只能向右下走了,不然数位多了是第一致命的,然后考虑每一次走优先走0,没有0再走1。所以此时直接广搜到终点就是最短的答案。那么如果起点不是1呢?那么我们就可以先让前面有一些0,直到找到一个1之后又重复第一种情况。所以我们要找的是x+y最大位置1,因为找到1之后我们就要开始优先考虑数位最小了,只能向右下走,所以找到x+y最大的1是保证了位数最小。所以这里需要进行第二次bfs,去将所有(x+y)max的点找到,并依次从这些点开始出发重复第一种情况。(以上是抄大佬的https://blog.csdn.net/maxichu/article/details/48027761)这里我只谈谈自己对最后结果输出的做法,感觉跟大佬的有些不一样,可能简单点,每个状态都存下当前的字符串,因为每次都是贪心的找,所以一到终点,直接输出就好。不用像大佬一样回溯之前走过的路径;

代码如下:

#include<iostream>
#include<cmath>
#include<string>
#include<cstring>
#include<stdio.h>
#include<queue>
using namespace std;
int a, b;
char map[1100][1100];
int vis[1100][1100];
int dir[4][2] = { {1,0},{0,1},{-1,0},{0,-1} };
int zero[4400];
int judge(int x, int y)
{
	if (x < 0 || y < 0 || x >= a || y >= b)
	{
		return 0;
	}
	else
		return 1;
}
struct node
{
	int x, y;

	string step;
	node()
	{
	}
	node(int x, int y)
	{
		this->x = x;
		this->y = y;
		
	}
};
vector<node>bg;
void bfs2()
{
	queue<node>q;
	q.push(node(0, 0));
	int maxx = 0;
	while (!q.empty())
	{
		node temp = q.front();
		q.pop();
		for (int i = 0; i < 4; i++)
		{
			int xx = temp.x + dir[i][0];
			int yy = temp.y + dir[i][1];
			if (!judge(xx, yy) || map[xx][yy] == '1'||vis[xx][yy])//如果不可以走或者是1
			{
				continue;
			}
			vis[xx][yy] = 1;
			q.push(node(xx, yy));
			if (xx + yy > maxx)
			{
				maxx = xx + yy;
				bg.clear();
			}
			if (xx + yy == maxx)
			{
				bg.push_back(node(xx, yy));
			}
		}

	}
}
void bfs()
{
	queue<node> q;
	node t;
	bg.push_back(node(0, 0));
	vis[0][0] = 1;
	if (map[0][0] == '0')//如果起点就是0先找最远的0位置
	{
		bfs2();
		for (int i = 0; i < bg.size(); i++)
		{
			q.push(bg[i]);
			q.back().step = "0";
		}
		bg.clear();//这种地方该清空就清空。。。
	}
	else
	{
		t.x = 0;
		t.y = 0;
		t.step = "1";
		vis[t.x][t.y] = 1;
		q.push(t);
	}
	while (!q.empty())
	{
		t = q.front();
		q.pop();
		int x = t.x;
		int y = t.y;
		if (t.x == a - 1 && t.y == b - 1)//到了终点,直接输出
		{
			int len = t.step.length();
			int i;
			for (i = 0; i < len; i++)
			{
				if (t.step[i] == '1')
					break;
			}
			if (i == len)//如果路径上的都是0,记得最后输出一个0,否则消掉前缀0之后,就不出任何结果了
			{
				cout << "0" << endl;
				break;
			}
				
			for (; i < len; i++)
			{
				cout << t.step[i];
			}
			cout << endl;
			break;
		}
		/*
		精华部分啊!!!!!
		*/
		if (map[x][y] == '1' && zero[x + y])/*如果跟原点相同远的距离的地方有0,但是这个位置是1,
											那这条路直接放弃,因为如果别的走法可以是0,而走这里是1,那么0肯定小*/
			continue;
		for (int i = 0; i < 4; i++)
		{
			int xx = t.x + dir[i][0];
			int yy = t.y + dir[i][1];
			
			if (!judge(xx, yy)) continue;
			
			if (map[xx][yy] == '0')//标记这个位置可以是0,删掉该位置是1的情况
				zero[xx + yy] = 1;
			if (!vis[xx][yy])
			{
				vis[xx][yy] = 1;
				node tt;
				tt.step = (t.step + map[xx][yy]);//把选到的点,直接加在每个点的状态上
				tt.x = xx;
				tt.y = yy;
				q.push(tt);
			}
			
			
		}
	}


}
int main()
{
	
	int t;
	cin >> t;
	while (t--)
	{
		scanf("%d%d", &a, &b);
		memset(vis, 0, sizeof(vis));
		memset(zero, 0, sizeof(zero));
		for (int i = 0; i < a; i++)
		{
			scanf("%s", map[i]);
		}
		bfs();
	}
	




	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39562952/article/details/81394077