人工智能导论(2)——启发式算法(八数码问题)

来源:互联网 发布:松江报警主机怎样编程 编辑:程序博客网 时间:2024/06/07 07:02

实验要求

用A*算法来解决八数码问题。


代码实现

#include<iostream>#include<stdio.h>#include<cmath> using namespace std;int open_cnt=0; int open_node_cnt;//open表节点个数 int close_cnt=0;int noresoult=0;struct Node{    int a[3][3];    int x,y;    int f,g,h;    int flag; //上一次移动方向     Node *father;}start,end;struct Open_Close{    int f;    Node *np;}open[10000],close[10000];bool isable(){//判断是否有解,逆序数之和奇偶性相同,有解    int s[9],e[9];    int tf=0,ef=0;    int k=0;        for(int i=0;i<3;i++){            for(int j=0;j<3;j++){                s[k]=start.a[i][j];                e[k]=end.a[i][j];                k++;            }        }    for(int i=0;i<9;i++){        for(int j=0;j<i;j++){            if(s[i]>s[j]&&s[j]!=0) tf+=1;            if(e[i]>e[j]&&e[j]!=0) ef+=1;        }    }    if((tf%2==1&&ef%2==1)||(tf%2==0&&ef%2==0)) return true;    else return false;}int a_start_h(Node *node){  //求 h()     int old_x,old_y,end_x,end_y;    int h=0;    for(int k=1;k<9;k++){        for(int i=0;i<3;i++){            for(int j=0;j<3;j++){                if(node->a[i][j]==k){                    old_x=i;                    old_y=j;                }                if(end.a[i][j]==k){                    end_x=i;                    end_y=j;                }            }        }        h+=abs(old_x-end_x)+abs(old_y-end_y);    }       return h;}void input(){               //输入     for(int i=0;i<3;i++){        for(int j=0;j<3;j++){            cin>>start.a[i][j];            if(start.a[i][j]==0){                start.x=i;                start.y=j;            }        }    }    for(int i=0;i<3;i++){        for(int j=0;j<3;j++){            cin>>end.a[i][j];            if(end.a[i][j]==0){                end.x=i;                end.y=j;            }        }    }    start.g=0;    start.h=a_start_h(&start);    start.f=start.g+start.h;}int show(Node *node){               //显示     Node *p=node;    if(p==&start) return 1;     else show(p->father);    cout<<"==============\n";    for(int i=0;i<3;i++){        for(int j=0;j<3;j++){            cout<<p->a[i][j]<<" ";        }        printf("\n");    }    cout<<"==============\n\n";}bool isend(Node *node){         //判断是否为目标节点     for(int i=0;i<3;i++){        for(int j=0;j<3;j++){            if(node->a[i][j]!=end.a[i][j])                return false;        }    }    return true;} void sort(Open_Close *open){      //open表排序     int min=99999,min_flag=0;     Open_Close temp;    for(int i=0;i<=open_cnt;i++){        if(min>open[i].f&&open[i].f>0){            min=open[i].f;            min_flag=i;        }    }    temp=open[min_flag];    open[min_flag]=open[0];    open[0]=temp;   }void move(int flag,Node *node){   //向四个方向扩展     int temp;    if(flag==1&&node->x>0){        Node *n = new Node();        for(int i=0;i<3;i++){            for(int j=0;j<3;j++){                n->a[i][j]=node->a[i][j];            }         }        n->a[node->x][node->y]=node->a[node->x-1][node->y];        n->a[node->x-1][node->y]=0;         n->x=node->x-1;        n->y=node->y;        n->flag=3;             n->father=node;        n->g=node->g+1;             //  求 g()         n->h=a_start_h(n);        n->f=n->g+n->h;        open_cnt++;        open_node_cnt++;        open[open_cnt].np=n;        //添加到open表        open[open_cnt].f=n->f;  //  求 f()     }    else if(flag==2&&node->y<2){        Node *n = new Node();        for(int i=0;i<3;i++){            for(int j=0;j<3;j++){                n->a[i][j]=node->a[i][j];            }        }        n->a[node->x][node->y]=node->a[node->x][node->y+1];        n->a[node->x][node->y+1]=0;        n->x=node->x;        n->y=node->y+1;        n->flag=4;             n->father=node;        n->g=node->g+1;             //  求 g()         n->h=a_start_h(n);        n->f=n->g+n->h;        open_cnt++;        open_node_cnt++;        open[open_cnt].np=n;        //添加到open表        open[open_cnt].f=n->f;  //  求 f()     }    else if(flag==3&&node->x<2){        Node *n = new Node();        for(int i=0;i<3;i++){            for(int j=0;j<3;j++){                n->a[i][j]=node->a[i][j];            }        }        n->a[node->x][node->y]=node->a[node->x+1][node->y];        n->a[node->x+1][node->y]=0;         n->x=node->x+1;        n->y=node->y;           n->flag=1;             n->father=node;        n->g=node->g+1;             //  求 g()         n->h=a_start_h(n);        n->f=n->g+n->h;        open_cnt++;        open_node_cnt++;        open[open_cnt].np=n;        //添加到open表        open[open_cnt].f=n->f;  //  求 f()     }    else if(flag==4&&node->y>0){        Node *n = new Node();        for(int i=0;i<3;i++){            for(int j=0;j<3;j++){                n->a[i][j]=node->a[i][j];            }        }        n->a[node->x][node->y]=node->a[node->x][node->y-1];        n->a[node->x][node->y-1]=0;        n->x=node->x;        n->y=node->y-1;             n->flag=2;             n->father=node;        n->g=node->g+1;             //  求 g()         n->h=a_start_h(n);        n->f=n->g+n->h;        open_cnt++;        open_node_cnt++;        open[open_cnt].np=n;        //添加到open表        open[open_cnt].f=n->f;  //  求 f()     }    } void expand(Node *node){    //节点扩展        for(int i=1;i<5;i++){        if(i!=node->flag) move(i,node);    }}int main(){    input();    open[0].np=&start;//start放入open表     open_node_cnt=1;    if(isable()){        while(true){//open表不为空             if(isend(open[0].np)){                cout<<"\n路径:\n";                show(open[0].np);                break;            }             expand(open[0].np);//扩展最优节点的子节点             open[0].np=NULL;            open[0].f=-1;            open_node_cnt--;             sort(open);   //open表排序        }    }    else cout<<"无解";} /*有解1 0 37 2 46 8 51 2 38 0 47 6 5无解1 2 3 4 0 7 6 5 83 2 1 6 5 0 4 7 8*/
阅读全文
0 0
原创粉丝点击