Codeup 宽搜入门八数字码问题

Problem C: 【宽搜入门】8数码难题

[Creator : Imported]

Time Limit : 20.000 sec Memory Limit : 128 MB

Description

初始状态的步数就算1,哈哈

输入:第一个33的矩阵是原始状态,第二个33的矩阵是目标状态。
输出:移动所用最少的步数

Input

2 8 3
1 6 4
7 0 5
1 2 3
8 0 4
7 6 5

Output

6

思路分析:

1.首先这个问题是宽搜的典型题目,当然也可以用多种方法做,例如这位大佬的解题七种方法解决八数字吗问题
2.这里因为我刚入门搜索,所以就用了一般的宽搜,思路是这样的:
首先用两个二维数组存储待处理的矩阵和目标矩阵,用0当作空的模块,其他在0模块的上下左右的数字都可以与之交换,模拟现实中拼图的过程,
3.然后就是普通的宽搜过程,数字0作为搜索的根节点入队,记录步数为1,当前的矩阵为待处理的矩阵,如果队列不为空就一直进入循环,进入循环后读取队首结构体变量top,然后队首出队,用两个一味数组存储上下左右的移动,
4.循环四次搜索队首元素的上下左右是否有符合条件的位置(符合条件就是该位置不越界,而且不能走上一层的上一层位置否则就走回去了)
5.将符合条件的位置信息,放在新的结构体变量的x,y 变量中,步数加 1 ,新定义一个矩阵用于模拟位置交换的操作:新位置(new_x , new_y)和结点的top.x,top.y,在矩阵中的元素交换位置(可以用 algorithm头文件下的swap(num1,num2)函数),然后把交换后的矩阵放入结构体中的当前矩阵变量(可以用 sting.h 头文件下的:memcpy(num1,num2,sizeof(num2))函数实现矩阵的赋值),子节点结构体入队
6.当前队首结点的当前矩阵和目标矩阵相同的时候结束搜索,输出结构体的步数变量,就是最少步数。

搜索的过程如下:

在这里插入图片描述

现在思路清楚了,就是去写代码了

#include <iostream>
#include <math.h>
#include <string.h> 
#include <queue>
using namespace std;
const int maxn=4; 
int d_x[4]={1,0,-1,0};
int d_y[4]={0,-1,0,1};
struct Node{
	int x,y,step;
	int current[maxn][maxn];
	int last[2];
}now,start,aim;
bool same(Node top)
{
		for(int i=0;i<3;i++)
	{
		for(int j=0;j<3;j++)
		{
			if(top.current[i][j]!=aim.current[i][j]) return false;
		}
	}
	return true;
}
bool iswill(int x ,int y )
{
	if(x<0 || y<0 || x>=3|| y>=3) return false;
	return true;
}
void bfs()
{
	start.step=1;
	queue<Node> q;
	q.push(start);
	while(!q.empty()){
		Node top=q.front();
		q.pop();
		if(same(top)) 
		{
			printf("%d\n",top.step);
			return ;
		}
		for(int i=0;i<4;i++)
		{
			int new_x=top.x+d_x[i];
			int new_y=top.y+d_y[i];
			if(iswill(new_x,new_y)&&(new_x!=top.last[0] || new_y!=top.last[1]))
			{
				now.x=new_x,now.y=new_y;
				now.step=top.step+1;
				now.last[0]=top.x,now.last[1]=top.y;
				int temp[4][4];
				memcpy(temp,top.current,sizeof(top.current));
				int t=temp[top.x][top.y];
				temp[top.x][top.y]=temp[new_x][new_y];
				temp[new_x][new_y]=t;
				memcpy(now.current,temp,sizeof(temp));
				q.push(now);
			}
		}
	}
	
}
int main()
{
	for(int i=0;i<3;i++)
	{
		for(int j=0;j<3;j++)
		{
			scanf("%d",&start.current[i][j]);
			//cin>>start.current[i][j];
			if(start.current[i][j]==0)
			{
				start.x=i,start.y=j;
			}
		}
	}
	for(int i=0;i<3;i++)
	{
		for(int j=0;j<3;j++)
		{
			scanf("%d",&aim.current[i][j]);
		}
	}
	bfs();
	return 0;
}
//y1 是c++ 源码中的一个double 类型的变量,所以一般变量命名的时候不要用y1
 

小结:

一开始提交的时候一直显示编译错误,但是在编译器上却没有显示有编译的问题,百度后了解到:y1 是c++ 源码中的一个double 类型的变量,所以一般变量命名的时候不要用y1 ,编译错误的原因就是使用了 变量y1,改后ac

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值