题意:在一个只有‘0’和‘1’的矩阵中,找一条从(0,0)到(n,m)的字典序最小的一个路径。
做法:bfs。但是不能每条路径都搜,要按照一定层次的搜。如果(0,0)是‘0’,就从(0,0)开始找一个离终点最近的且值为‘0’的点。然后,从那个点开始进行按照层次来进行bfs。每个点的层次就是坐标的x和y加起来的值。每搜索一个层次,就找出该层次中最小的值,并将该层次中与最小值一样的点搜索到下一层。这样既能保证字典序是最小的,也能大大减少搜索量。
(但是比赛时写错小细节,wa到底……)
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
#include<string>
#include<set>
#include<queue>
#include<climits>
using namespace std;
const int maxn = 1001;
char mat[maxn][maxn];
bool vis[maxn][maxn];
int dirx[4] = { 0, 0, 1, -1 };
int diry[4] = { 1, -1, 0, 0 };
queue<pair<int, int> > que;
pair<int,int> bfs1(int n, int m)
{
//
while (!que.empty()) que.pop();
que.push(make_pair(0, 0));
vis[0][0] = true;
int maxed = 0, maxx=0, maxy=0;
while (!que.empty())
{
pair<int,int>cur = que.front();
que.pop();
int curx = cur.first, cury = cur.second;
if (curx + cury > maxed)
{
maxed = curx + cury;
maxx = curx;
maxy = cury;
}
if (mat[curx][cury] != '0') continue;
for (int i = 0; i < 4; i++)
{
int nxtx = curx + dirx[i];
int nxty = cury + diry[i];
if(nxtx<0 || nxtx>n || nxty<0 || nxty>m) continue;
if (!vis[nxtx][nxty])
{
que.push(make_pair(nxtx, nxty));
vis[nxtx][nxty] = true;
}
}
}
return make_pair(maxx, maxy);
}
void bfs2(int cur, int n, int m)
{
printf("1");
for (int i = cur; i < n + m; i++)
{
char mined = '1';
for (int j = 0; j <= n; j++)
{
int k =i - j;
if (k>=0 && k <= m&&vis[j][k])
{
mined = min(mined, mat[j+1][k]);
mined = min(mined, mat[j][k + 1]);
}
}
printf("%c", mined);
for (int j = 0; j <= n; j++)
{
int k =i - j;
if (k<0 || k>m||!vis[j][k]) continue;
if (mat[j][k + 1] == mined) vis[j][k + 1] = true;
if (mat[j + 1][k] == mined) vis[j + 1][k] = true;
}
}
printf("\n");
}
int main()
{
//freopen("d://1009.in", "r", stdin);
//freopen("d://out.txt", "w", stdout);
int T;
scanf("%d", &T);
while (T--)
{
int n, m;
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++)
{
scanf("%s", &mat[i]);
}
for (int i = 0; i < m; i++) mat[n][i] = '9';
for (int i = 0; i < n; i++) mat[i][m] = '9';
memset(vis, 0, sizeof(vis));
pair<int, int> ret = bfs1(n - 1, m - 1);
int cur;
if (mat[0][0] == '0') cur = ret.first + ret.second;
else cur = 0;
if (vis[n - 1][m - 1]&&mat[n-1][m-1]=='0') {
printf("0\n"); continue;
}
bfs2(cur, n - 1, m - 1);
}
}