官方解析:
If we require that the explorer could only move downward or rightward, this problem will be easier: the length of the binary number will always be n+m-1, and we could work this out length by length. At first, the length of the binary number is 1 (at the entrance). If the entrance is adjacent to some 0, the explorer would definitely go to these 0s; otherwise, he could only go to 1s. In either occasion, there will be several possible positions, but the binary numbers will always be same. After getting the minimum value and the possible positions of this length, we could walk the next step, by finding the adjacent 0s with this length's possible position. Finally, we could arrive at the exit.
Now return to the original problem: the explorer could move in any direction. However, is moving for long optimal? Absolutely not. A longer binary number is always larger than a short one, but do not forget the preceding 0s. In fact. The explorer could walk on any number of 0s at first, and still keep the binary number equal to 0. Therefore, we need to find all the positions that are connected by 0s with the entrance. The explorer would walk on these positions freely, and then step on the first 1. He should make the first 1 nearest to the exit. After that, we could use the solution in the first paragraph to solve the whole problem.
相应的解法:
#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
const int inf = 0x3f3f3f3f;
int mark[1010][1010], n, m, cnt; // cnt 表示可行点的个数;
char s[1010][1010];
struct node{
int x, y;
}_n[2010];
void init(){
scanf("%d%d", &n, &m);
for(int i = 0; i < n; ++i){
scanf("%s", s[i]);
}
}
int dir[4][2] = {{1, 0}, {0, 1}, {0, -1}, {-1, 0}};
void find_start(){
memset(mark, -1, sizeof(mark));
if(s[0][0] == '1'){
cnt = 1;
_n[0].x = 0;
_n[0].y = 0;
return ;
}
queue<node> q;
node cur, next;
cur.x = 0, cur.y = 0;
q.push(cur);
while(!q.empty()){
cur = q.front();
q.pop();
for(int i = 0; i < 4; ++i){
next.x = cur.x + dir[i][0];
next.y = cur.y + dir[i][1];
if(next.x < 0 || next.y < 0 || next.x >= n || next.y >= m)
continue;
if(mark[next.x][next.y] != -1)
continue;
if(s[next.x][next.y] == '1')
mark[next.x][next.y] = 1;
if(s[next.x][next.y] == '0'){
mark[next.x][next.y] = 0;
q.push(next);
}
}
}
if(mark[n - 1][m - 1] == 0){
cnt = 0;
return ;
}
cnt = 0;
int key = inf;
for(int i = 0; i < n; ++i){
for(int j = 0; j < m; ++j){
if(mark[i][j] == 1){
int x = n + m - i - j - 2; // 走到(n-1, m-1);
if(x < key){
cnt = 0;
_n[cnt].x = i;
_n[cnt++].y = j;
}
if(x == key){
_n[cnt].x = i;
_n[cnt++].y = j;
}
}
}
}
}
void bfs(){
queue<node> q1, q2;
node cur, next;
memset(mark, 0, sizeof(mark));
for(int i = 0; i < cnt; ++i){
mark[_n[i].x][_n[i].y] = 1;
q1.push(_n[i]);
}
printf("1");
if(mark[n - 1][m - 1] == 1)
return ;
while(1){
int flag = 1; // 找到0(flag = 0) 没找到flag = 1;
while(!q1.empty()){
cur = q1.front();
q1.pop();
for(int i = 0; i < 2; ++i){
next.x = cur.x + dir[i][0];
next.y = cur.y + dir[i][1];
if(next.x < 0 || next.x >= n || next.y < 0 || next.y >= m)
continue;
if(!mark[next.x][next.y]){
mark[next.x][next.y] = 1;
if(s[next.x][next.y] == '0')
flag = 0;
q2.push(next);
}
}
}
printf("%d", flag);
if(mark[n - 1][m - 1] == 1)
break;
while(!q2.empty()){
cur = q2.front();
q2.pop();
if(flag == 0){
if(s[cur.x][cur.y] == '0')
q1.push(cur);
}
else
q1.push(cur);
}
}
}
int main()
{
int T;
cin >> T;
while(T--){
init();
find_start();
if(cnt == 0)
printf("0\n");
else{
bfs();
printf("\n");
}
}
return 0;
}
我的AC代码:
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1010;
struct node
{
int x, y;
};
char a[maxn][maxn];
bool vis[maxn][maxn];
int dir[4][2] = {1,0, 0,1, -1,0, 0,-1};
int x, y, n, m;
bool check (int x, int y)
{
if (x<0 || y<0 || x>=n || y>=m)
return false;
return true;
}
void bfs ()
{
node p, q;
p.x = x, p.y = y;
queue <node> Q;
Q.push (p);
while (!Q.empty())
{
p = Q.front();
Q.pop();
for (int i=0; i<4; i++)
{
q.x = p.x + dir[i][0];
q.y = p.y + dir[i][1];
if (check(q.x, q.y) && !vis[q.x][q.y])
{
vis[q.x][q.y] = true;
if (a[q.x][q.y] == '0')
Q.push (q);
if (x + y < q.x + q.y)
x = q.x, y = q.y;
}
}
}
}
int main ()
{
int t;
scanf ("%d", &t);
while (t --)
{
memset (vis, false, sizeof(vis));
vis[0][0] = true;
scanf ("%d %d", &n, &m);
for (int i=0; i<n; i++)
scanf ("%s", a[i]);
x = y = 0;
if (a[x][y] == '0')
bfs ();
if (a[x][y] == '0')
putchar('0');
else
{
bool nowflag = false;
putchar ('1');
for (int i=x+y; i<n+m-2; i++)
{
bool flag = false;
for (x=0; x<=i; x++)
{
y = i - x;
if (!check(x, y) || !vis[x][y])
continue;
if (nowflag && a[x][y]=='1')
continue;
for (int j=0; j<2; j++)
{
int xx = x + dir[j][0];
int yy = y + dir[j][1];
if (!check(xx,yy))
continue;
vis[xx][yy] = true;
if (a[xx][yy] == '0')
flag = true;
}
}
nowflag = flag;
putchar (flag?'0':'1');
}
}
puts("");
}
return 0;
}