POJ 1475: 推箱子

表示被毒瘤题吓到了!(我要回家)

暴力出奇迹,骗分过样例。

数学先打表,DP看运气。

穷举TLE,递推UKE。

模拟MLE,贪心还CE。

想要骗到分,就要有方法。

图论背模板,数论背公式。

动规背方程,高精背代码。

如果都没背,干脆输样例。

模拟定想全,动规定找对。

贪心定证明,二分L M+1。

vis[i][j][k] 表示从(i,j) 的经过的k方向 有没有 走过!
因为如果普通BFS的vis是没有用的!
such as this

8 8
########
#.....T#
#..S...#
###B####
#......#
#......#
#......#
########

还要就是要知道,不一定是箱子的最短路会引起答案的正确,就是说箱子是找一条合适的路,而不是最短的路,所以不能在BFS完箱子之后,再枚举人的路径!,于是就是在BFS箱子的路径的时候顺便判断一下人的路径,那么在用一个struct 储存一个string 最后输出!

#pragma GCC optimize(3)
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <queue>
#include <string>
#define N 25
using namespace std;
int n,m,sx,sy,bx,by,ex,ey,fuck,vis[N][N][4],to[N][N];
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
char how[4]={'N','S','W','E'},sm[4]={'n','s','w','e'}; // the dirction
char s[N][N];
// x,y : people   tox,toy : box!
struct node{int x,y,tox,toy;string ans;}now,nxt,pre;
queue<node> G,S;
string temp;
inline bool check(int x,int y){if(x>=1&&x<=n&&y>=1&&y<=m&&s[x][y]!='#') return 1;return 0;}
bool Find(int startx,int starty,int tox,int toy,int canx,int cany)
{
    temp="";
    memset(to,0,sizeof to);
    while(!S.empty()) S.pop();
    node bb;
    bb.x=startx,bb.y=starty; S.push(bb);
    while(!S.empty())
    {
        node last=S.front(); S.pop();
        if(last.x==tox&&last.y==toy) {temp=last.ans;return true;}
        for(int i=0;i<4;i++)
        {
            node yy=last; yy.x+=dx[i];yy.y+=dy[i];
            if(!check(yy.x,yy.y) || (yy.x==canx&&yy.y==cany) || to[yy.x][yy.y]) continue;
            to[yy.x][yy.y]=1;
            yy.ans=last.ans+sm[i];
            S.push(yy);
        }
    }
    return false;
}
string BFS_BOX()
{
    now.x=sx,now.y=sy;  // start == perxon x ,y
    now.tox=bx,now.toy=by; // where box is  == box x,y
    now.ans="";
    while(!G.empty()) G.pop();
    G.push(now);
    while(!G.empty())
    {
        now=G.front(); G.pop();
        if(now.tox==ex && now.toy==ey)
           return now.ans;
        for(int i=0;i<4;i++)
        {
            // this means can people reach the box's back so that the box can move
            // we just need to let the box move and judge whether people can reach there!
            nxt=now;
            nxt.tox+=dx[i],nxt.toy+=dy[i];
            nxt.x=now.tox,nxt.y=now.toy;
            if(!check(nxt.tox,nxt.toy) || vis[nxt.tox][nxt.toy][i]) continue;
            if(i==0)
        {if(Find(now.x,now.y,now.tox+1,now.toy,now.tox,now.toy)) nxt.ans+=temp;else continue;}
            if(i==1)
        {if(Find(now.x,now.y,now.tox-1,now.toy,now.tox,now.toy)) nxt.ans+=temp;else continue;}
            if(i==2)
        {if(Find(now.x,now.y,now.tox,now.toy+1,now.tox,now.toy)) nxt.ans+=temp;else continue;}
            if(i==3)
        {if(Find(now.x,now.y,now.tox,now.toy-1,now.tox,now.toy)) nxt.ans+=temp;else continue;}
            vis[nxt.tox][nxt.toy][i]=1;
            nxt.ans+=how[i];
            G.push(nxt);

        }
    }
    return "Impossible.";
}
int main()
{
    while(~scanf("%d%d",&n,&m) &&n&&m)
    {
        memset(vis,0,sizeof vis);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                cin>>s[i][j];
                if(s[i][j]=='S') sx=i,sy=j;
                if(s[i][j]=='B') bx=i,by=j;
                if(s[i][j]=='T') ex=i,ey=j;
            }
        printf("Maze #%d\n",++fuck);
        cout<<BFS_BOX()<<endl;
        puts("");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值