题目大意:有一个由0和1组成的矩阵(m*n)表示迷宫,入口是左上角,出口是右下角,记录你走过的点的数字(0或者1),最后将会得到一个二进制串,要求二进制串最小。
解题思路:首先m+n-1步为最短路径,想想为什么,多走的话相当度二进制串要多一位,这一点可以用曼哈顿距离来理解,其次整个程序分成两段,一开始如果碰到0的话,bfs四个方向拓展,遇到1结束,统计x+y的最大值确定能走的最远距离(曼哈顿距离最远),如果这时候能走到终点,则整个程序结束。否则之后继续拓展,此时拓展是两个方向,下方和右方,直到抵达终点。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
const int maxn=1010;
int n,m,t;
char s[maxn][maxn];
int dx[]= {1,0,-1,0};
int dy[]= {0,1,0,-1};
int vis[maxn][maxn];
struct node
{
int x,y;
node(int x=0, int y=0, int dir=0):x(x),y(y) {}
};
void path()
{
memset(vis,0,sizeof(vis));
queue<node> q;
node u(1,1);
q.push(u);
vis[1][1]=1;
while(!q.empty())
{
node u=q.front();
q.pop();
// cout<<u.x<<" "<<u.y<<endl;
if(s[u.x][u.y]=='0')
{
for(int i=0; i<4; i++)
{
int new_x=u.x+dx[i];
int new_y=u.y+dy[i];
if(new_x<1||new_y<1||new_x>n||new_y>m||vis[new_x][new_y]) continue;
vis[new_x][new_y]=1;
q.push(node(new_x,new_y));
}
}
}
if(vis[n][m]&&s[n][m]=='0')
{
printf("0\n");
return;
}
int path1=-1;
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
if(vis[i][j]) path1=max(path1,i+j);
printf("1");
for(int i=path1; i<n+m; i++)
{
char ret='1';
for(int j=1; j<=n; j++)
{
if (1 <= i - j && i - j <= m &&vis[j][i - j])
{
if(i-j+1<=m) ret=min(ret,s[j][i-j+1]);
if(j+1<=n) ret=min(ret,s[j+1][i-j]);
}
}
printf("%c",ret);
for(int j=1; j<=n; j++)
{
if (1 <= i - j && i - j <= m &&vis[j][i - j])
{
if(i-j+1<=m&&ret==s[j][i-j+1]) vis[j][i-j+1]=1;
if(j+1<=n&&ret==s[j+1][i-j]) vis[j+1][i-j]=1;
}
}
}
printf("\n");
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)
scanf("%s",s[i]+1);
path();
}
return 0;
}