zoj 1249 | poj 1475 Pushing Boxes

 题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=249


又是推箱子。。题目求的是推箱子所要的最少次数。  那么以箱子为开始点 进行BFS。每次判断人(BFS)能不能到达箱子所需推到的反方向。如果能救如队列。有几个细节需要注意。1,箱子移动时,箱子可以移动到人当前所在的位置。2,人移动时,人不能移动到箱子未改变状态时所在的位置。。然后模拟即可。



下面是AC代码:

#include<iostream>
#include<vector>
#include<cstdio>
#include<string>
#include<queue>
#include<cstring>
using namespace std;
int n,m;
char map[25][25];
int       dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
int other_dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int ex,ey,flag;
bool vis[25][25][25][25];
bool mark[25][25];
char op[]="nswe";
char big_op[]="NSWE";
string ans;
struct node{
    int b_x,b_y;
    int p_x,p_y;
    int step;
    string ans;
}s_pos;
bool cheack(int x,int y){
     return x>=0&&x<n&&y>=0&&y<m&&map[x][y]!='#';
     return false;
}
bool people_cango(node &cur,node last,int e_x,int e_y){
     queue<node > q;  node per;per=cur;   per.step=0;  per.ans="";
     memset(mark,false,sizeof(mark));
     q.push(per);
     mark[cur.p_x][cur.p_y]=true;

     while(!q.empty()){
         node now=q.front();  q.pop();
          if(now.p_x==e_x&&now.p_y==e_y){
             cur.ans+=now.ans;
             return true;
           }
         for(int i=0;i<4;i++){
             node next=now;     next.step+=1;
             next.p_x+=dir[i][0];   next.p_y+=dir[i][1];
             if(cheack(next.p_x,next.p_y)&&!mark[next.p_x][next.p_y]){
                 if(next.p_x==last.b_x&&next.p_y==last.b_y)  continue;  //遇见箱子
                 mark[next.p_x][next.p_y]=true;
                 next.ans+=op[i];
                 if(next.p_x==e_x&&next.p_y==e_y){
                    cur.ans+=next.ans;
                    return true;
                 }
                 q.push(next);
             }
         }
     }
    return false;

}
void bfs(){
     queue<node > q;
     memset(vis,false,sizeof(vis));     q.push(s_pos);
     vis[s_pos.b_x][s_pos.b_y][s_pos.p_x][s_pos.p_y]=true;
     while(!q.empty()){
         node now = q.front(); q.pop();

         for(int i=0;i<4;i++){
             node next = now;   next.step+=1;
             next.b_x+=dir[i][0];  next.b_y+=dir[i][1];

             int x=now.b_x+other_dir[i][0];                  //人要到达箱子的反面
             int y=now.b_y+other_dir[i][1];
             if(cheack(next.b_x,next.b_y)&&cheack(x,y)&&!vis[next.b_x][next.b_y]
                [now.b_x][now.b_y]){
            //     if(next.b_x==now.p_x&&next.b_y==now.p_y)  continue;
              //    cout<<next.p_x<<" "<<next.p_y<<endl;

                 if(people_cango(next,now,x,y)){
              //      cout<<x<<" "<<y<<endl;
                    next.p_x=now.b_x;
                    next.p_y=now.b_y;
                    next.ans+=big_op[i];
                     if(next.b_x==ex&&next.b_y==ey){
                        flag=1;
                        ans=next.ans;
                        return ;
                    }

                    vis[next.b_x][next.b_y][next.p_x][next.p_y]=true;
                    q.push(next);
                 }
             }


         }

     }

}
int main(){
    int ca=1;
    while(scanf("%d%d",&n,&m)!=EOF,n+m){

          for(int i=0;i<n;i++)  scanf("%s",map[i]);

          for(int i=0;i<n;i++){
              for(int j=0;j<m;j++){
              if(map[i][j]=='T'){
                  ex=i,ey=j;
              }
              if(map[i][j]=='B'){
                  s_pos.b_x=i;  s_pos.b_y=j;
              }
              if(map[i][j]=='S'){
                  s_pos.p_x=i;  s_pos.p_y=j;
              }
              }
          }
          

          flag=0; s_pos.step=0;  s_pos.ans="";
          bfs();
          cout<<"Maze #"<<ca++<<endl;
          if(flag){
             cout<<ans<<endl;
          }
          else
          cout<<"Impossible."<<endl;
          cout<<endl;
          

    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值