POJ - 1475 Pushing Boxes

这题我是1A的(其实在POJ上交了无数次)

做的时候一开始还读错题了,冷静调样例时才发现要Push数最少时Walk最少

具体思路:BFS啦,只是状态好像要记很多多东西啦,什么人的位置,箱子的位置啦,推了几次啊,走了几步啊

用个优先队列好像会快很多

在加个最优性剪枝好像就更快了(不加就死循环了)

然后就没啥了

 

花絮:震惊! 某学生被续走两天的时间! 原因竟是........优先队列没有清空辣鸡多组数据

AC代码

#include<cstdio>
#include<cctype>
#include<cstring>
#include<queue>
using namespace std;
int n,m,t;
char mp[100][100];
const int dir[4][2]={{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
const char Dir[4] = {'S','N','E','W'};
struct point{int x,y;};
struct State{point box,man;int Push,Walk;};
int best[25][25][25][25][2];
bool operator <(State a,State b){if(a.Push!=b.Push)return a.Push>b.Push;else return a.Walk>b.Walk;}
inline void BecomeBest(const State& state){best[state.box.x][state.box.y][state.man.x][state.man.y][0]=state.Push,best[state.box.x][state.box.y][state.man.x][state.man.y][1]=state.Walk;}
priority_queue<State> q;
inline bool Batter(const State& state){if(best[state.box.x][state.box.y][state.man.x][state.man.y][0]!=state.Push) return best[state.box.x][state.box.y][state.man.x][state.man.y][0]>state.Push;return best[state.box.x][state.box.y][state.man.x][state.man.y][1]>state.Walk;}
inline bool isUreachable(point a){return a.x<=0||a.x>n||a.y<=0||a.y>m||mp[a.x][a.y]=='#';}
void printPath(point b,point m,int p,int w)
{
    if(p==0&&w==0)return;
    for(int i = 0; i < 4;i++)
    {
        point pm,pb;
        pm.x=m.x+dir[i][0],pm.y=m.y+dir[i][1];
        if(isUreachable(pm))continue;
        if(!(pm.x==b.x&&pm.y==b.y)&&best[b.x][b.y][pm.x][pm.y][0]==p&&best[b.x][b.y][pm.x][pm.y][1]==w-1)
        {
            printPath(b,pm,p,w-1),putchar(tolower(Dir[i]));
            break;
        }
        pb.x=b.x+dir[i][0],pb.y=b.y+dir[i][1];
        if(isUreachable(pb))continue;
        if(pb.x==m.x&&pb.y==m.y&&best[pb.x][pb.y][pm.x][pm.y][0]==p-1&&best[pb.x][pb.y][pm.x][pm.y][1]==w)
        {
            printPath(pb,pm,p-1,w),putchar(Dir[i]);
            break;
        }
    }
}
void solve()
{
    while (!q.empty())q.pop();
    int sx,sy,tx,ty,bx,by;
    memset(best,0x6F,sizeof(best));
    for (int i=1; i<=n; i++)
        for (int j=1; j<=m; j++)
            if(mp[i][j]=='S')sx=i,sy=j;
            else if(mp[i][j]=='B')bx=i,by=j;

    State now,nex;
    now.box.x=bx,now.box.y=by,now.man.x=sx,now.man.y=sy,now.Push=0,now.Walk=0,q.push(now),BecomeBest(now);
    while(!q.empty())
    {
        now=q.top(),q.pop();
        if(mp[now.box.x][now.box.y] == 'T')
        {
            printPath(now.box,now.man,now.Push,now.Walk),puts("");
            return;
        }
        for(int i = 0; i < 4; ++i)
        {
            nex=now,nex.man.x+=dir[i][0],nex.man.y+=dir[i][1];
            if(isUreachable(nex.man))continue;
            if(nex.man.x==now.box.x&&nex.man.y==now.box.y)
            {
                nex.box.x+=dir[i][0],nex.box.y+=dir[i][1];
                if(isUreachable(nex.box))continue;
                nex.Push++;
                if(!Batter(nex))continue;
                q.push(nex),BecomeBest(nex);
            }
            else
            {
                nex.Walk++;
                if(!Batter(nex))continue;
                q.push(nex),BecomeBest(nex);
            }
        }
    }
    puts("Impossible.");
}
int main()
{
    while (scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0)return 0;
        while(getchar() != '\n');
        for (int i=1; i<=n; i++)gets(mp[i]+1);
        printf("Maze #%d\n",++t);
        solve();
        puts("");
    }
    return 0;
}

 

posted @ 2017-11-03 19:00  橙子用户  阅读(163)  评论(0编辑  收藏  举报