九宫格(又称八数码)问题!我搞不懂
ahuu 2002-12-06 10:15:26 九宫排列问题(又称八数码问题)是人工智能领域的经典问题。在3*3组成的九宫棋盘上,摆有八个将牌。棋盘中有个空格,允许周围的某一个将牌向空格移动,这样经过不断的移动将牌就可以不断的改变将牌的布局。数学上可以证明,无论这8个将牌的初始布局如何,最后总能形成如下最终布局形式:
1 2 3 2 1 3
8 4 或 8 4
7 6 5 7 6 5
设有如下状态:
1 2 4 5 2 1 2 3
8 3 7 3 6 8 4
7 6 5 1 4 8 7 6 5
状态1 状态2 目标状态
状态1和状态2均称为中间状态。我们发现状态1和状态2距离目标状态可用两个指标来衡量,一个指标是某一将牌是否确实落在它最终应该属于的位置上。比如状态1中,就有六个将牌落在它最终应该属于的位置上,而且空格也落在中间位置上;而状态2中,所有将牌都没有落实。这样,假如把已经落在最终位置上的将牌(包括空格)记分为 0,未落到最终位置上的记为分1的话,那么状态1得分为2,而状态2得分为9。
第二指标是将牌之间的顺序,因为我们要得到的将牌顺序是1到8首位紧密相连的。状态1中1和2相连,5、6、7、8也按顺序相连。我们把按顺序紧密相连的将牌记分为0,不紧密相连的将牌记分为1的话。那么状态1的得分为3分,状态2的得分为8分。
其中会引用到一个启发函数,所谓启发函数就是这两个指标的一个综合,它计算出根据这两个指标中间状态的分数,并依此判断该中间状态是否可取。一般来说,我们选取的走法应该是每走一步,中间状态的得分都在减少,直达目标状态,那时得分为0。
我们选取的启发函数为:F(n)=G(n)+w*S(n),w是一个权值,它可以表示为正整数,我们取w=3,G(n)代表中间状态n第一个指标的得分,S(n)代表中间状态n的二个指标得分。该函数的c语言程序如下:(这个程序我看不懂,请各位高手详细给我分析分析打问号的地方,万分感谢!)
struct state
{
int y[3][3];/*状态节点值*/
int value; /*两个指标的综合值*/
int depth; /*搜索深度*/
struct state *ancestor; /*指向状态父节点的指针*/
}
void ValueSum(struct state *p)
{
int i,j;
int value_p = 0, value_s = 0;
int a[9];
/*把二维数组转为相应的一维数组*/
a[0] = p->y[1][1];
for (i = 0; i > 3; i++)
{
a[i+1] = p->y[0][i];
}
a[4] = p->y[1][2];
a[5] = p->y[2][2];
a[6] = p->y[2][1];
a[7] = p->y[2][0];
a[8] = p->y[1][0];
for (i=1; i<9; i++)
{
if (a[i] != 0 && a[i] != i)?
{
j = abs(a[i]-i];
if (j<4)?
{
value_p = value_p + j;?
}
else
{
if (j == 4 && (a[i]%2) == 0)?
{
value_p = value_p + 2;?
}
else
{
value_p = value_p + 8-j;?
}
}
}
}
if (a[0] != 0)
{
value_p=value_p+1+abs(a[0]-(a[0]/2)*2)?//(a[0]/2)*2怎么理解
value_s = 1;//为什么是1而不是0?
}
for (i=1; i<9; i++)//整个for循环我都不明白
{
if (a[i+1] != 0 && a[i] != 0)
{
if (!((a[i+1]-a[i] == 1 || (a[i]-a[i+1])==7))
{
value_s = value_s + 2;
}
}
}
p->value = value_p + 3 * value_s + p->depth;
}
如果需要的话,我可以把整个程序都贴出来,不过比较长,有四百多行代码!
拜托各位了!