版权声明:本文为博主原创文章,未经博主允许不得转载。 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;
}