【SeedCoder2015年 热身题6 搜索】Move Game (题目)

本文介绍了一款基于3x3网格的游戏,玩家通过上下左右移动不同颜色的小球到达目标位置。文章详细解释了如何使用宽度优先搜索算法来找出解决这个游戏的最少移动步数,并提供了完整的C++代码实现。

【问题】


现有如下一款游戏,游戏的目的是通过”左,右,上,下”滑动来移动红,绿,蓝色的小球,每操作一次所有小球最多只能移动一步(与2048不同),其中灰色区域块为禁止区域,小球不能移动到该位置。若所有有色小球停留在对应的色区块下,则游戏结束。那么对于该游戏关卡,最少需要多少步才能完成。


【输入】

输入只由一组测试样例组成。该样例由两部分组成,第一部分为3×3的矩阵,矩阵每一行占据一列,每个数之间以Tab键隔开;其中0表示该单元未被小球和灰色壁垒占据,-1表示该单元被灰色壁垒占据,1表示被红色小球占据,2表示被绿色小球占据,3表示被蓝色小球占据;第二部分表示红,绿,蓝色块的位置,第一行表示红色色块的位置,第二行表示绿色色块的位置,第三行表示蓝色色块的位置。数字之间以Tab键隔开。

【输出】

对于每一次输出样例,输出最小的操作数。

【示例输入】

1         0             -1

3         2             0

-1         -1           0

1         2

0         1

0         0

--------------------------------------------------------------------------------------------------------------------------------------------------

【解答】

               该题目与上一道题目类似,都是利用宽度优先搜索。该示例代码未按照指定格式进行输出,输出了最短操作步骤,可以直接按照输出步骤完成该游戏。

//--------------------------------------【程序说明】-------------------------------------------
//		程序说明:上上下下ABAB
//		程序描述:搜索
//		IDE版本:Visual Studio 2013
//		作者:Arthur Lee
//------------------------------------------------------------------------------------------------  

//【1】头文件
#include <fstream>
#include <ctime>
#include <list>
#include <functional>//包含less<>等仿函数
#include <algorithm>
#include <deque>//包含deque类
using namespace std;

#define TIMER
//【2】函数声明
void InitialData();
bool BreadthFirstSearch();
//【3】定义枚举体,在几种方法中切换
enum Method
{
	BreadthFirst
};
enum Action{
	Left,Right,
	Up,Down
};
enum Color{
	Red=1,Green,Blue
};
class Point {
public:
	int x;
	int y;
	Point(){
		x = 0;
		y = 0;
	}
	Point(int x0, int y0) :x(x0), y(y0){}
	//Point(Point& p) :x(p.x), y(p.y){}
	bool operator ==(Point pos){
		return (x == pos.x&&y == pos.y);
	}
	bool operator !=(Point pos){
		return !(*this == pos);
	}
	Point& operator = (const Point& p){
		this->x = p.x;
		this->y = p.y;
		return *this;
	}
};

Point PosTemp[3];//全局Point变量,类实现需要放在这之前

//定义的判断准则
bool CompareWithX_IndexIncrease(const int& x1, const int& x2){
	return less<int>()(PosTemp[x1].x, PosTemp[x2].x);
}
bool CompareWithX_IndexDecrease(const int& x1, const int& x2){
	return greater<int>()(PosTemp[x1].x, PosTemp[x2].x);
}
bool CompareWithY_IndexIncrease(const int& x1, const int& x2){
	return less<int>()(PosTemp[x1].y, PosTemp[x2].y);
}
bool CompareWithY_IndexDecrease(const int& x1, const int& x2){
	return greater<int>()(PosTemp[x1].y, PosTemp[x2].y);
}
class State{
public:
	static Point FinalPoint[3];
	int Board[3][3];//游戏面板,0表示无占据,Red,Green,Blue表示有点占据。-1表示障碍物占据
	Point InitialPoint[3];//R,G,B
	list<Action> Routine;

	State& operator =(const State& s){
		for (int i = 0; i < 3; ++i)
			for (int j = 0; j < 3; ++j)
				this->Board[i][j] = s.Board[i][j];
		for (int i = 0; i < 3; ++i){
			this->InitialPoint[i] = s.InitialPoint[i];
		}
		this->Routine = s.Routine;
		return *this;
	}
	bool IsFinalState(){
		int i = 0;
		for (; i < 3; ++i){
			if (InitialPoint[i] != FinalPoint[i])
				break;
		}
		if (i < 3)
			return false;
		else
			return true;
	}
	bool operator == (State s){
		int i = 0;
		for (; i < 3; ++i){
			if (InitialPoint[i] != s.InitialPoint[i])
				break;
		}
		if (i < 3)
			return false;
		else
			return true;
	}

	bool MoveOneStep(Action act, State& result){//NOTE:为保证修改形参Result,该函数必须以State&作为参数~~!!
		int Order[3] = { 0, 1, 2 };//0 - Red,1-Green,2-Blue;表示三者排序指标
		for (int i = 0; i < 3; ++i)
			PosTemp[i] = InitialPoint[i];
		result = *this;//result 储存转换后的最终的结果
		bool flag = false;//表示MoveOneStep 是否改变了状态。
		switch (act)
		{
		case Left:
			sort(Order, Order + 3, CompareWithY_IndexIncrease);
			for (int i = 0; i < 3; ++i){
				if (InitialPoint[Order[i]].y >= 1 && 
					result.Board[InitialPoint[Order[i]].x][InitialPoint[Order[i]].y - 1] == 0)
				{
					result.Board[InitialPoint[Order[i]].x][InitialPoint[Order[i]].y] = 0;
					result.InitialPoint[Order[i]].y -= 1;
					result.Board[InitialPoint[Order[i]].x][InitialPoint[Order[i]].y - 1] = (Order[i] + 1);
					flag = true;
				}
			}
			break;
		case Right:
			sort(Order, Order + 3, CompareWithY_IndexDecrease);
			for (int i = 0; i < 3; ++i){
				if (InitialPoint[Order[i]].y<2 && 
					result.Board[InitialPoint[Order[i]].x][InitialPoint[Order[i]].y + 1] == 0)
				{
					result.Board[InitialPoint[Order[i]].x][InitialPoint[Order[i]].y] = 0;
					result.InitialPoint[Order[i]].y += 1;
					result.Board[InitialPoint[Order[i]].x][InitialPoint[Order[i]].y + 1] = (Order[i] + 1);
					flag = true;
				}
			}
			break;
		case Up:
			sort(Order, Order + 3, CompareWithX_IndexIncrease);
			for (int i = 0; i < 3; ++i){
				if (InitialPoint[Order[i]].x >= 1 && 
					result.Board[InitialPoint[Order[i]].x - 1][InitialPoint[Order[i]].y] == 0)
				{
					result.Board[InitialPoint[Order[i]].x][InitialPoint[Order[i]].y] = 0;
					result.InitialPoint[Order[i]].x -= 1;
					result.Board[InitialPoint[Order[i]].x - 1][InitialPoint[Order[i]].y] = (Order[i] + 1);
					flag = true;
				}
			}
			break;
		case Down:
			sort(Order, Order + 3, CompareWithX_IndexDecrease);
			for (int i = 0; i < 3; ++i){
				if (InitialPoint[Order[i]].x <2 && 
					result.Board[InitialPoint[Order[i]].x + 1][InitialPoint[Order[i]].y] == 0)
				{
					result.Board[InitialPoint[Order[i]].x][InitialPoint[Order[i]].y] = 0;
					result.InitialPoint[Order[i]].x += 1;
					result.Board[InitialPoint[Order[i]].x + 1][InitialPoint[Order[i]].y] = (Order[i] + 1);
					flag = true;
				}
			}
			break;
		default:
			break;
		}
		return flag;
	}

};
Point State::FinalPoint[3] = {};
//【4】变量声明
bool IsExistInHashTable(State);
deque<State> HashTable;//充当hashtable 的功能
State InitialState;
State Result;//存放最终的结果

int main(){
#ifdef TIMER
	clock_t start = clock();
#endif // TIMER
	ifstream fin("in.txt");
	if (fin.fail())
		return 1;
	ofstream fout("out.txt");
	Method method = Method::BreadthFirst;
	bool flag = false;
	while (!fin.eof())
	{
		InitialData();
		for (int i = 0; i < 3; ++i)
			for (int j = 0; j < 3; ++j){
				fin >> InitialState.Board[i][j];
				switch (InitialState.Board[i][j])
				{
				case 1://红色
					InitialState.InitialPoint[0].x = i;
					InitialState.InitialPoint[0].y = j;
					break;
				case 2://绿色
					InitialState.InitialPoint[1].x = i;
					InitialState.InitialPoint[1].y = j;
					break;
				case 3:
					InitialState.InitialPoint[2].x = i;
					InitialState.InitialPoint[2].y = j;
					break;
				default:
					break;
				}
			}
		fin >> State::FinalPoint[0].x >> State::FinalPoint[0].y
			>> State::FinalPoint[1].x >> State::FinalPoint[1].y
			>> State::FinalPoint[2].x >> State::FinalPoint[2].y;
		switch (method)
		{
		case BreadthFirst:
			flag = BreadthFirstSearch();
			break;
		default:
			break;
		}

		if (flag)//输出
		{
			fout << "the smallest steps to achieve the goal is " << Result.Routine.size() << "\n";
			while (!Result.Routine.empty())
			{
				switch (Result.Routine.front())
				{
				case Left:
					fout << "left" << "\t";
					break;
				case Right:
					fout << "right" << "\t";
					break;
				case Up:
					fout << "up" << "\t";
					break;
				case Down:
					fout << "down" << "\t";
					break;
				default:
					break;
				}
				Result.Routine.pop_front();
			}
		}
		else
			fout << "there is no answer!" << "\n";

		fout << "\n";
	}
	
#ifdef TIMER
	clock_t end = clock();
	double duration = (double)(end - start);
	fout << "runtime : " << duration << "ms" << endl;
#endif // TIMER
	fout.close();
	return 0;
}


//【5】函数实现
void InitialData(){
	HashTable.clear();
}

bool BreadthFirstSearch(){
	list<State> list_temp;
	State temp;
	list_temp.push_back(InitialState);
	HashTable.push_back(InitialState);

	while (!list_temp.empty()){
		temp = list_temp.front();
		list_temp.pop_front();

		for (int i = 0; i < 4; ++i){
			if (temp.MoveOneStep((Action)i, Result)){
				if (!IsExistInHashTable(Result)){
					Result.Routine.push_back((Action)i);
					list_temp.push_back(Result);
					HashTable.push_back(Result);
					if (Result.IsFinalState())
						return true;
				}
			}
		}
	}
	return false;
}

bool IsExistInHashTable(State s){
	for (int i = 0; i < HashTable.size(); ++i){
		if (HashTable[i] == s)
		{
			return true;
		}
	}
	return false;
}



内容概要:本文系统整理了《微软面试100完整版(含解析+备考指南)2026最新求职资源》,涵盖算法编程、逻辑思维、计算机基础、系统设计与工程实践、职场综合五大核心型,共100道高频原,均来自微软近十真实面试库,剔除过时内容,新增AI工程应用、轻量化系统设计等2026前沿考点。每道题目配有详细解思路与考察要点,覆盖数据结构、动态规划、位运算、网络协议、数据库事务、微服务架构、高并发设计等关键技术领域,并包含逻辑推理、工程排查、产品权衡等综合素质题目,全面适配微软海内外各岗位面试需求。此外,文章还提供分层刷策略、地域差异化备考建议及完整资源获取路径,助力求职者高效通关初面、复面与终面。; 适合人群:准备应聘微软的应届毕业生、1-5工作经验的技术岗从业者(如软件开发、算法、测试、数据、运维等),以及计划投递微软海外岗位的求职者;尤其适合缺乏系统面试准备、希望提升解思维与工程表达能力的人群。; 使用场景及目标:①针对微软技术面试中的算法进行专项突破,掌握最优解法与代码规范;②训练逻辑思维与系统设计能力,应对高阶岗位考察;③准备终面综合问,提升职场素养与岗位匹配度表达;④根据国内/海外不同考点调整复习重点,实现精准备考。; 阅读建议:此资源以真为核心,强调解思路而非死记硬背,建议按“分类刷—总结模板—模拟手撕—复盘优化”流程学习,重点关注代码边界处理、复杂度优化与中英文表达逻辑,结合自身背景补充项目复盘与系统设计练习,全面提升面试实战能力。
内容概要:本文围绕永磁同步电机(PMSM)的二阶线性自抗扰矢量控制系统展开深入研究,重点实现了基于Simulink的系统建模仿真。研究采用二阶线性自抗扰控制(LADRC)策略,结合扩张状态观测器(ESO)对系统内部动态和外部扰动进行实时估计与前馈补偿,有效提升了电机在负载突变、参数摄动等复杂工况下的转速控制精度、动态响应速度与系统鲁棒性。文中详细构建了电流环与转速环的双闭环矢量控制架构,系统分析了控制器关键参数的设计方法、观测器带宽的整定原则以及整体系统的稳定性条件,并通过大量仿真实验验证了所提出控制方案相较于传统PI控制在抗干扰能力、响应性能和鲁棒性方面的显著优越性。; 适合人群:具备自动控制理论、电机控制原理、现代控制理论等相关专业知识,熟悉Simulink/Matlab仿真环境,且有一定工程实践经验的电气工程、自动化、控制科学与工程等领域的硕士/博士研究生、科研人员及从事高性能电机驱动系统开发的工程技术人员。; 使用场景及目标:①为高等院校和科研机构提供先进电机控制算法的教学案例与科研实验平台,深化对自抗扰控制(ADRC)理论的理解;②为企业在高性能伺服驱动、新能源汽车电驱系统、工业自动化等领域的下一代控制器研发提供可靠的技术参考、仿真验证方案和原型设计基础;③帮助研究人员系统掌握ADRC的核心思想、设计流程及其在高精度运动控制系统中的具体工程实现方法。; 阅读建议:学习者应具备扎实的自动控制与电机学理论基础及Simulink建模能力,建议结合韩京清教授的经典ADRC文献进行原理性学习,深入理解ESO的观测机理与TD的安排机制。在仿真实践中,应动手调试控制器带宽、观测器增益等核心参数,对比分析不同扰动工况(如突加负载、转速指令跳变)下的系统响应曲线,以直观感受控制性能的差异。为进一步深化研究,可将该仿真模型与硬件在环(HIL)测试平台或实际电机实验平台对接,完成从算法设计、仿真验证到物理实现的完整闭环验证流程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值