蓝桥杯2017省赛C/C++A组题2跳蚱蜢(宽搜bfs)

题目:跳蚱蜢
如图所示:
在这里插入图片描述
有9只盘子,排成1个圆圈。
其中8只盘子内装着8只蚱蜢,有一个是空盘。
我们把这些蚱蜢顺时针编号为 1~8

每只蚱蜢都可以跳到相邻的空盘中,
也可以再用点力,越过一个相邻的蚱蜢跳到空盘中。

请你计算一下,如果要使得蚱蜢们的队形改为按照逆时针排列,
并且保持空盘的位置不变(也就是1-8换位,2-7换位,…),至少要经过多少次跳跃?

注意:要求提交的是一个整数,请不要填写任何多余内容或说明文字。

分析思路:
给9只盘子编号,用一维数组保存蚱蜢状态,一维数组的下标即盘子编号,每个数组元素存蚱蜢编号,元素值为0表示空盘。
在这里插入图片描述
于是蚱蜢初态为012345678,目标态为087654321。
因为空盘的左边第一个、第二个蚱蜢和右边的第一个、第二个蚱蜢可以往里跳,所以得出结论:1种状态通过一步变换可以衍生出4种状态。
解题关键已很明显,就是解决如何表示出空盘左一、左二、右一、右二的蚱蜢跳进空盘。经过以上设定和分析,蚱蜢跳进空盘相当于数组中0和其左一、左二、右一、右二元素交换位置,要实现这一操作,就需要获知0的的下标。结合盘子环形摆放的特点,令0的下标为pos,那么和0做交换的元素的下标可表示为(pos+1+9)%9,(pos+2+9)%9,(pos-1+9)%9,(pos-2+9)%9。(加9可防止下标溢出,可自行验证)

题解代码如下:(添加了额外计算程序运行时间的代码,可视需求增删)

#include<iostream>
#include<queue>
#include<set>
#include<string>
#include<time.h>//必须加后缀
using namespace std;

struct record{//用于记录变换状态
  string state;//记录各盘数字
  int step;//记录是第几步
  int pos;//用于记录空盘的位置(下标)
  record(string State,int Step,int Pos)
  {
    state=State;
    step=Step;
    pos=Pos;
  }
  record(){}
  void operator=(const record &rec)
  {
    state=rec.state;
    step=rec.step;
    pos=rec.pos;
  }
};

// //string作为内置数据类型,有默认比较规则,也可以不写
// struct cmpSet{//自定义比较规则
//   bool operator()(string s1,string s2)
//   {
//     return s1<s2;//不取等以排除重复状态
//   }
// };

string Origin="012345678";//初态
string Target="087654321";//目标态
queue<record> q;//保存搜索记录
set<string> st;//保存状态,使用默认比较规则
//set<string,cmpRecord>;//自定义了比较规则的写法

void add(string state,int step,int pos,int new_pos)
{
  swap(state[pos],state[new_pos]);
  if(st.find(state)==st.end()){//查重
    q.push(record(state,step+1,new_pos));
    st.insert(state);
  }
}

int main()
{
  clock_t start,finish;//记录开始,结束时刻
  double totaltime;//保存运行时间
  start=clock();//获取开始时间
  
  q.push(record(Origin,0,0));//加入初态
  st.insert(Origin);

  record rec;

  while(!q.empty())
  {
    rec=q.front();//取出队首元素
    if(rec.state==Target){//到达目标状态
      cout<<rec.step<<endl;//输出答案
      break;//跳出循环
    }
    //加9防止下标溢出
    add(rec.state,rec.step,rec.pos,(rec.pos+1+9)%9);//左一蚱蜢跳进空盘
    add(rec.state,rec.step,rec.pos,(rec.pos+2+9)%9);//左二蚱蜢跳进空盘
    add(rec.state,rec.step,rec.pos,(rec.pos-1+9)%9);//右一蚱蜢跳进空盘
    add(rec.state,rec.step,rec.pos,(rec.pos-2+9)%9);//右二蚱蜢跳进空盘
    q.pop();//队首出队
  }

  finish=clock();//获取结束时间
  totaltime=(double)(finish-start);//计算运行时间
  cout<<"The runtime is "<<totaltime<<"ms."<<endl;//输出运行时间

  return 0;
}

答案为20。运行结果如下。
在这里插入图片描述
总结:该题要点为宽搜BFS、环形数据的处理。

发布了21 篇原创文章 · 获赞 45 · 访问量 1286

猜你喜欢

转载自blog.csdn.net/qq_44643644/article/details/105451593
今日推荐