必威体育Betway必威体育官网
当前位置:首页 > IT技术

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

时间:2019-08-23 05:11:05来源:IT技术作者:seo实验室小编阅读:60次「手机版」
 

八数码问题

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

时间限制: 20 Sec  内存限制: 128 MB

提交: 63  解决: 13

题目描述

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

输入:第一个3*3的矩阵是原始状态,第二个3*3的矩阵是目标状态。 

输出:移动所用最少的步数 

Input

2 8 3 

1 6 4 

7 0 5 

1 2 3 

8 0 4 

7 6 5 

Output

6

经验总结

这题可以说。。。有点坑了。。。折腾了几天,倒不是说这一题的坑多。。是自己身上的坑多º·(˚ ˃̣̣̥᷄⌓˂̣̣̥᷅ )‧º· 

  先说说这个题目的坑吧,首先题目说的有点不清楚,害的我这种小白都不知道要干什么0.0  后来百度了才知道,原来0是代表空格,只能移动空格位置,最终得到第二个矩阵的状态,  还有一个坑,八数码问题可能是无解的,所以,这题竟然没说无解的时候要输出什么?可能是。。测试数据中就没有无解的吧,测试完发现,果真木有。。(\#-_-)\┯━┯

再说说这个问题,这个问题本身。。。难度倒是不大,还在构思范围之内,手贱搜了一下网上的代码。。才发现,卧槽?还可以这样解??此处贴一大神的帖子 7种方法求解八数码问题 看完了这个帖子,妈耶。。脑阔疼。。映射方法三种(数组+哈希+map),搜索方法三种(BFS+DBFS+A*),而且一个比一个高效,让我等小白大开眼界,然后,我看到其中的康托展开,于是乎又手贱去搜了个帖子康托展开和逆康托展开  emmm这个倒是不难,可以理解( ´´ิ∀´ิ` )  get了一个新技能~  后来关于八数码问题无解的判别条件也去搜了搜  就搜到了一个大佬的帖子~判断N 数码是否有解 牛人总结 归并排序    万事俱备,只欠提交啦~

  

然鹅。。事情并没有我想象的那么顺利。。看了代码,又去查了一些代码规范以及自己不懂的撸码方式,比如:

1、在for循环中++i与i++到底有没有区别,只放在for循环里,区别不大,但是要明白他们的区别i++是先用后加,++i是先加后用,所以区别就是。。。看下面代码你就懂啦。

模拟a=i++;
temp=i;
i=i+1;
a=temp;

模拟a=++i;
i=i+1;
a=i;

i++需要多一个临时存储空间,操作上也要多一步赋值,所以效率上,++i要更快一些。

2、结构体可以内置初始化函数,这样的话生成一个新结构体就可以像C++中的构造函数一样写啦~,关于内置操作运算符的使用,我也学习到了。。。就比如:

struct node
{
	int cost;
	bool operator<(const node &no)const
	{
		return cost>no.cost;
	}
}

struct node
{
	int cost;
	friend bool operator<(const node &n1,const node &n2)const
	{
		return n1.cost>n2.cost;
	}
}

这两个代码的效果是一样的,但是表达上,参数数量不同,const修饰位置不同,而且一个是内置函数一个是友元函数,区别很多。。。但这里强调一下,const常量修饰,防止其更改参数内容,加&引用是为了高效,因为你又不准备修改它,所以传一个原参的地址指针过来,效率就很高,内存方面占用更小。

最后说说自己的问题吧,马虎!!while(scanf("%d",&n))竟然没有发现少加了一个取反位运算符~,导致输出一直超限。。。找不到原因,还以为是算法思想出了问题,就十分崩溃。。。

最终实现代码,是参考了上面大神的A*+BFS+map,这样比单纯的用BFS+数组标记在时间和空间上都快了至少两个数量级。。。最后奉上代码。。。大神请轻喷0.0

正确代码

#include <cstdio>
#include <map>
#include <queue>

using namespace std;
char goal[10];
int start,termination;
struct node
{
	int step,cost,num,pos;
	node(int n,int s,int p)
	{
		num=n;
		step=s;
		pos=p;
		compute();
	}
	bool operator<(const node &no)const
	{
		return cost>no.cost;
	}
	void compute()
	{
		int c=0;
		char temp[10];
		sprintf(temp,"%09d",num);
		for(int i=0;i<9;i++)
		{
			if(temp[i]!=goal[i])
				c++;
		}
		cost=step+c;
	}
};
int director[9][4]={{-1,-1,3,1},{-1,0,4,2},{-1,1,5,-1},
{0,-1,6,4},{1,3,7,5},{2,4,8,-1},
{3,-1,-1,7},{4,6,-1,8},{5,7,-1,-1}};
void swap(char str[],int a,int b)
{
	char temp=str[a];
	str[a]=str[b];
	str[b]=temp;
}
bool judge(char a[],char b[])
{
	int r1=0,r2=0;
	for(int i=0;i<9;i++)
	{
		if(a[i]=='0')
			continue;
		for(int j=0;j<i;j++)
		{
			if(a[j]=='0')
				continue;
			if(a[j]>a[i])
				r1++;
		}
	}
	for(int i=0;i<9;i++)
	{
		if(b[i]=='0')
			continue;
		for(int j=0;j<i;j++)
		{
			if(b[j]=='0')
				continue;
			if(b[j]>b[i])
				r2++;
		}
	}
	if(r1%2==r2%2)
		return true;
	else
		return false;
}
priority_queue<node> p;
map<int,bool> mp;
int combine(int num,int pos)
{
	char temp[10];
	int temp1;
	node s(num,0,pos);
	p.push(s);
	mp[num]=true;
	while(!p.empty())
	{
		s=p.top();
		p.pop();
		sprintf(temp,"%09d",s.num);
		for(int i=0;i<4;i++)
		{
			if(director[s.pos][i]!=-1)
			{
				swap(temp,s.pos,director[s.pos][i]);
				sscanf(temp,"%d",&temp1);
				if(s.num==termination)
					return s.step+1;
				if(mp.count(temp1)==0)
				{
					node r(temp1,s.step+1,director[s.pos][i]);
					p.push(r);
					mp[temp1]=true;
				}
				swap(temp,s.pos,director[s.pos][i]);
			}
		}
	}
}

int main()
{
	int n,pos;
	char temp[10];
	while(~scanf("%d",&n))
	{

		start=n;
		for(int i=0;i<8;i++)
		{
			scanf("%d",&n);
			start=start*10+n;
		}
		sprintf(temp,"%09d",start);
		for(int i=0;i<9;i++)
			if(temp[i]=='0')
				pos=i;
		termination=0;
		for(int i=0;i<9;i++)
		{
			scanf("%d",&n);
			termination=termination*10+n;
		}
		sprintf(goal,"%09d",termination);
		if(judge(temp,goal))
		{
			int count=0;
			count=combine(start,pos);
			printf("%d\n",count);
		}
		else
		{
			printf("-1\n");
		}
	}
	return 0;
}

相关阅读

记一次在西部数码上买域名的悲催经历

有一天,在西部数码上查询HK后缀的域名,发现在有好些3个字母单词的都没有注册,当时心理面那个激动呀,心想在这个年代居然还可以找到未

LED数码显示器的结构和工作原理

结构:由发光二极管显示字段组成,在单片机应用系统中通常使用七段LED数码管,由共阴极和共阳极两种。七段LED显示器中有八个发光二极管

74hc164如何驱动数码管

http://www.elecfans.com/dianlutu/187/20180129625897.html 74HCT164是高速硅门 CMOS 器件,与低功耗肖特基型 TTL (LSTTL) 器件的引

7种方法求解八数码问题

【八数码问题】//https://vijos.org/p/1360在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用

数码大师2013破解补丁|数码大师2013白金版注册破解补

下载来源出处:数码大师2013白金版破解补丁 数码大师这款软件实在是太贵了,这款数码大师2013白金版注册码生成器能够帮助您免费试用

分享到:

栏目导航

推荐阅读

热门阅读