zoukankan      html  css  js  c++  java
  • 【POJ1475】Pushing Boxes-A*(或BFS?)

    测试地址:Pushing Boxes

    题目大意:给定一个r*c的矩形地图,里面有一些石头,有石头的地方不能走,你一开始在S点,要将地图中的一个箱子B推到目标点T(玩过推箱子小游戏的同学应该很容易理解,没玩过的话我在这里解释一下,就是当你要往一个方向移动时,箱子正好在你要到达的地方,此时你和你的箱子都要往那个方向移动一步),箱子也不能被推到有石头的地方,求出一个表示路线的字符串,其中小写字母表示普通的移动,大写字母表示推着箱子时的移动,字母表示方向,要求推箱子的次数最少,如果有多解,输出总移动次数最少的,如果还是有多解,任意输出一个。如果不可能推到,输出“Impossible.”。

    做法:这道题目看上去比较复杂,我们来梳理一下。首先要确定搜索时要记录的状态,这个很容易能想到:人的位置和箱子的位置。由于题目中要求的最优解,我们还要附加两个值pushes和walk,表示推动箱子的移动数和平常的移动数,pushes优先级比walk高,然后和前面已经搜出的状态做双关键字比较,如果比以前的状态好,就可以加入优先队列中,优先队列的排序规则也是这个规则。输出路线的话,只要记录一个状态的“父节点”,即拓展到该节点并使该节点状态最优的点,如果箱子的位置到达了T,就从这个状态开始反着搜,判断行走的方向即可。怎么判断是否推动了箱子?只要查看箱子的坐标是否移动即可。还有一个地方坑了我一把,就是存储路线的字符数组一定要开大,因为一个点不一定只走一遍或两遍,所以无法轻易判断路线的长度,所以内存足够的情况下,只能开大一点保险。

    (这道题的确是好题...学习A*的同学一定要做一做)

    (听说还有双BFS的方法?有待学习)

    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    using namespace std;
    int r,c,move[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
    int fa[30][30][30][30][4],h[30][30][30][30][2],t=0;
    char a[30][30];
    bool flag;
    struct node {int x,y;} S,B,T;
    
    struct state
    {
      node s,b;
      int pushes,walk;
      bool operator < (state a) const
      {
        if (pushes!=a.pushes) return a.pushes<pushes;
    	else return a.walk<walk;
      }
    };
    
    void setbest(state p)
    {
      h[p.s.x][p.s.y][p.b.x][p.b.y][0]=p.pushes;
      h[p.s.x][p.s.y][p.b.x][p.b.y][1]=p.walk;
    }
    
    bool best(state p)
    {
      if (h[p.s.x][p.s.y][p.b.x][p.b.y][0]!=p.pushes) return p.pushes<h[p.s.x][p.s.y][p.b.x][p.b.y][0];
      else return p.walk<h[p.s.x][p.s.y][p.b.x][p.b.y][1];
    }
    
    bool can(int x,int y)
    {
      return x>=1&&x<=r&&y>=1&&y<=c&&a[x][y]!='#';
    }
    
    void outputpath(int sx,int sy,int g)
    {
      char r[10000];
      flag=1;
      int x1=sx,y1=sy,x2=T.x,y2=T.y,j=g;
      while(j>0)
      {
        int fx1,fx2,fy1,fy2;
    	char tmp='a';
    	fx1=fa[x1][y1][x2][y2][0];fy1=fa[x1][y1][x2][y2][1];
    	fx2=fa[x1][y1][x2][y2][2];fy2=fa[x1][y1][x2][y2][3];
    	if (fx2!=x2||fy2!=y2) tmp='A';
    	if (x1-fx1==-1) r[j]='N'-'A'+tmp;
    	if (x1-fx1==1) r[j]='S'-'A'+tmp;
    	if (y1-fy1==-1) r[j]='W'-'A'+tmp;
    	if (y1-fy1==1) r[j]='E'-'A'+tmp;
    	j--;x1=fx1,y1=fy1,x2=fx2,y2=fy2;
      }
      for(int i=1;i<=g;i++)
        printf("%c",r[i]);
    }
    
    void AStar()
    {
      memset(fa,0,sizeof(fa));
      memset(h,0x7f,sizeof(h));
      priority_queue<state> Q;
      state now,next;
      now.s=S,now.b=B;now.pushes=now.walk=0;
      Q.push(now);
      while(!Q.empty())
      {
        now=Q.top();
    	Q.pop();
    	if (now.b.x==T.x&&now.b.y==T.y) {outputpath(now.s.x,now.s.y,now.pushes+now.walk);break;}
    	for(int i=0;i<=3;i++)
    	  if (can(now.s.x+move[i][0],now.s.y+move[i][1]))
    	  {
    	    next.s.x=now.s.x+move[i][0];
    		next.s.y=now.s.y+move[i][1];
    	    if (now.b.x==now.s.x+move[i][0]&&now.b.y==now.s.y+move[i][1])
    		{
    		  if (!can(now.b.x+move[i][0],now.b.y+move[i][1])) continue;
    		  next.b.x=now.b.x+move[i][0];
    		  next.b.y=now.b.y+move[i][1];
    		  next.pushes=now.pushes+1;next.walk=now.walk;
    		}
    		else
    		{
    		  next.b.x=now.b.x;
    		  next.b.y=now.b.y;
    		  next.walk=now.walk+1;next.pushes=now.pushes;
    		}
    		if (best(next))
    		{
    		  fa[next.s.x][next.s.y][next.b.x][next.b.y][0]=now.s.x;
    		  fa[next.s.x][next.s.y][next.b.x][next.b.y][1]=now.s.y;
    		  fa[next.s.x][next.s.y][next.b.x][next.b.y][2]=now.b.x;
    		  fa[next.s.x][next.s.y][next.b.x][next.b.y][3]=now.b.y;
    		  setbest(next);
    		  Q.push(next);
    		}
    	  }
      }
    }
    
    int main()
    {
      while(scanf("%d%d",&r,&c)&&r&&c)
      {
        t++;
        for(int i=1;i<=r;i++)
    	{
    	  char s[30];
    	  scanf("%s",s);
    	  for(int j=1;j<=c;j++)
    	  {
    	    a[i][j]=s[j-1];
    	    if (s[j-1]=='S') S.x=i,S.y=j;
    		if (s[j-1]=='B') B.x=i,B.y=j;
    		if (s[j-1]=='T') T.x=i,T.y=j;
    	  }
    	}
    	
    	printf("Maze #%d
    ",t);
    	flag=0;
    	AStar();
    	if (!flag) printf("Impossible.");
    	printf("
    
    ");
      }
      
      return 0;
    }
    


  • 相关阅读:
    PNG文件格式具体解释
    opencv2对读书笔记——使用均值漂移算法查找物体
    Jackson的Json转换
    Java实现 蓝桥杯VIP 算法训练 装箱问题
    Java实现 蓝桥杯VIP 算法训练 装箱问题
    Java实现 蓝桥杯VIP 算法训练 单词接龙
    Java实现 蓝桥杯VIP 算法训练 单词接龙
    Java实现 蓝桥杯VIP 算法训练 方格取数
    Java实现 蓝桥杯VIP 算法训练 方格取数
    Java实现 蓝桥杯VIP 算法训练 单词接龙
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793893.html
Copyright © 2011-2022 走看看