Finding Nemo POJ 2049(三维BFS)

来源:互联网 发布:学生 赚钱 知乎 编辑:程序博客网 时间:2024/05/05 12:22

思路:从题目上看,这个收索不是个对于一个物体(门或者墙)都是有两个大的属性,即坐标和摆放的方向,所以可以用一个三维的数组来表示,前两维代表坐标,后一维表示方向,然后这个三维数组有0,1,2三个值分别表示空地,门,墙。在者注意坐标的问题,统一左下移动(或者右上)。方便的是人的坐标直接就是浮点转化为整形。我们同时可以将问题转化为人想要出来迷宫需要走过多少门。

#include<cstdio>#include<cstring>#include<queue>#include<iostream>using namespace std;int mp[220][220][2],mi;//三维BFSstruct node{    int x,y,ans;};int jx[]={0,-1,0,1};int jy[]={1,0,-1,0};int  vis[220][220];void bfs(int s,int t){    int i,j;    node f1,f2;    queue<node>q;//队列    f1.x=s,f1.y=t;    f1.ans=0;    vis[f1.x][f1.y]=1;//标记的是方格的右上角,类似被困者所在的位置    mi=0x3f3f3f3f;    q.push(f1);    while(!q.empty() )    {        f1=q.front();//        q.pop();        if(f1.x>199||f1.y>199||f1.x==0||f1.y==0)        {            if(f1.ans<mi)                mi=f1.ans;            continue;        }        if(f1.ans>=mi)//此题用的队列好处是可以节省空间随时弹出元素            continue;//注意剪枝        f2.x=f1.x+jx[0];        f2.y=f1.y+jy[0];        if(!vis[f2.x][f2.y]&&mp[f1.x][f1.y][0]!=2)//向上走        {            if(mp[f1.x][f1.y][0]==1)//向上走时判断是否可走中的mp的下标是没有走之前的的mp值因上和右均属于本方格                f2.ans=f1.ans+1;//左与下都属于其他空格            else                f2.ans=f1.ans;            vis[f2.x][f2.y]=1;            q.push(f2);        }        f2.x=f1.x+jx[1];        f2.y=f1.y+jy[1];        if(!vis[f2.x][f2.y]&&mp[f2.x][f2.y][1]!=2)//向左走        {            if(mp[f2.x][f2.y][1]==1)                f2.ans=f1.ans+1;            else                f2.ans=f1.ans;            vis[f2.x][f2.y]=1;            q.push(f2);        }        f2.x=f1.x+jx[2];        f2.y=f1.y+jy[2];        if(!vis[f2.x][f2.y]&&mp[f2.x][f2.y][0]!=2)//向下走        {            if(mp[f2.x][f2.y][0]==1)                f2.ans=f1.ans+1;            else                f2.ans=f1.ans;            vis[f2.x][f2.y]=1;            q.push(f2);        }        f2.x=f1.x+jx[3];        f2.y=f1.y+jy[3];        if(!vis[f2.x][f2.y]&&mp[f1.x][f1.y][1]!=2)//向右走        {            if(mp[f1.x][f1.y][1]==1)                f2.ans=f1.ans+1;            else                f2.ans=f1.ans;            vis[f2.x][f2.y]=1;            q.push(f2);        }    }}int main(){    int n, m, i, j, a, b, t, d;    double x, y;    while(cin>>n>>m)    {        if(n==-1&&m==-1)            break;        memset(mp,0,sizeof(mp) );//mp必须清零!其值为2为有墙1为门,0为空地        for(i=0;i<n;i++)        {            cin>>a>>b>>d>>t;            if(d)                for(j=0;j<t;j++)                mp[a-1][b+j][1]=2;//此题的构图也是难点选择是坐下点表示的一个方格            else                for(j=0;j<t;j++)                mp[a+j][b-1][0]=2;        }        for(i=0;i<m;i++)        {            cin>>a>>b>>d;            if(d)                mp[a-1][b][1]=1;            else                mp[a][b-1][0]=1;        }        cin>>x>>y;        a=x,b=y;//直接将浮点型付给整形舍去小数点有利于将格子放缩到左下方的点上        if(a>199||b>199||a==0||b==0)        {            cout<<"0"<<endl;            continue;        }        memset(vis,0,sizeof(vis));        bfs(a,b);        if(mi==0x3f3f3f3f)        {            printf("-1\n");        }        else            printf("%d\n",mi);    }    return 0;}
0 0