poj2049Finding Nemo(优先队列+bfs)

->题目请戳这里<-

题目大意:二维坐标平面内给m个墙,n个门,每个墙4个参数:x,y,d,t。(x,y)为墙最左/下点坐标,d表示墙的姿势,d = 1表示墙是竖着的,即平行于y轴,d=0表示墙水平的,墙的厚度不计。每个门3个参数:x,y,d,意义与墙相同,门的长度默认1。墙的范围1-199(此处乃大坑,说了都是泪啊啊。。。)。现在给你一个坐标(f1,f2),求从(0,0)点到给定点至少要过几个门。除了给定的墙和门,其他都是空地。

题目分析:题意很明白,算法很清楚,bfs。这题算是一道比较不错的搜索题,如果没有那个大坑的话。因为这个题要自己把地图构造出来。构造的思路是这样的:首先将所有的边缩成点,我是将所有的横边往左端点缩,所有的竖边往上端点缩。这样每个点有2个状态的边:横边和竖边。每条边有3个状态:0表示空地,1表示墙,2表示门。判重也比较简单,直接开3维数组判重就可以了。这样我们就可以搜了,要用到优先队列。

详情请见代码:

#include <iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;
const int N = 205;
int map[N][N][2];//将门和墙缩成左上角一个点,
//所以每个点用2个状态标识,0表示水平,1表示竖直,
//每个状态用3个值表示具体状态,0表示什么都没有
//1表示墙,2表示门
bool flag[N][N][2];//判重
int m,n;
int si,sj;
int dx[] = {1,-1,0,0};
int dy[] = {0,0,1,-1};
struct node
{
    int i,j,door;
    friend bool operator < (struct node a,struct node b)
    {
        return a.door > b.door;
    }
}s,now;
//queue<node>lcm;
priority_queue<node>lcm;

void bfs()
{
    while(!lcm.empty())
        lcm.pop();
    s.door = 0;
    s.i = si;
    s.j = sj;
    lcm.push(s);
    while(!lcm.empty())
    {
        //now = lcm.front();
        now = lcm.top();
        //printf("%d  %d\n",now.i,now.j);
        //system("pause");
        lcm.pop();
        if(map[now.i][now.j][0] != 1)//可以向上走
        {
            if(!flag[now.i][now.j][0])
            {
                flag[now.i][now.j][0] = 1;
                if(map[now.i][now.j][0] == 2)
                    s.door = now.door + 1;
                else
                    s.door = now.door;
                s.i = now.i;
                s.j = now.j + 1;
                if(s.i == 0 && s.j == 0)
                {
                    printf("%d\n",s.door);
                    return;
                }
                if(s.i >= 0 && s.j >= 0 && s.i <= 202 && s.j <= 202)
                    lcm.push(s);
            }
        }
        if(map[now.i][now.j][1] != 1)//可以向left走
        {
            if(!flag[now.i][now.j][1])
            {
                flag[now.i][now.j][1] = 1;
                if(map[now.i][now.j][1] == 2)
                    s.door = now.door + 1;
                else
                    s.door = now.door;
                s.i = now.i - 1;
                s.j = now.j;
                if(s.i == 0 && s.j == 0)
                {
                    printf("%d\n",s.door);
                    return;
                }
                if(s.i >= 0 && s.j >= 0 && s.i <= 202 && s.j <= 202)
                    lcm.push(s);
            }
        }
        if(map[now.i + 1][now.j][1] != 1)//right
        {
            if(!flag[now.i + 1][now.j][1])
            {
                flag[now.i + 1][now.j][1] = 1;
                if(map[now.i + 1][now.j][1] == 2)
                    s.door = now.door + 1;
                else
                    s.door = now.door;
                s.i = now.i + 1;
                s.j = now.j;
                if(s.i == 0 && s.j == 0)
                {
                    printf("%d\n",s.door);
                    return;
                }
                if(s.i >= 0 && s.j >= 0 && s.i <= 202 && s.j <= 202)
                    lcm.push(s);
            }
        }
        if(now.j >= 1 && map[now.i][now.j - 1][0] != 1)//down
        {
            if(!flag[now.i][now.j - 1][0])
            {
                flag[now.i][now.j - 1][0] = 1;
                if(map[now.i][now.j - 1][0] == 2)
                    s.door = now.door + 1;
                else
                    s.door = now.door;
                s.i = now.i;
                s.j = now.j - 1;
                if(s.i == 0 && s.j == 0)
                {
                    printf("%d\n",s.door);
                    return;
                }
                if(s.i >= 0 && s.j >= 0 && s.i <= 202 && s.j <= 202)
                    lcm.push(s);
            }
        }
    }
    printf("-1\n");
    return;
}

int main()
{
    int x,y,d,t,i;
    while(~scanf("%d%d",&m,&n))
    {
        if(m == -1 && n == -1)
            break;
        memset(map,0,sizeof(map));
        while(m --)
        {
            scanf("%d%d%d%d",&x,&y,&d,&t);
            if(d)
            {
                for(i = y + 1;i <= y + t;i ++)
                {
                    map[x][i][1] = 1;
                }
            }
            else
            {
                for(i = x;i < x + t;i ++)
                {
                    map[i][y][0] = 1;
                }
            }
        }
        while(n --)
        {
            scanf("%d%d%d",&x,&y,&d);
            if(d)
                map[x][y + 1][1] = 2;
            else
                map[x][y][0] = 2;
        }
        double f1,f2;
        cin>>f1>>f2;
        //scanf("%lf%lf",&f1,&f2);
        if(f1 < 0 || f2 < 0 || f1 > 199 || f2 > 199)
        {
            printf("0\n");
        }
        else if(m == 0 && n == 0)
        {
            printf("0\n");
        }
        else
        {
            si = floor(f1);
            sj = ceil(f2);
            memset(flag,0,sizeof(flag));
            bfs();
        }
    }
    return 0;
}
//1516K	79MS
/*
8 9
1 1 1 3
2 1 1 3
3 1 1 3
4 1 1 3
1 1 0 3
1 2 0 3
1 3 0 3
1 4 0 3
2 1 1
2 2 1
2 3 1
3 1 1
3 2 1
3 3 1
1 2 0
3 3 0
4 3 1
1.5 1.5
4 0
1 1 0 1
1 1 1 1
2 1 1 1
1 2 0 1
1.5 1.7
1 6
1 2 1 5
0 2 0
0 3 0
0 4 0
0 5 0
0 6 0
0 7 0
0.5 5.5
4 0
1 1 0 1
1 1 1 1
1 2 0 1
2 1 1 1
1.5 1.4
3 1
1 1 0 1
1 1 1 1
1 2 0 1
2 1 1
1.5 1.4
8 8
1 1 1 3
2 1 1 2
3 1 1 3
4 1 1 3
1 1 0 3
2 2 0 2
2 3 0 2
1 4 0 3
2 1 1
2 2 1
3 1 1
3 2 1
3 3 1
1 1 0
3 3 0
4 3 1
2.5 3.5
-1 -1
*/
还是忍不住要吐槽一下这题,RE了大半天了,说了墙的范围是1-199,实际上会给这个范围之外的数据!!这不是坑么!!!!!!!!!!!!!!

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