45行代码AC_2017年第八届蓝桥杯C/C++ A组第二题(广搜模板+解题报告)

问题描述

有9只盘子,排成1个圆圈。
其中8只盘子内装着8只蚱蜢,有一个是空盘。
我们把这些蚱蜢顺时针编号为 1~8

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

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


思考与分析

给出结论: 对于从某一状态转换到另一状态,问最少需要多少步, 不出意外都是广搜。

广搜的优势在于:第一次遍历到的结果,一定就是最短路径或最少步数,特殊类型题除外。

接下来考虑本题

首先, 将盘子们看做一个一维数组, 通过取余的方式使他们逻辑上相连

接下来,构造队列,将盘子的初始状态入队,分四种情况(+1, +2 , -1 , -2 )进行广搜, 将得到的结果判重后入队

判重的原因是:有可能搜索到相同排列顺序的盘子们, 因此要定义判重数组, 或使用mep容器去重

蓝桥杯的广搜题真的挺少的, 不过套模板一般都能很轻松的解出来。


#include<bits/stdc++.h>
using namespace std;

int s = 123456789, t = 876543219;
int dir[4] = {
    
    -2, -1, 1, 2}, a[10];
bool index[1000000000];				//判断情况是否重复
	
int num(int a[]) {
    
    					//数组转变量 
	int sum = 0; 
	for(int i = 0; i < 9; i++) {
    
    
		sum *= 10; sum += a[i];
	}
	return sum;
} 

void bfs() {
    
    
	queue<int>q_index;		//记录位置情况
	queue<int>q_step;		//记录步数
	//队列初始化 
	index[s] = 1;
	q_index.push(s);
	q_step.push(1);
	
	int flag = 0;
	while(flag != 1) {
    
    
		int x = q_index.front();		//出队操作 
		int cnt = q_step.front();
		int k = 8, temp;
		while(x>0) {
    
    
			if(x%10==9) temp=k;	//记下空盘的位置
			a[k--] = x%10;
			x /= 10; 
		}
		for(int i = 0; i < 4; i++) {
    
    
			swap(a[temp], a[(temp+dir[i]+9)%9]);	//位置移动 
			int j = num(a);
			if(!index[j]) {
    
    
				if(j==t) {
    
      cout<<cnt<<'\n'; flag=1; }
				index[j] = 1;
				q_index.push(j);
				q_step.push(cnt+1); 
			} 
			swap(a[temp], a[(temp+dir[i]+9)%9]); //空盘一共需要跳四次,因此交换后还需换回来 
		}
		q_index.pop();
		q_step.pop();
	} 
} 


int main() {
    
    
	bfs();
return 0; } 

求三连 求三连! 啊!我第一个给博主三连!

猜你喜欢

转载自blog.csdn.net/weixin_43899069/article/details/108876757
今日推荐