蓝桥杯卡片换位

/*
 *题目描述:
卡片换位
你玩过华容道的游戏吗?
这是个类似的,但更简单的游戏。
看下面 3 x 2 的格子
+---+---+---+
|  A  |  *   |  *   |
+---+---+---+
|   B  |      |  *  |
+---+---+---+
在其中放5张牌,其中A代表关羽,B代表张飞,* 代表士兵。还有一个格子是空着的。你可以把一张牌移动到相邻的空格中去(对角不算相邻)。游戏的目标是:关羽和张飞交换位置,其它的牌随便在哪里都可以。
输入格式:输入两行6个字符表示当前的局面
输出格式:
一个整数,表示最少多少步,才能把AB换位(其它牌位置随意)
例如,输入:
* A
**B
程序应该输出:
17
再例如,输入:
A B
***
程序应该输出:
12
 * */

刚看到 题目时想到的方法是BFS,先将原始的情况放入队列,然后取出比较,没有达到终止情况,从空位开始走一步,上下左右各一种情况,一共四种情况(当然,越界的可以忽略),将走一步的情况保存在队列中,然后依次取出比较,如果符合终止条件,则得到步数,因为是一步一步的情况比较,所以最先匹配到终止条件的一定是最少步数,如果不符合终止条件,继续从空格开始,上下左右走一步,放在队列后,所有循环大致是,从队列取出,比较,不符合就在取出的情况的基础上再走一步,然后再取出。。。然而我不是用这种方法的。。。

DFS方法就是从空格开始,上下左右来递归遍历,遇到终止情况则记录步数,跟原有步数比较,保证每次存储的都是最少的步数。

BFS是把每一步的所有情况保存起来,找到最少步数
DFS是遍历每一种能够到达终止条件的步数,取最小

其中有几个要点,
1、不必储存二维数组,只需保存A,B,和空格的 坐标即保存了整个局面
2、需要标记数组以免走回头路
3、标记数组在回来时需擦除,以保证另一种遍历方式可以遍历
4、方向向量数组保存每一个方向的x,y增量,方便每一次上下左右走

上代码:

public class huarongdao {
 static class Gezi{
  public int x;
  public int y;
  public Gezi() {
  }
 };
 static int go[][]={{0,-1},{0,1},{-1,0},{1,0}};
 static Gezi a;
 static Gezi b;
 static Gezi k;
 static int minstep=10000000;
 static int[][][][][][] vis;
 public static void main(String[] args) throws IOException {
  vis=new int[3][3][3][3][3][3];
  a=new Gezi();
  b=new Gezi();
  k=new Gezi();
  Scanner scanner=new Scanner(System.in);
  
 
  
  for(int i=0;i<2;i++){
   String string=scanner.next();
   string.trim();
   for(int j=0;j<3;j++){
    if (string.charAt(j)=='A') {
     a.x=i;
     a.y=j;
    }
    if (string.charAt(j)=='B') {
     b.x=i;
     b.y=j;
    }
    if (string.charAt(j)=='#') {
     k.x=i;
     k.y=j;
    }
   }
  }
  dfs(a.x,a.y,b.x,b.y,k.x,k.y,0);
  System.out.println(minstep);
  
  }


 private static void dfs(int ax,int ay,int bx,int by,int kx,int ky,int step) {
  
  if (ax==b.x&&ay==b.y&&bx==a.x&&by==a.y) {
   minstep=Math.min(minstep, step);
   return;
  }
  /*
   * A#B
***
   * */
  if(ax<0||ax>1||ay<0||ay>2){
   return;
  }
  if(bx<0||bx>1||by<0||by>2){
   return;
  }
  
  if(kx<0||kx>1||ky<0||ky>2){
   return;
  }
  
  if (vis[ax][ay][bx][by][kx][ky]==1) {
   return;
  }
  vis[ax][ay][bx][by][kx][ky]=1;
  for(int i=0;i<4;i++){
   int xx=kx+go[i][0];
   int yy=ky+go[i][1];
   if(xx==ax&&yy==ay){
    dfs(kx, ky, bx, by, xx, yy, step+1);
   }
   else {
    if(xx==bx&&yy==by){
     dfs(ax, ay, kx, ky, xx, yy, step+1);
    }
   
    else{
     dfs(ax, ay, bx, by, xx, yy, step+1);
    }
   }
   
  }
  vis[ax][ay][bx][by][kx][ky]=0;
  
 }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值