题目描述:
八方块移动游戏要求从一个含8个数字(用1-8表示)的方块以及一个空格方块(用0表示)的3x3矩阵的起始状态开始,不断移动该空格方块以使其和相邻的方块互换,直至达到所定义的目标状态。空格方块在中间位置时有上、下、左、右4个方向可移动,在四个角落上有2个方向可移动,在其他位置上有3个方向可移动。例如,假设一个3x3矩阵的初始状态为:
8 0 3
2 1 4
7 6 5
目标状态为:
1 2 3
8 0 4
7 6 5
则一个合法的移动路径为:
8 0 3 8 1 3 8 1 3 0 1 3 1 0 3 1 2 3
2 1 4 => 2 0 4 => 0 2 4 => 8 2 4 => 8 2 4 => 8 0 4
7 6 5 7 6 5 7 6 5 7 6 5 7 6 5 7 6 5
另外,在所有可能的从初始状态到目标状态的移动路径中,步数最少的路径被称为最短路径;在上面的例子中,最短路径为5。如果不存在从初试状态到目标状态的任何路径,则称该组状态无解。
请设计有效的(细节请见评分规则)算法找到从八方块的某初试状态到某目标状态的所有可能路径中的最短路径,并用C/C++实现。
输入数据:
程序需读入已被命名为start.txt的初始状态和已被命名为goal.txt的目标状态,这两个文件都由9个数字组成(0表示空格,1-8表示8个数字方块),每行3个数字,数字之间用空格隔开。
输出数据:
如果输入数据有解,输出一个表示最短路径的非负的整数;如果输入数据无解,输出-1。
自测用例:
评分规则:
1)我们将首先使用和自测用例不同的10个start.txt以及相同的goal.txt,每个测试用例的运行时间在一台Intel Xeon 2.80GHz 4 CPU/6G 内存的Linux机器上应不超过10秒(内存使用不限制),否则该用例不得分;
2)每个选手的总分(精确到小数点后6位)=10秒钟内能产生正确结果的测试用例数量x10+(1/产生这些正确结果的测试用例的平均运行毫秒);
3)如果按此评分统计仍不能得出总决赛将决出的一、二、三等奖共计九名获奖者,我们将先设N=2,然后重复下述过程直至产生最高的9位得分:用随机生成的另外10个有解的start.txt再做测试,并对这10*N个测试用例用2)中公式重新计算总分,N++。
//冠军ACRush的代码:
//转载自:http://star.baidu.com/data/demo/ACRush.txt
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const int hashsize=70001;
const int maxnode=50000;
const int maxp=40;
const int ten[]={1,10,100,1000,10000,100000,1000000,10000000,100000000};
const int C[]={2,3,2,3,4,3,2,3,2};
const int EP[][4]={{1,3,0,0},{0,2,4,0},{1,5,0,0},{0,4,6,0},{1,3,5,7},{2,4,8,0},{3,7,0,0},{4,6,8,0},{5,7,0,0}};
struct Tlist
{
int data,d;
Tlist *next;
};
struct Thashpoint
{
int data;
Thashpoint *next;
};
//Memory
int ID;
Tlist listM[maxnode],*q;
Thashpoint hashM[maxnode],*p;
//data
int src,dest;
//heap
Tlist *head[maxp],*expand[maxp],*lp1,*lp2;
//Hash
Thashpoint *hash[hashsize];
//expand
int nowp,A[9],arcT[9],dist[9][9],b,depth,swap[9][9];
int data,G,newdata,newG;
bool find_answer;
void readdata(const char *filename,int &data)
{
int i,v;
FILE *f=fopen(filename,"r");
data=0;
for (i=0;i<9;i++)
{
fscanf(f,"%d",&v);
data=data+v*ten[i];
}
fclose(f);
}
bool check_noanswer()
{
int p[9],i,b1,b2;
bool vis[9];
for (i=0;i<9;i++)
p[i]=arcT[src/ten[i]%10];
for (b1=0; src/ten[b1]%10!=0;b1++);
for (b2=0;dest/ten[b2]%10!=0;b2++);
int countP=0;
memset(vis,false,sizeof(vis));
for (i=0;i<9;i++)
if (!vis[i])
{
countP++;
for (int k=i;!vis[k];k=p[k])
vis[k]=true;
}
return (countP-dist[b1][b2])%2==0;
}
void preprocess()
{
ID=0;
find_answer=false;
memset(hash,0,sizeof(hash));
memset(head,0,sizeof(head));
memset(expand,0,sizeof(expand));
for (int k=0;k<9;k++)
arcT[dest/ten[k]%10]=k;
for (int u=0;u<9;u++)
for (int v=0;v<9;v++)
{
dist[u][v]=abs(u/3-v/3)+abs(u%3-v%3);
swap[u][v]=ten[u]-ten[v];
}
}
void addnode()
{
if (newdata==dest)
{
printf("%d\n",depth);
find_answer=true;
return;
}
int address=newdata%hashsize;
for (p=hash[address];p!=NULL;p=p->next)
if (p->data==newdata)
return;
if (ID==maxnode)
return;
p=&hashM[ID];
p->data=newdata;
p->next=hash[address];
hash[address]=p;
q=&listM[ID];
ID++;
q->data=newdata;
q->d=depth;
if (newG>=maxp)
return;
if (newG==nowp)
{
q->next=expand[depth];
expand[depth]=q;
}
else
{
q->next=head[newG];
head[newG]=q;
}
}
void solve()
{
nowp=-1;
newdata=src;
newG=0;
for (int k=0;k<9;k++)
if (src/ten[k]%10!=0)
newG+=dist[arcT[src/ten[k]%10]][k];
depth=0;
addnode();
if (find_answer)
return;
for (int p=0;p<maxp;p++) if (head[p]!=NULL)
{
nowp=p;
for (lp1=head[p];lp1!=NULL;lp1=lp2)
{
lp2=lp1->next;
lp1->next=expand[lp1->d];
expand[lp1->d]=lp1;
}
for (int d=0;d<=p;d++)
for (;expand[d]!=NULL;)
{
data=expand[d]->data;
G=p-expand[d]->d;
depth=expand[d]->d+1;
expand[d]->d=-2;
expand[d]=expand[d]->next;
for (b=0;data/ten[b]%10!=0;b++);
for (int v=0;v<C[b];v++)
{
int u=EP[b][v];
int c=data/ten[u]%10;
newdata=data+swap[b][u]*c;
c=arcT[c];
newG=depth+G-dist[c][u]+dist[c][b];
addnode();
if (find_answer)
return;
}
}
}
printf("-1\n");
}
int main()
{
readdata("start.txt",src);
readdata("goal.txt",dest);
preprocess();
if (check_noanswer())
printf("-1\n");
else
solve();
return 0;
}
分享到:
相关推荐
《八数码问题C++源代码解析》 八数码问题,又称滑动拼图或15拼图,是人工智能领域中的一个经典问题,它基于九宫格的布局,目标是通过有限次的移动操作将打乱的数字方块恢复到初始的有序状态。在这个问题中,每个...
C++实现的人工智能原理实验:八数码问题源代码+实验报告 本实验课程是计算机、智能、物联网等专业学生的一门专业课程,通过实验,帮助学生更好地掌握人工智能相关概念、技术、原理、应用等;通过实验提高学生编写...
人工智能中经典的八数码问题的c语言实现,可以自己输入初始状态
采用Java编写的八数码问题,完美解决!
在给定的“八数码问题”(也称为“滑动拼图游戏”)中,A*算法被用来解决如何通过最少的移动次数将打乱的数字方块恢复到有序状态。下面将详细介绍A*算法及其在八数码问题中的应用。 A*算法的核心在于它的评估函数,...
学习并理解这些源代码,开发者可以深入掌握C语言的数组操作、结构体、指针、递归、循环等基础知识,同时还能了解到算法设计和实现的过程,为今后解决类似问题提供思路。此外,这个项目还可以作为面试题或教学案例,...
【八数码问题】,也称为滑动拼图游戏,是人工智能领域中常见的一个问题实例,用于研究和演示不同的搜索算法。这个经典的问题涉及到在一个2x3的框架内,用数字1到8填充七个方块,还有一个空格,目标是通过最少的移动...
八数码问题的VC源代码通常会实现以下功能: 1. **初始化**:创建3x3的棋盘并随机或预设初始状态。 2. **表示状态**:用二维数组或其他数据结构存储棋盘状态,空位用特殊值表示。 3. **移动操作**:定义函数处理上、...
在提供的压缩包文件中,虽然没有直接的源代码文件,但"八数码问题的源代码"可能是包含这些功能的源代码文件。其他文件如"站长265源码下载.html"和"zz265.com.txt"可能是指提供源码下载的网站信息,而"重要说明.txt...
求解八数码难题,求出其从一种状态转到另一种状态,所需的最小步数及其过程,在VC ++6.0上运行通过。
《八数码问题与九宫格问题的解决方案及源代码解析》 八数码问题,又称滑动拼图,是计算机科学领域中的一个经典问题,源于古老的九宫格游戏。该问题通常在一个3x3的网格上展开,包含8个带有数字的方块和一个空白方块...
实验一的核心是通过启发式搜索算法解决八数码问题,这是一种经典的AI问题,目的是将初始状态的棋盘通过最少的步数变换为目标状态。在这个实验中,C语言被用来编写实现算法的源代码。 启发式搜索算法在八数码问题中...
在本文中,我们将深入探讨“人工智能八数码源代码”这一主题。八数码问题,又称滑动拼图游戏,是人工智能领域中的一个经典问题,用于演示基础的搜索算法,如盲目搜索(如深度优先搜索DFS、广度优先搜索BFS)和启发式...
**八数码问题** 八数码问题(也称滑动拼图或15拼图)是一个经典的逻辑谜题,玩家需要通过移动空格处的方块...源代码文件`bashuma.cpp`提供了具体的实现细节,而生成的`八数码问题.exe`则可以让用户直接进行互动体验。
学过人工智能的相信都遇到过八数码问题,在此给出一个一个有序搜索的源程序。
本项目提供的"八数码游戏delphi源代码"是用Delphi编写的,目的是作为算法学习和实践的平台。通过这个代码,我们可以深入理解如何运用计算机科学中的基本概念来解决实际问题。以下是一些关键知识点: 1. 回溯算法:...
十五数码问题,也被称为十五拼图,是人工智能领域的一个经典示例,用于研究搜索算法和问题解决策略。这个问题源于一个简单的游戏,玩家需要通过滑动15个数字方块(0到14)来重新排列它们,使得它们按照1到15的顺序...
这里我们将深入探讨Delphi版本的15数码问题算法源代码及其相关知识点。 首先,`Puzzle15C.dpr`是Delphi项目的主程序文件,它定义了整个应用程序的入口点。在这个文件中,通常会包含项目启动、初始化、资源加载等...
在"EightNumber"这个文件中,我们可以期待找到用某种编程语言实现的八数码问题广度优先搜索算法的源代码。代码可能包括状态的定义、移动函数、队列操作、边界条件检查以及如何打印出找到的解决方案等功能。如果你有...
【文件名称】"EightNumPathBFS"可能是一个包含Java源代码的文件,该代码实现了上述的宽度优先搜索算法来解决八数码问题。这个文件可能会包含一个名为`EightNumSolver`的类,其中包含了状态类、搜索逻辑以及相关的...