标题:九宫问题;这个程序编好了,但是输出结果不正确,请各位大神帮小弟看看错在 ...
取消只看楼主
秋Ye霜落
Rank: 1
等 级:新手上路
帖 子:10
专家分:0
注 册:2012-12-10
结帖率:50%
 问题点数:0 回复次数:1 
九宫问题;这个程序编好了,但是输出结果不正确,请各位大神帮小弟看看错在哪里!
#include "iostream"
#include "stdlib.h"
using namespace std;
 
//棋盘大小
#define size 9
 
//定义二维数组来存储数据表示某一个特定状态
typedef int status[size][size];
 
//定义状态图中的节点数据结构,即节点的状态信息等
typedef struct Node
{
    status data;                    //节点所存储的状态
    struct Node *parent;            //指向节点的父亲节点
    struct SpringLink *child;        //指向节点的后继节点
    struct Node *next;                //指向链表的后一个节点
    int f_value;                    //由初始状态经由当前节点至目标状态的总耗散值
    int g_value;                    //由初始状态经到当前节点实际耗散值
    int h_value;                    //由当前节点到目标状态的预计耗散值
}NNode, *PNode;
 
 
//定义表述指向当前节点的扩展节点的链表
typedef struct SpringLink
{
    struct Node *pointData;            //指向节点的指针
    struct SpringLink *next;        //指向当前节点的其他扩展节点
}SPLink, *PSPLink;
 
//声明OPEN表和CLOSED表
PNode open;
PNode closed;
 
//计算棋盘状态的逆序数
int InverseNumber(status a)
{
    int i, j, sum=0;
    int data_chang[size*size]={0};
 
    //将二维数组转换成一维数组,以方便求逆序数
    for(i=0;i<size;i++)
    {
        for(j=0;j<size;j++)
        {
            data_chang[i*size+j]=a[i][j];        
        }
    }
 
 
    //计算序列中除零外的逆序数
    for(i=0;i<=size*size;i++)
    {
        if(data_chang[i]!=0)
        {
            //要比较多少次,从最后一个元素开始比较
            for(j=i;j>=0;j--)        
            {   
                //当后一个数比前一个数小时
                if(data_chang[i]<data_chang[j])   
                {
                    sum++;
                }
            }
        }
    }
    return sum;
}
 
//判断是否存在解决方案
bool hasSolution(status startStatus,status targetStatus)
{
    int startInverseNumber=InverseNumber(startStatus);
    int tatgetInverseNumber=InverseNumber(targetStatus);
 
    //判断初始状态和目标状态除零外的序列逆序数奇偶性,相同则可求值,不同则不可求
    if( (startInverseNumber%2) != (tatgetInverseNumber%2) )
    {
        return false;
    }
    else
    {
        return true;
    }
}
 
 
//初始化一个空链表
void initLink(PNode &Head)
{
    Head = (PNode)malloc(sizeof(NNode));
    Head->next = NULL;
}
 
 
//判断链表是否为空
bool isEmpty(PNode Head)
{
    if(Head->next == NULL)
    {
        return true;
    }
    else
    {
        return false;
    }
}
 
 
//从链表中拿出一个数据
void popNode(PNode &Head , PNode &FNode)
{
    if(isEmpty(Head))
    {
        FNode = NULL;
        return;
    }
    FNode = Head->next;
    Head->next = Head->next->next;
    FNode->next = NULL;
}
 
//向节点的最终后继节点链表中添加新的子节点
void addSpringNode(PNode &Head , PNode newData)
{
    PSPLink newNode = (PSPLink)malloc(sizeof(SPLink));
    newNode->pointData = newData;
 
    newNode->next = Head->child;
    Head->child = newNode;
}
 
//释放状态图中存放节点后继节点地址的空间
void freeSpringLink(PSPLink &Head)
{
    PSPLink tmm;
 
    while(Head != NULL)
    {
        tmm = Head;
        Head = Head->next;
        free(tmm);
    }
}
 
//释放open表与closed表中的资源
void freeLink(PNode &Head)
{
    PNode tmn;
 
    tmn = Head;
    Head = Head->next;
    free(tmn);
 
    while(Head != NULL)
    {
        //首先释放存放节点后继节点地址的空间
        freeSpringLink(Head->child);
        tmn = Head;
        Head = Head->next;
        free(tmn);
    }
}
 
//向普通链表中添加一个节点
void addNode(PNode &Head , PNode &newNode)
{
    newNode->next = Head->next;
    Head->next = newNode;
}
 
//向非递减排列的链表中添加一个节点
void addAscNode(PNode &Head , PNode &newNode)
{
    PNode P;
    PNode Q;
 
    P = Head->next;
    Q = Head;
    while(P != NULL && P->f_value < newNode->f_value)
    {
        Q = P;
        P = P->next;
    }
    //上面判断好位置之后,下面就是简单的插入节点了
    newNode->next = Q->next;
    Q->next = newNode;
}
 
//计算节点到目标状态的预计耗散值
int computeh_value(PNode theNode,status targetStatus)
{
    int num = 0;
    for(int i = 0 ; i < 3 ; i++)
    {
        for(int j = 0 ; j < 3 ; j++)
        {
            if(theNode->data[i][j] != targetStatus[i][j])
            {
                num++;
            }
        }
    }
    return num;
}
 
//计算节点的f,g,h值
void computeAllValue(PNode &theNode , PNode parentNode, status targetStatus)
{
    if(parentNode == NULL)
    {
        theNode->g_value = 0;
    }
    else
    {
        theNode->g_value = parentNode->g_value + 1;
    }
 
    theNode->h_value = computeh_value(theNode,targetStatus);
    theNode->f_value = theNode->g_value + theNode->h_value;
}
 
//初始化函数,进行算法初始条件的设置
void initial(status startStatus,status targetStatus)
{
    //初始化open以及closed表
    initLink(open);
    initLink(closed);
 
    //初始化起始节点,令初始节点的父节点为空节点
    PNode NULLNode = NULL;
    PNode StartNode = (PNode)malloc(sizeof(NNode));
    for(int i = 0 ; i < 3 ; i++)
    {
        for(int j = 0 ; j < 3 ; j++)
        {
            StartNode->data[i][j] = startStatus[i][j];
        }
    }
    StartNode->parent = NULL;
    StartNode->child = NULL;
    StartNode->next = NULL;
    computeAllValue(StartNode, NULLNode,targetStatus);
 
    //起始节点进入OPEN表
    addAscNode(open , StartNode);
}
 
//将B节点的状态赋值给A节点
void statusAEB(PNode &ANode , PNode BNode)
{
    for(int i = 0 ; i < 3 ; i++)
    {
        for(int j = 0 ; j < 3 ; j++)
        {
            ANode->data[i][j] = BNode->data[i][j];
        }
    }
}
 
 
//两个节点是否有相同的状态
bool hasSameStatus(PNode ANode , PNode BNode)
{
    for(int i = 0 ; i < size ; i++)
    {
        for(int j = 0 ; j < size ; j++)
        {
            if(ANode->data[i][j] != BNode->data[i][j])
                return false;
        }
    }
    return true;
}
 
//节点与其祖先节点是否有相同的状态
bool hasAnceSameStatus(PNode OrigiNode , PNode AnceNode)
{
    while(AnceNode != NULL)
    {
        if(hasSameStatus(OrigiNode , AnceNode))
            return true;
        AnceNode = AnceNode->parent;
    }
    return false;
}
 
//取得方格中空的格子的位置
void getPosition(PNode theNode , int &row , int &col)
{
    for(int i = 0 ; i < size ; i++)
    {
        for(int j = 0 ; j < size ; j++)
        {
            if(theNode->data[i][j] == 0)
            {
                row = i;
                col = j;
                return;
            }
        }
    }
}
 
//交换两个数字的值
void changeAB(int &a , int &b)
{
    int c;
    c = b;
    b = a;
    a = c;
}
 
//检查相应的状态是否在某一个链表中
bool inLink(PNode spciNode , PNode theLink , PNode &theNodeLink , PNode &preNode)
{
    preNode = theLink;
    theLink = theLink->next;
 
    while(theLink != NULL)
    {
        if(hasSameStatus(spciNode , theLink))
        {
            theNodeLink = theLink;
            return true;
        }
        preNode = theLink;
        theLink = theLink->next;
    }
    return false;
}
 
//产生节点的后继节点链表
void SpringLink(PNode theNode , PNode &spring, status targetStatus)
{
    int row;
    int col;
 
    getPosition(theNode , row , col);
 
    //空的格子右边的格子向左移动
    if(col != 2)
    {
        PNode rlNewNode = (PNode)malloc(sizeof(NNode));
        statusAEB(rlNewNode, theNode);
        changeAB(rlNewNode->data[row][col], rlNewNode->data[row][col + 1]);
        if(hasAnceSameStatus(rlNewNode, theNode->parent))
        {
            free(rlNewNode);//与父辈相同,丢弃本节点
        }
        else
        {
            rlNewNode->parent = theNode;
            rlNewNode->child = NULL;
            rlNewNode->next = NULL;
            computeAllValue(rlNewNode, theNode, targetStatus);
            //将本节点加入后继节点链表
            addNode(spring, rlNewNode);
        }
    }
    //空的格子左边的格子向右移动
    if(col != 0)
    {
        PNode lrNewNode = (PNode)malloc(sizeof(NNode));
        statusAEB(lrNewNode, theNode);
        changeAB(lrNewNode->data[row][col], lrNewNode->data[row][col - 1]);
        if(hasAnceSameStatus(lrNewNode, theNode->parent))
        {
            free(lrNewNode);//与父辈相同,丢弃本节点
        }
        else
        {
            lrNewNode->parent = theNode;
            lrNewNode->child = NULL;
            lrNewNode->next = NULL;
            computeAllValue(lrNewNode, theNode, targetStatus);
            //将本节点加入后继节点链表
            addNode(spring , lrNewNode);
        }
    }
    //空的格子上边的格子向下移动
    if(row != 0)
    {
        PNode udNewNode = (PNode)malloc(sizeof(NNode));
        statusAEB(udNewNode , theNode);
        changeAB(udNewNode->data[row][col], udNewNode->data[row - 1][col]);
        if(hasAnceSameStatus(udNewNode, theNode->parent))
        {
            free(udNewNode);//与父辈相同,丢弃本节点
        }
        else
        {
            udNewNode->parent = theNode;
            udNewNode->child = NULL;
            udNewNode->next = NULL;
            computeAllValue(udNewNode, theNode, targetStatus);
            //将本节点加入后继节点链表
            addNode(spring, udNewNode);
        }
    }
    //空的格子下边的格子向上移动
    if(row != 2)
    {
        PNode duNewNode = (PNode)malloc(sizeof(NNode));
        statusAEB(duNewNode, theNode);
        changeAB(duNewNode->data[row][col], duNewNode->data[row + 1][col]);
        if(hasAnceSameStatus(duNewNode, theNode->parent))
        {
            free(duNewNode);//与父辈相同,丢弃本节点
        }
        else
        {
            duNewNode->parent = theNode;
            duNewNode->child = NULL;
            duNewNode->next = NULL;
            computeAllValue(duNewNode, theNode, targetStatus);
            //将本节点加入后继节点链表
            addNode(spring , duNewNode);
        }
    }
}
 
//输出给定节点的状态
void outputStatus(PNode stat)
{
    for(int i = 0 ; i < 3 ; i++)
    {
        for(int j = 0 ; j < 3 ; j++)
        {
            cout << stat->data[i][j] << " ";
        }
        cout << endl;
    }
}
 
//输出最佳的路径
void outputBestRoad(PNode goal)
{
    int deepnum = goal->g_value;
 
    if(goal->parent != NULL)
    {
        outputBestRoad(goal->parent);
    }
    cout << "第" << deepnum-- << "步的状态:" << endl;
    outputStatus(goal);
}
 
 
void AStar(status startStatus,status targetStatus)
{
    PNode tmpNode;                        //指向从open表中拿出并放到closed表中的节点的指针
    PNode spring;                        //tmpNode的后继节点链
    PNode tmpLNode;                        //tmpNode的某一个后继节点
    PNode tmpChartNode;
    PNode thePreNode;                    //指向将要从closed表中移到open表中的节点的前一个节点的指针
    bool getGoal = false;                //标识是否达到目标状态
    long numcount = 1;                    //记录从open表中拿出节点的序号
 
    initial(startStatus,targetStatus);    //对函数进行初始化
    initLink(spring);                    //对后继链表的初始化
    tmpChartNode = NULL;
 
    cout << "从OPEN表中拿出的节点的状态及相应的值" << endl;
    while(!isEmpty(open))
    {
        //从OPEN表中拿出f值最小的元素,并将拿出的元素放入CLOSED表中
        popNode(open, tmpNode);
        addNode(closed, tmpNode);
 
 
        cout << "第" << numcount++ << "个状态是:" << endl;
        outputStatus(tmpNode);
        cout << "其f值为:" << tmpNode->f_value << endl;
        cout << "其g值为:" << tmpNode->g_value << endl;
        cout << "其h值为:" << tmpNode->h_value << endl;
 
 
        //如果拿出的元素是目标状态则跳出循环
        if(computeh_value(tmpNode, targetStatus) == 0)
        {
            getGoal = true;
            break;
        }
 
        //产生当前检测节点的后继(与祖先不同)节点列表,产生的后继节点的parent属性指向当前检测的节点
        SpringLink(tmpNode, spring, targetStatus);
 
        //遍历检测节点的后继节点链表
        while(!isEmpty(spring))
        {
            popNode(spring , tmpLNode);
            //状态在OPEN表中已经存在,thePreNode参数在这里并不起作用
            if(inLink(tmpLNode , open , tmpChartNode , thePreNode))
            {
                addSpringNode(tmpNode , tmpChartNode);
                if(tmpLNode->g_value < tmpChartNode->g_value)
                {
                    tmpChartNode->parent = tmpLNode->parent;
                    tmpChartNode->g_value = tmpLNode->g_value;
                    tmpChartNode->f_value = tmpLNode->f_value;
                }
                free(tmpLNode);
            }
            //状态在CLOSED表中已经存在
            else if(inLink(tmpLNode, closed, tmpChartNode, thePreNode))
            {
                addSpringNode(tmpNode, tmpChartNode);
                if(tmpLNode->g_value < tmpChartNode->g_value)
                {
                    PNode commu;
                    tmpChartNode->parent = tmpLNode->parent;
                    tmpChartNode->g_value = tmpLNode->g_value;
                    tmpChartNode->f_value = tmpLNode->f_value;
                    freeSpringLink(tmpChartNode->child);
                    tmpChartNode->child = NULL;
                    popNode(thePreNode, commu);
                    addAscNode(open, commu);
                }
                free(tmpLNode);
            }
            //新的状态即此状态既不在OPEN表中也不在CLOSED表中
            else
            {
                addSpringNode(tmpNode, tmpLNode);
                addAscNode(open, tmpLNode);
            }
        }
    }
 
    //目标可达的话,输出最佳的路径
    if(getGoal)
    {
        cout << endl;
        cout << "路径长度为:" << tmpNode->g_value << endl;
        outputBestRoad(tmpNode);
    }
 
    //释放节点所占的内存
    freeLink(open);
    freeLink(closed);
}
 
void main()
{
 
    //开始状态和目标状态
    status startStatus={2,3,7,1,8,6,5,0,4};
    status targetStatus={1,2,3,8,0,4,7,6,5};
 
    if(hasSolution(startStatus,targetStatus))
    {
        AStar(startStatus,targetStatus);
    }
    else
    {
        cout << "从当前输入的初始状态无法经过有限步数变换至您期望的目标状态!" << endl;
    }
    system("pause");
}
搜索更多相关主题的帖子: 存储 include parent status 
2012-12-16 10:35
秋Ye霜落
Rank: 1
等 级:新手上路
帖 子:10
专家分:0
注 册:2012-12-10
得分:0 
跪求!
2012-12-16 10:36



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-391466-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.026506 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved