人工智能第一次实验\八数码问题、八数码问题(人工智能实验)
迭代深入A*搜索(IDA*)、递归最佳优先搜索RBFS解八数码问题、人工智能实验)
#include <time.h> #include <stdlib.h> #include <windows.h> #include <stdio.h> #define IN1 0x7FFFFFFF /*************************************************************************************************/ enum Actions{u,d,l,r,nop}; //动作:上、下、左、右、无 typedef struct jiegou{ //表示问题的状态 int p[9]; struct jiegou * next; struct jiegou * prev; Actions act; //前驱到达本状态的动作 int num_of_step; int shiying; //适应函数值 }zhuangtai; /*************************************************************************************************/ /*************************************************************************************************/ int haosan(int p[],int n){ //耗散函数 int k; k=n; int goal[9]={1,4,7,2,5,8,3,6,0}; for(int i=0;i<8;i++){ int j; for(j=0;j<9&&p[j]!=goal[i];j++); if(j%3>i%3)k=k+(j%3-i%3)*2; else k=k+(i%3-j%3)*2; if(j/3>i/3)k=k+(j/3-i/3)*2; else k=k+(i/3-j/3)*2; } return k; } /*************************************************************************************************/ /*************************************************************************************************/ zhuangtai * jianztai(int temp[9],int n,Actions a,zhuangtai * n_=NULL,zhuangtai * p_=NULL){//创建新状态结点 zhuangtai *s=new zhuangtai; s->num_of_step=n; s->act=a; s->next=n_; s->prev=p_; for(int i=0;i<9;i++) s->p[i]=temp[i]; s->shiying=haosan(s->p,s->num_of_step); return s; } /*************************************************************************************************/ /*************************************************************************************************/ int * randep(int d){ //随机的初始状态产生器 int *p=new int[9]; int i,j,k,t; for(i=0;i<3;i++){ for(j=0;j<3;j++) p[i+j*3]=i*3+j+1; } p[8]=0; j=8; int *xubo2=new int[d]; srand((unsigned)time(NULL)); for(i=0;i<d;i++) { switch(rand()%4) { case 0: //move up if(j==3|j==6|j==0){i--;continue; } //若遇到边界,则再次产生随机数; else k=j-1;break; case 1: //move down if((j+1)%3==0){i--;continue; } //若遇到边界,则再次产生随机数; else k=j+1;break; case 2: //move left if(j<3){i--;continue; } //若遇到边界,则再次产生随机数; else k=j-3;break; case 3: //move right if(j>5){i--;continue; } //若遇到边界,则再次产生随机数; else k=j+3;break; default:break; } t=p[j];p[j]=p[k];p[k]=t; j=k; } return p; } /*************************************************************************************************/ /*************************************************************************************************/ int * move_up(int p[]){ int i,t; int *temp=new int[9]; for(i=0;i<9;i++) temp[i]=p[i]; for(i=0;temp[i]>0;i++); if(i%3!=0){ t=temp[i]; temp[i]=temp[i-1]; temp[i-1]=t; return temp; } delete temp;return NULL; } /*************************************************************************************************/ /*************************************************************************************************/ int * move_down(int p[]){ int i,t; int *temp=new int[9]; for(i=0;i<9;i++) temp[i]=p[i]; for(i=0;temp[i]>0;i++); if((i-2)%3!=0){ t=temp[i]; temp[i]=temp[i+1]; temp[i+1]=t; return temp; } delete temp;return NULL; } /*************************************************************************************************/ /*************************************************************************************************/ int * move_left(int p[]){ int i,t; int *temp=new int[9]; for(i=0;i<9;i++) temp[i]=p[i]; for(i=0;temp[i]>0;i++); if(i>2){ t=temp[i]; temp[i]=temp[i-3]; temp[i-3]=t; return temp; } delete temp;return NULL; } /*************************************************************************************************/ /*************************************************************************************************/ int * move_right(int p[]){ int i,t; int *temp=new int[9]; for(i=0;i<9;i++) temp[i]=p[i]; for(i=0;temp[i]>0;i++); if(i<6){ t=temp[i]; temp[i]=temp[i+3]; temp[i+3]=t; return temp; } delete temp;return NULL; } /*************************************************************************************************/ /*************************************************************************************************/ void input8(int p[]){ //打印八数码。 //printf("\n"); for(int i=0;i<3;i++){ for( int j=0;j<9;j+=3){ if(p[i+j]>0) printf("%d ",p[i+j]); else printf(" "); //当为零时输出空格“ ”。 } printf("\n"); } } /*************************************************************************************************/ /*************************************************************************************************/ char * idas(int init[],int &g){ zhuangtai *xubo=jianztai(init,0,nop); int i,k; int num1,num2; zhuangtai * l1,*s,*t; num1=xubo->shiying; while(num1<IN1) { num2=IN1;i=0; l1=jianztai(xubo->p,0,u); while(l1!=NULL) { s=l1; if(s->num_of_step>30) return NULL; k=s->shiying; l1=l1->next; if( k>num1){ if(k<num2 ) num2=k; free(s); } else{ if(k==s->num_of_step) { char *jiejue=new char[s->num_of_step]; jiejue[0]=0; g=k; t=s; for(i=g-1;i>=0;i--) { switch(t->act) { case u:jiejue[i]='u';break; case d:jiejue[i]='d';break; case l:jiejue[i]='l';break; case r:jiejue[i]='r';break; default:break; } t=t->prev; } return jiejue; } else{ int * t; if( s->act!=d && (t=move_up(s->p))!=NULL) l1=jianztai(t,s->num_of_step+1 ,u,l1,s); if( s->act!=u && (t=move_down(s->p))!=NULL) l1=jianztai(t,s->num_of_step+1 ,d,l1,s); ; if( s->act!=r && (t=move_left(s->p))!=NULL) l1=jianztai(t,s->num_of_step+1 ,l,l1,s); ; if( s->act!=l && (t=move_right(s->p))!=NULL) l1=jianztai(t,s->num_of_step+1 ,r,l1,s); } } } num1=num2; } return NULL; } /*************************************************************************************************/ /*************************************************************************************************/ zhuangtai * rbfs_r(zhuangtai * st,int f_limit,int &fbest){ if(haosan(st->p,st->num_of_step)==st->num_of_step)return st; zhuangtai * successor=NULL,*s,*best,*result; int alter; //expand successors int * t; if( st->act!=d && (t=move_up(st->p))!=NULL) successor=jianztai(t,st->num_of_step+1 ,u,successor,st); if( st->act!=u && (t=move_down(st->p))!=NULL) successor=jianztai(t,st->num_of_step+1 ,d,successor,st); if( st->act!=r && (t=move_left(st->p))!=NULL) successor=jianztai(t,st->num_of_step+1 ,l,successor,st); if( st->act!=l && (t=move_right(st->p))!=NULL) successor=jianztai(t,st->num_of_step+1 ,r,successor,st); for(s=successor;s!=NULL;s=s->next){ if(s->shiying<st->shiying) s->shiying=st->shiying; } while(1){ best=successor; for(s=successor;s!=NULL;s=s->next){ if(s->shiying<best->shiying) best=s; } if(best->shiying>f_limit){fbest=best->shiying;return NULL;} alter=IN1; for(s=successor;s!=NULL;s=s->next){ if(s==best)continue; else if(s->shiying < alter) alter=s->shiying; } result=rbfs_r(best, (f_limit<alter)?f_limit:alter, best->shiying); if(result!=NULL)return result; } } /*************************************************************************************************/ /*************************************************************************************************/ char * rbfs(int init[],int &g){ //递归RBFS算法 zhuangtai *xubo=xubo=jianztai(init,0,nop); zhuangtai *final=rbfs_r(jianztai(xubo->p,0,nop),IN1,xubo->shiying); zhuangtai *t; char *jiejue=new char[final->num_of_step]; jiejue[0]=0; t=final;g=final->num_of_step; for(int i=g-1;i>=0;i--) { switch(t->act) { case u:jiejue[i]='u';break; case d:jiejue[i]='d';break; case l:jiejue[i]='l';break; case r:jiejue[i]='r';break; default:break; } t=t->prev; } return jiejue; } /*************************************************************************************************/ /*************************************************************************************************/ int main(int argc, _TCHAR* argv[]) { char * jiejue; zhuangtai * xubo; int i,g,m; LARGE_INTEGER lv,lv1,lv2; double secondsPerTick; QueryPerformanceFrequency( &lv ); secondsPerTick = 1000000.0/ lv.QuadPart; while(1){ printf("*************************************************************************"); printf("\n请输入的初始状态产生器移动步数d(1-3000000):\n"); scanf("%d",&g); if(g<=0){ //限制输入输出的大小1-3000000整数 printf("输入错误!\n");continue; } else if(g>3000000){ printf("数值太大,无法解决!抱歉!\n");continue; } xubo=jianztai(randep(g),0,nop); printf("*******************\n"); printf("八数码初始状态:\n"); input8(xubo->p); printf("*******************\n"); printf("\n***********************************"); printf("\n操作:\n1.迭代深入A*搜索求解 IDA*;\n2.递归最佳优先搜索求解 RBFS;\n3.两者同时.\n0.跳出"); printf("\n***********************************\n请输入操作对应的数字:"); scanf("%d",&m); if(m<0|m>=4){ //限制输入输出的大小0-3整数 printf("输入错误!请重新输入!\n");continue; } while(m<4){ if(m==3)m=-1; QueryPerformanceCounter( &lv1 ); if(m==1||m==-1) jiejue=idas(xubo->p,g); else if(m==2||m==-2) jiejue=rbfs(xubo->p,g); else if(m==0) break; else break; QueryPerformanceCounter( &lv2 ); if(jiejue==NULL){ printf("Failed\n"); system("pause"); break;; } if(m==1||m==-1){printf("\n***********************************");printf("\n迭代深入A*搜索(IDA*)解得:");} if(m==2||m==-2){printf("***********************************");printf("\n递归最佳优先搜索RBFS解得:");} printf("\n运行结果:"); printf("共移动%d步\n",g); printf("运行时间:%f us\n",secondsPerTick * (lv2.QuadPart-lv1.QuadPart)); printf("移动路径:"); for(i=0;i<g-1;i++) printf("%c,",jiejue[i]); printf("%c\n",jiejue[i]); switch(m) { case 1: case 2: case -2:m=5;break; case -1:m=-2;break; default:break; } } printf("***********************************\n"); system("pause"); } return 0; } /*************************************************************************************************/