• Hdu 1254 推箱子


    Problem地址:http://acm.hdu.edu.cn/showproblem.php?pid=1254

    看完这到题,我就觉得题目有一点没有说明白:数字3,也就是目标点,人可不可以走。

    事实证明,数字3是可以走的,所以在判断人是否能到达目的地时,要认为0和3都能走。

    这是第一点。

    接着才是我的思路:

    首先,这是一道搜索题(这简直是废话)。题目要求计算箱子所需的最小步数,而不是人的。每次移动箱子时,就要考虑人能否到达箱子的后面,这样,箱子才能被往前推。其次,在判断人是否能到达箱子的后面时,除了我刚说的注意点外,还有一点是需要注意的,就是此时人不能走到箱子的位置。也就是每次移动箱子时,就要把现在箱子的位置标记为人不能通过,待判断完后,再取消刚才对箱子的标记。接着是考虑箱子能否往回走,实际上对于每一点时,箱子可重复走到,但从每个方向走到一个点时只能走一次。同一个点不能被箱子从同一个发向走两次,至于为什么,可以这么想:如果同一个点能被箱子从同一个发向走两次,那么箱子就必然可以第三次从这个方向走到这点,也自然可以第四次,第五次,第六次。。。。。。所以需要一个数组来进行判断箱子是不是已经从这个方向走过这个点了。

    #include <iostream>
    #include <cstring>
    #include <queue>
    #include <cstdio>
    
    using namespace std;
    
    const int MAXN = 10;
    int maze[MAXN][MAXN]; // represents the inputing matrix
    int M, N; //M rows, N columns
    int dir[4][2] = { -1,0, 1,0, 0,-1, 0,1 }; // directions : up, down, left, right
    bool boxVis[MAXN][MAXN][MAXN]; // row, column, direction
    
    
    typedef struct point{
        int x;
        int y;
    }point; // just used as a point
    
    
    typedef struct node{
        int steps;
        int x, y;
        int from;
        point person;
        friend bool operator < ( node t1, node t2 )
        {
            return t2.steps < t1.steps;
        }
    }node; // used for the condition of box
    
    point target, startP, startBox;
    
    bool Is_reach( point pS, point pF ) // person start, person finish
    {
        queue <point> q;
        bool hash[M][N];
        memset( hash, false, sizeof(hash) );
        point t, next;
        t.x = pS.x;
        t.y = pS.y;
        hash[t.x][t.y] = true; // the start point
        q.push( t );
        int i;
        while( !q.empty() )
        {
            t = q.front();
            q.pop();
            if( t.x==pF.x && t.y==pF.y )
                return true;
            for( i=0;i<4;i++ )
            {
                next.x = t.x + dir[i][0];
                next.y = t.y + dir[i][1];
                if( next.x>=0 && next.x<M && next.y>=0 && next.y<N
                   && (maze[next.x][next.y]==0||maze[next.x][next.y]==3) // 推箱子的人可以走0(地板),也可以走3(目的地)
                   && !hash[next.x][next.y] ) // 0 means it is empty
                {
                    hash[next.x][next.y] = true;
                    q.push(next);
                }
            }
        }
        return false;  // if the person can't reach, return false
    }
    
    int BoxBfs()
    {
        priority_queue <node> q;
        node t, next;
        t.x = startBox.x;
        t.y = startBox.y;
        t.steps = 0;
        t.person.x = startP.x;
        t.person.y = startP.y;
        q.push( t );
        int record;
        int i;
        point pF; // 推箱子的人需要到的地方
        memset( boxVis, false, sizeof(boxVis) );
        while( !q.empty() )
        {
            t = q.top();
            q.pop();
            if( t.x==target.x && t.y==target.y )
                return t.steps;
            for( i=0;i<4;i++ )
            {
                next.x = t.x + dir[i][0];
                next.y = t.y + dir[i][1];
                pF.x = t.x - dir[i][0];
                pF.y = t.y - dir[i][1]; // 推箱子的人需要到的地方
                if( next.x>=0 && next.x<M && next.y>=0 && next.y<N && !boxVis[next.x][next.y][i]
                   && maze[next.x][next.y]!=1)
                {
                    record = maze[t.x][t.y];
                    maze[t.x][t.y] = 2;  // 标记, 使箱子现在所在的位置不能被人所走过
                    if( Is_reach( t.person, pF )  )
                    {
                        next.steps = t.steps + 1;
                        next.person.x = t.x;
                        next.person.y = t.y;
                        q.push( next );
                        boxVis[next.x][next.y][i] = true;
                    }
                    maze[t.x][t.y] = record;
                }
            }
        }
        return -1;
    }
    
    int main()
    {
        int T;
        int i,j;
        cin >> T;
        while( T-- )
        {
            scanf("%d%d", &M, &N);
            memset( boxVis, -1, sizeof(boxVis) );
            for( i=0;i<M;i++ )
            {
                for( j=0;j<N;j++ )
                {
                    scanf("%d", &maze[i][j]);
                    switch (maze[i][j]){
                        case 2: startBox.x = i; startBox.y = j;
                                maze[i][j] = 0; // avoiding that this point becomes a disreached point
                                break;
                        case 3: target.x = i; target.y = j;
                                //maze[i][j] = 0;
                                break;
                        case 4: startP.x = i; startP.y = j;
                                maze[i][j] = 0; // the reason is same with the reason before
                                break;
                    };
                }
            }
            cout << BoxBfs() << endl;
        }
        return 0;
    }
    /*
    test data:
    
    3 5
    4 0 0 0 0
    1 2 0 0 0
    0 0 0 0 3
    
    7 4
    0 0 0 0
    0 0 1 0
    0 2 0 3
    1 4 1 0
    1 0 1 0
    1 0 1 0
    1 0 0 0
    
    */
    
  • 相关阅读:
    Python之路第二篇——Python环境与安装
    div层、fieldset分组标签、table表格的居中特效的综合运用
    在不影响系统的情况下给C盘添加磁盘空间(分区工具)
    C# windowsFroms更换皮肤的简单使用
    第二代居民身份证阅读器GTICR100(国腾)接口类调用方法
    C# 指定字符串截取方法
    C# 报表(report)和LocalReport类如何实现打印?
    RewriterURL实现二级域名的访问
    如何修改VS2012产品使用权属于某某的名称?
    OS与Internet
  • 原文地址:https://www.cnblogs.com/Emerald/p/4115644.html
Copyright © 2020-2023  润新知