HDU 5335 Walk Out(BFS+BFS) 经典 2015 Multi-University Training Contest 4

Walk Out

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 506    Accepted Submission(s): 84


Problem Description
In an nm maze, the right-bottom corner is the exit (position (n,m) is the exit). In every position of this maze, there is either a 0 or a 1 written on it.

An explorer gets lost in this grid. His position now is (1,1) , and he wants to go to the exit. Since to arrive at the exit is easy for him, he wants to do something more difficult. At first, he'll write down the number on position (1,1) . Every time, he could make a move to one adjacent position (two positions are adjacent if and only if they share an edge). While walking, he will write down the number on the position he's on to the end of his number. When finished, he will get a binary number. Please determine the minimum value of this number in binary system.
 

Input
The first line of the input is a single integer T (T=10) , indicating the number of testcases.

For each testcase, the first line contains two integers n and m (1n,m1000) . The i -th line of the next n lines contains one 01 string of length m , which represents i -th row of the maze.
 

Output
For each testcase, print the answer in binary system. Please eliminate all the preceding 0 unless the answer itself is 0 (in this case, print 0 instead).
 

Sample Input
   
   
   
   
2 2 2 11 11 3 3 001 111 101
 

Sample Output
   
   
   
   
111 101
 

Author
XJZX
 

Source
2015 Multi-University Training Contest 4
 

题意:要求从(0,0)走到(n-1 , m-1)经过的位置里的值组合成二进制数值最小。

解题:先用BFS从(0,0)出发,去掉前导0,找出离(n-1 , m-1 )最近的一些位置为1,然后再从找出的这些位置开始出发(每个位置只走一次),用两个数组模似两个队列,交换使用,每次队列里面的位置值要么全为0,要么全为1,这样即保证了最短长度,而且也保证了字典序最小。

5
15 15
101010111011010
110011011000111
100011110100100
101101100110011
100011000110011
100111111111001
101001101001100
100101001100110
100111111000010
101001001000110
101100100110100
100100110010010
110100100100110
100010010010001
111111111001001


10100000000000000100100001001

#include<stdio.h>
#include<queue>
#include<iostream>
#include<string.h>
#include<string>
using namespace std;
const int N = 1015;

char mapt[N*N];
int fath[N*N],vist[N*N],dir[4][2]={1,0,0,1,0,-1,-1,0};
int n,m;

int inq[2],q[2][N*N] , tq[N*N] , minlen;
int ABS(int aa){return aa>0?aa:-aa;}
void bfs1(int st)
{
    int x,y,kk=0;
    memset(vist,0,sizeof(vist));

    inq[0]=inq[1]=0;
    minlen=ABS(n-1-st/m)+ABS(m-1-st%m);//找一个位置为1的离(n-1,m-1)位置最近的一些点

    if(mapt[st]=='0')
        tq[kk++]=st;
   vist[st]=1;

    while(kk)
    {
        st=tq[--kk];
        x=st/m; y=st%m;
        for(int e=0; e<4; e++)
        {
            int tx=x+dir[e][0] , ty=y+dir[e][1];
            if(tx>=0&&tx<n&&ty>=0&&ty<m&&vist[tx*m+ty]==0)
            {
                if(mapt[tx*m+ty]=='0')
                    tq[kk++]=tx*m+ty;
                else
                {
                    int tlen=ABS(n-1-tx)+ABS(m-1-ty);
                    if(minlen>tlen)minlen=tlen;
                }
                vist[tx*m+ty]=1;
            }
        }
    }
    for(int i=0; i<n; i++)
    for(int j=0; j<m; j++)
    if(vist[i*m+j]==1&&mapt[i*m+j]=='1'&&ABS(n-1-i)+ABS(m-1-j)==minlen)
    {
        q[0][inq[0]++]=i*m+j;
    }
}

void bfs2(int endd)
{
    int x,y,st,flag=0;
    memset(fath,-1,sizeof(fath));
//两个队列交换使用保证序列的长度一样
    while(inq[flag])
    {
        bool bb=0; //队列里的位置所在的格子值要么全是0,要么全1,这要才能保证字典序最小
        for(int i=0; i<inq[flag]; i++)
        {
             st=q[flag][i];
            x=st/m; y=st%m;
            for(int e=0; e<2; e++)//走两个方向:向右向下
            {
                int tx=x+dir[e][0] , ty=y+dir[e][1] ;
                int tst=tx*m+ty;
                if(tx>=0&&tx<n&&ty>=0&&ty<m)
                if(mapt[tst]=='0'&&vist[tst]==0)//先找0
                {
                     fath[tst]=st;
                    vist[tst]=1+vist[st];
                    if(tst==endd)
                    {
                        return ;
                    }
                    q[!flag][inq[!flag]++]=tst;
                    bb=1;
                }
            }
        }
        if(bb==0)
        for(int i=0; i<inq[flag]; i++)
        {
             st=q[flag][i];
            x=st/m; y=st%m;
            for(int e=0; e<2; e++)
            {
                int tx=x+dir[e][0] , ty=y+dir[e][1] ;
                int tst=tx*m+ty;
                if(tx>=0&&tx<n&&ty>=0&&ty<m)
                if(mapt[tst]=='1'&&vist[tst]==0)
                {
                     fath[tst]=st;
                    vist[tst]=1+vist[st];
                    if(tst==endd)
                    {
                        return ;
                    }
                    q[!flag][inq[!flag]++]=tst;
                }
            }
        }
        inq[flag]=0;
        flag=!flag;
    }
}
char str[N*N];
void prin(int endd)
{
     int k=0;
    while(endd!=-1)
    {
        //printf("<-(%d,%d)%c ",endd/m,endd%m,mapt[endd]);
        str[k++]=mapt[endd];
        endd=fath[endd];
    }
    while(k--)
    {
        printf("%c",str[k]);
    }
    printf("\n");
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=0; i<n; i++)
        {
            scanf("%s",str);
            for(int j=0; j<m; j++)
                mapt[i*m+j]=str[j];
        }

        int endd=n*m-1;
        bfs1(0);
        if(vist[endd]!=0)
        {
            printf("%c\n",mapt[endd]);
        }
        else
        {
            bfs2(endd);
            prin(endd);
        }
    }
}


你可能感兴趣的:(算法,搜索,bfs)