bfs经典

题意:地图上分别用‘.’表示硬地,‘#’表示禁地,‘E’表示易碎地面。你的任务操作一个1*1*2的长方体。长方体有两种状态分别为:立在地面上,躺在地面上。把长方体从入口移动到出口,求需要的最小步数。

原题链接:http://poj.org/problem?id=3322

#include<iostream>
#include<cstring> 
#include<queue>
#include<cstdio>
using namespace std;

struct node{
    int x;
    int y;
    int lie; //lie=0,代表竖着;lie=1,代表横着躺着;lie=2,代表垂直躺着 
};

char map[553][553];
int r,c;//r表示地图的行数,c表示地图的列数 
node start,end; //记录起点和终点的状态 
int dx[4]={-1,1,0,0};//表示左右方向的移动 
int dy[4]={0,0,1,-1};//表示上下方向的移动 
int dis[553][553][3];//记录起点走到x,y时候,状态为lie的路径长度 

void init()
{
    for(int i=1;i<=r;i++)
    {
        for(int j=1;j<=c;j++)
        {
            for(int k=0;k<3;k++)
            {
                dis[i][j][k]=-1;    
            }
        }
    }
}

bool judge(int x,int y)
{
    if(x<=r&&x>=1&&y<=c&&y>=1)
    {
        return true;
    }
    return false;
}

bool judge_stay(node n)//判断一个长方体呆着是否合理 
{
    if(!judge(n.x,n.y))
        return 0;
    if(map[n.x][n.y]=='#')
        return 0;
    if(n.lie==0&&map[n.x][n.y]!='.')
        return 0;
    if(n.lie==1&&(map[n.x][n.y+1]=='#'))
        return 0;
    if(n.lie==2&&(map[n.x+1][n.y]=='#'))
        return 0;
    return 1;    
}
/*
int dx_lie0[4]={0,0,-2,1};//lie=0的时候,向四个方向运动时,x的变化。 左右上下 
int dy_lie0[4]={-2,1,0,0};//lie=0的时候,向四个方向运动时,y的变化。 
int dx_lie1[4]={0,0,-1,1};
int dy_lie1[4]={-1,2,0,0};
int dx_lie2[4]={0,0,-1,2};
int dy_lie2[4]={-1,1,0,0}; 
*/

int dx_lie[3][4]={0,0,-2,1,0,0,-1,1,0,0,-1,2};
int dy_lie[3][4]={-2,1,0,0,-1,2,0,0,-1,1,0,0};
int lie[3][4]={1,1,2,2,0,0,1,1,2,2,0,0};//lie[i][j]表示状态为i的时候,向j方向反转后,lie的状态 


int bfs()
{
    queue<node>q;
    while(!q.empty())
    {
        q.pop();
    }
    q.push(start);
    dis[start.x][start.y][start.lie]=0;
    while(!q.empty())
    {
        node t=q.front();
        q.pop();
        for(int k=0;k<4;k++)
        {
            node next;
            next.x=t.x+dx_lie[t.lie][k];
            next.y=t.y+dy_lie[t.lie][k];
            next.lie=lie[t.lie][k];
            if(judge_stay(next))
            {
                if(dis[next.x][next.y][next.lie]==-1)
                {
                    //cout<<t.x<<' '<<t.y<<' '<<t.lie<<endl;
                    //cout<<"x"<<next.x<<endl;
                    //cout<<"y"<<next.y<<endl;
                    //cout<<"lie"<<next.lie<<endl;

                    q.push(next);
                    dis[next.x][next.y][next.lie]=dis[t.x][t.y][t.lie]+1;
                    //cout<<endl<<"x"<<next.x<<" y"<<next.y<<" lie"<<next.lie<<" dis"<<dis[next.x][next.y][next.lie];
                    //cout<<endl<<endl;
                    if(next.x==end.x&&next.y==end.y&&next.lie==end.lie)
                    {    
                        return dis[next.x][next.y][next.lie];
                    }
                }
            }
        }
    }
    return -1;
}

void fun_st_ed()        //处理起点和终点 
{
    for(int i=1;i<=r;i++)
    {
        for(int j=1;j<=c;j++)
        {
            if(map[i][j]=='O')
            {
                end.x=i;
                end.y=j;
                end.lie=0;
                map[i][j]='.';
            }
            if(map[i][j]=='X')
            {
                for(int k=0;k<4;k++)
                {
                    int next_x=i+dx[k];
                    int next_y=j+dy[k];
                    if(judge(next_x,next_y)&&map[next_x][next_y]=='X')
                    {
                        start.x=min(i,next_x);
                        start.y=min(j,next_y);
                        start.lie=k<2?2:1;//k<2的时候说明是上下有连着的X,k>2说明左右有连着的X; 
                        map[i][j]='.';
                        map[next_x][next_y]='.';
                    }
                } 
            }
            if(map[i][j]=='X')//说明周围四个点当中没有X。 
            {
                //cout<<"i"<<i<<"j"<<j<<endl;
                start.x=i;
                start.y=j;
                start.lie=0;
                map[i][j]='.';
            }
        }
    }
}



int main()
{
    while(cin>>r>>c)
    {
        if(r==0&&c==0)
        {
            break;
        }
        memset(map,0,sizeof(map));
        for(int i=1;i<=r;i++)
        {
            //for(int j=1;j<=c;j++)
            //{
                //cin>>map[i][j];
                scanf("%s",map[i]+1);
            //}
            //getchar();
        }
        init();
        fun_st_ed();
        //cout<<start.x<<start.y<<start.lie<<endl;
        int ans=bfs();
        if(ans==-1)
        {
            cout<<"Impossible"<<endl;
        }
        else
        {
            cout<<ans<<endl;
        }
     } 
    return 0;
}


/*
7 7
#######
#...X##
#..##O#
#....E#
#....E#
#.....#
#######
*/

解题思路:用bfs求最短路径。用数组表示前状态和后状态的关系。用dis数组记录最短路径的长度。

猜你喜欢

转载自www.cnblogs.com/hang-shao/p/10517872.html
BFS