poj2049 Finding Nemo(建图+BFS+优先队列+特判)

poj2049 Finding Nemo(建图+BFS+优先队列+特判)
Time Limit: 2000ms Memory Limit: 65536kB

Description

Nemo is a naughty boy. One day he went into the deep sea all by himself. Unfortunately, he became lost and couldn’t find his way home. Therefore, he sent a signal to his father, Marlin, to ask for help.
After checking the map, Marlin found that the sea is like a labyrinth with walls and doors. All the walls are parallel to the X-axis or to the Y-axis. The thickness of the walls are assumed to be zero.
All the doors are opened on the walls and have a length of 1. Marlin cannot go through a wall unless there is a door on the wall. Because going through a door is dangerous (there may be some virulent medusas near the doors), Marlin wants to go through as few doors as he could to find Nemo.
Figure-1 shows an example of the labyrinth and the path Marlin went through to find Nemo.
poj2049 Finding Nemo(建图+BFS+优先队列+特判)_第1张图片
We assume Marlin’s initial position is at (0, 0). Given the position of Nemo and the configuration of walls and doors, please write a program to calculate the minimum number of doors Marlin has to go through in order to reach Nemo.

Input
The input consists of several test cases. Each test case is started by two non-negative integers M and N. M represents the number of walls in the labyrinth and N represents the number of doors.
Then follow M lines, each containing four integers that describe a wall in the following format:
x y d t
(x, y) indicates the lower-left point of the wall, d is the direction of the wall – 0 means it’s parallel to the X-axis and 1 means that it’s parallel to the Y-axis, and t gives the length of the wall.
The coordinates of two ends of any wall will be in the range of [1,199].
Then there are N lines that give the description of the doors:
x y d
x, y, d have the same meaning as the walls. As the doors have fixed length of 1, t is omitted.
The last line of each case contains two positive float numbers:
f1 f2
(f1, f2) gives the position of Nemo. And it will not lie within any wall or door.
A test case of M = -1 and N = -1 indicates the end of input, and should not be processed.

Output
For each test case, in a separate line, please output the minimum number of doors Marlin has to go through in order to rescue his son. If he can’t reach Nemo, output -1.

Sample Input

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 -1

Sample Output

5
-1

Source
Beijing 2004


题意并不复杂,容易想到广搜,但是步数最小并不保证最优解,所以队列要关于开门数目形成优先队列。大一基本算法知识还算扎实,上了大二很少学习基本算法了,学习数据结构也以理论学习定性学习纸上谈兵为主,毕竟基本算法掌握后很少会用到亲手写的复杂数据结构与算法。但是对于复杂问题的建模能力一直是大一OI/ACM式练习所欠缺的(大一上计算概论曾经写过北京地铁站算一点非主流不多的练习吧),这个问题算法并不复杂,但是却要自己建立模型,自己有条不紊磨合各个模块,调试实现,有一点大作业或者项目的风格,很适合目前的练习。

具体实现见代码,注意要特判Nemo初始位置。

另外,原来做题包括以下贴的代码visit有一个维度记录到这个位置的门数,事实上这是不需要的,可以改为记下到这点最小门数,比其小才入队,这样可以减少hash表一维的空间。


Accepted    21248kB 983ms   2297 B  G++ 
#include
#include
#include

using namespace std;

const int MAX_SIZE=199;
const int INF=0xFFFFFFFF;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};//u,r,d,l

struct state_type
{
    int x,y;
    int step;
    state_type(int _x,int _y,int _step):x(_x),y(_y),step(_step){};
    friend bool operator <(const state_type& s1,const state_type& s2)
    {
        return s1.step>s2.step;
    };
};

priority_queue q;
bool visit[MAX_SIZE+2][MAX_SIZE+2][500];
int cost[MAX_SIZE+2][MAX_SIZE+2][4];//cost[x][y][u:r:d:l]
int x0,y0;//Nemo
int sx,sy;

bool read_in();
void bfs();

int main()
{
    //freopen("input.txt","r",stdin);
    while (read_in())
    {
        /*
        for (int y=5;y>=0;y--)
        {
            for (int x=0;x<=5;x++)
                printf("(%2d/%2d/%2d/%2d)",cost[x][y][0],cost[x][y][1],
                cost[x][y][2],cost[x][y][3]);
            printf("\n");
        }
        */
        bfs();
    }
    return 0;
}

void bfs()
{
    int x,y,step,x1,y1,step1;
    state_type state(0,0,0);
    memset(visit,false,sizeof(visit));
    while (!q.empty())
        q.pop();
    q.push(state_type(0,0,0));
    while (!q.empty())
    {
        state=q.top();
        x=state.x;
        y=state.y;
        step=state.step;
        q.pop();
        //printf("%d %d %d\n",x,y,step);
        if (x==x0 && y==y0)
        {
            printf("%d\n",step);
            return;
        }
        for (int d=0;d<4;d++)
            if (cost[x][y][d]!=INF)
            {
                x1=x+dir[d][0];
                y1=y+dir[d][1];
                step1=step+cost[x][y][d];
                if (x1<0 || x1>sx+1 || y1<0 || y1>sy+1)
                    continue;
                if (!visit[x1][y1][step1])
                {
                    visit[x1][y1][step1]=true;
                    q.push(state_type(x1,y1,step1));
                }
            }
    }
    printf("-1\n");
    return;
}

bool read_in()
{
    int walls,doors,x,y,d,l;
    float fx,fy;
    scanf("%d%d",&walls,&doors);
    if (walls==-1 && doors==-1)
        return false;
    memset(cost,0,sizeof(cost));
    sx=sy=0;
    while (walls--)
    {
        scanf("%d%d%d%d",&x,&y,&d,&l);
        if (x>sx)
            sx=x;
        if (y>sy)
            sy=y;
        if (d==0)
        {
            for (int i=0;i1][0]=cost[x+i][y][2]=INF;
        }
        else if (d==1)
        {
            for (int i=0;i1][y+i][1]=cost[x][y+i][3]=INF;
        }
    }
    while (doors--)
    {
        scanf("%d%d%d",&x,&y,&d);
        if (x>sx)
            sx=x;
        if (y>sy)
            sy=y;
        if (d==0)
            cost[x][y-1][0]=cost[x][y][2]=1;
        else if (d==1)
            cost[x-1][y][1]=cost[x][y][3]=1;
    }
    scanf("%f%f",&fx,&fy);
    x0=fx;
    y0=fy;
    if (x0<1 || x0>sx || y0<1 || y0>sy)
        x0=y0=0;
    return true;
}

你可能感兴趣的:(Algorithm)