⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 a.cpp

📁 a算法解决八码难题
💻 CPP
字号:
#include<iostream>
#include<stdio.h>
#include<math.h>
#define N 3
#define M 100000

using namespace std;


class jgnode{
public:
	int value[N][N];                 //记录九宫各位置的值
	int num[2];                      //记录0的位置
	int h;
	jgnode *pre;                  //指向父辈节点的指针
	jgnode *next;
	jgnode():pre(NULL)            //默认构造函数
	{}

	jgnode(const int v[N][N],jgnode *p=NULL){//构造函数初始化
		for(int i=0;i<N;i++)
			for(int j=0;j<N;j++)
				value[i][j]=v[i][j];
		pre=p;
	}
	jgnode(const int v[N][N],jgnode *p=NULL,int n[2]=0){
		for(int i=0;i<N;i++)
			for(int j=0;j<N;j++)
				value[i][j]=v[i][j];
		pre=p;
		num[0]=n[0];
		num[1]=n[1];
		h=0;
		next=NULL;
	}

	void setp(jgnode *p){            //设置父辈节点的指针
		pre=p;
	}
	void setv(int *v){               //设置记录九宫各位置的值
		for(int i=0;i<N;i++)
			for(int j=0;j<N;j++)
				value[i][j]=v[i*3+j];
	}
	void setn(int n[2]){num[0]=n[0];num[1]=n[1];}          //设置0的位置
	void print(){                     //输出九宫
		for(int i=0;i<N;i++){
			for(int j=0;j<N;j++)
				cout<<value[i][j]<<"  ";
			cout<<endl;}
		cout<<endl;
	}
	int isequal(int v[N][N]){
		for(int i=0;i<N;i++)
			for(int j=0;j<N;j++)
				if(value[i][j]!=v[i][j])
					return -1;
		return 0;
	}

};

void findzero(int tv[N][N],int tn[2]);
int expand(jgnode *h,jgnode *t,jgnode *g,int gp[9][2]);
int isgnode(jgnode *t,jgnode *g,int tv[N][N]);
int printnode(jgnode *g);
void evalue(jgnode *t,int tv[N][N]);
int expnode(jgnode *h,jgnode *t,int tv[N][N],int tn[2],int gp[9][2]);
int hfunct(int tv[N][N],int gp[9][2]);
void enopen(jgnode *h,jgnode *temp);

int main(){
	int vs[N][N]={1,2,3,4,0,5,6,7,8},vg[N][N]={0,1,2,3,4,5,6,7,8},vt[N][N],tnum[2]={0,0};
/*	for(int i=0;i<N;i++)
		for(int j=0;j<N;j++)
			vg[i][j]=vs[2-i][2-j];*/
	int ecount=1,ocount=0,ccount=0,j=0,temp=0,counter=0;
	char cho='n';
do{
	//ecount记录open表末端,ocount记录open表始端,ccount记录closed表末端
	jgnode *closed[M]={NULL};
	jgnode *snode=NULL,*gnode=NULL,*tnode=NULL,*head=NULL;
	//snode为开时节点,gnode为目标节点,tnode为寄存节点
	cout<<"输入开始节点(如1,2,3,4,0,5,6,7,8):"<<endl;
	for(int m=0;m<N;m++)
		for(int n=0;n<N;n++)
			cin>>vs[m][n];//scanf("%d",&vs[m][n]);
	int gp[9][2]={{0,0},{0,1},{0,2},{1,0},{1,1},{1,2},{2,0},{2,1},{2,2}};
	findzero(vs,tnum);
	snode=new jgnode(vs,NULL,tnum);
	snode->h=hfunct(vs,gp);
	cout<<snode->h<<endl;
	//cout<<"出入目标节点(如3、1、2、4、0、5、6、7、8):"<<endl;
	//for(m=0;m<N;m++)
	//	for(int n=0;n<N;n++)
	//		cin>>vg[m][n];//scanf("%d",&vg[m][n]);
	gnode=new jgnode(vg,NULL,tnum);
	cout<<"开始节点:"<<endl;
	snode->print();
	cout<<"目标节点:"<<endl;
	gnode->print();
	head=snode;
	cout<<"start:"<<endl;
	if(snode->isequal(vg)==0){
		cout<<"find with th snode."<<endl;
		return 0;
	}
	ecount=expand(head,snode,gnode,gp);
	if(ecount==-1)
		return 0;
	while(j++<M){
		if(head->next==NULL)
			break;
		tnode=head->next;
		head->next=tnode->next;
		evalue(tnode,vt);
		while(closed[counter]!=NULL){
			if(closed[counter++]->isequal(vt)==0){
				temp=1;break;}
		}
		if(temp==0){
		closed[ccount++]=tnode;
		ecount=expand(head,tnode,gnode,gp);
		if(ecount==-1)
			break;
		}
		temp=0;counter=0;
	}
	cout<<"扩展次数为:  "<<j<<endl;
/*	while(head!=NULL){
		cout<<head->h<<endl;
		head->print();
		head=head->next;
	}
	int ccc=0;
	while(closed[ccc]!=NULL){
		cout<<closed[ccc]->h<<endl;
		closed[ccc++]->print();
	}*/
	j=0;
	cout<<"是否继续下一次搜索(y or n):"<<endl;
	cin>>cho;
	}while((cho=='y')||(cho=='Y'));
	return 0;
}

int printnode(jgnode *g,int c){
	int cc=c;
	if((g->pre)!=NULL)
		cc=printnode(g->pre,c+1);
	g->print();
	return cc;
}
int isgnode(jgnode *t,jgnode *g,int tv[N][N]){
	int count=0;
	if(g->isequal(tv)==0){
		g->pre=t;
		cout<<"find the goal node!!"<<endl;
		cout<<"搜索路径如下:"<<endl;
		count=printnode(g,count);
		cout<<"路径长度:"<<count<<endl;
		return -1;
	}
	return 0;
}
int expnode(jgnode *h,jgnode *t,int tv[N][N],int tn[2],int gp[9][2]){
	jgnode *temp;
	if((t->pre)!=NULL){
		if(((t->pre)->isequal(tv))!=0){
			temp=new jgnode(tv,t,tn);
			temp->pre=t;
			temp->h=hfunct(tv,gp);//yaogai
			//cout<<temp->h<<endl;
			//temp->print();
			enopen(h,temp);
			return 1;
		}
		else return 0;
	}
	else{
		temp=new jgnode(tv,t,tn);
		temp->pre=t;
		temp->h=hfunct(tv,gp);//yaogai
		//cout<<temp->h<<endl;
		//temp->print();
		enopen(h,temp);
		return 1;
	}
}
//扩展当前节点,并判断是否为目标
int expand(jgnode *h,jgnode *t,jgnode *g,int gp[9][2]){
	int td=0,ti,tj,tv[N][N],tn[2],ct=0,flag=0;
	ti=t->num[0];tj=t->num[1];
    if((ti-1)>=0){
		evalue(t,tv);
		tn[0]=ti-1;tn[1]=tj;
		td=tv[ti-1][tj];tv[ti-1][tj]=tv[ti][tj];tv[ti][tj]=td;
		if(isgnode(t,g,tv)==-1)
			return -1;
		expnode(h,t,tv,tn,gp);
	}
    if((tj+1)<=2){
		evalue(t,tv);
		tn[0]=ti;tn[1]=tj+1;
		td=tv[ti][tj+1];tv[ti][tj+1]=tv[ti][tj];tv[ti][tj]=td;
		if(isgnode(t,g,tv)==-1)
			return -1;
		expnode(h,t,tv,tn,gp);
	}
    if((ti+1)<=2){
		evalue(t,tv);
		tn[0]=ti+1;tn[1]=tj;
		td=tv[ti+1][tj];tv[ti+1][tj]=tv[ti][tj];tv[ti][tj]=td;
		if(isgnode(t,g,tv)==-1)
			return -1;
		expnode(h,t,tv,tn,gp);
	}
    if((tj-1)>=0){
		evalue(t,tv);
		tn[0]=ti;tn[1]=tj-1;
		td=tv[ti][tj-1];tv[ti][tj-1]=tv[ti][tj];tv[ti][tj]=td;
		if(isgnode(t,g,tv)==-1)
			return -1;
		expnode(h,t,tv,tn,gp);
	}
	return 0;
}
void evalue(jgnode *t,int tv[N][N]){
	for(int i=0;i<N;i++)
		for(int j=0;j<N;j++)
			tv[i][j]=t->value[i][j];
}

int hfunct(int tv[N][N],int gp[9][2]){
	int p=0,s=0;
	int pp[9][2]={{0,1},{0,2},{1,2},{0,0},{1,1},{2,2},{1,0},{2,0},{2,1}};
	for(int i=0;i<N;i++){
		for(int j=0;j<N;j++){
			p+=abs(i-gp[(tv[i][j])][0])+abs(j-gp[(tv[i][j])][1]);
			if((i!=1)||(j!=1)){
				if(tv[(pp[i*3+j][0])][(pp[i*3+j][1])]!=((pp[i*3+j][0])*3+pp[i*3+j][1]))
					s+=2;
			}
		}
	}
	if(tv[1][1]!=0)
		s+=1;
	return p+3*s;
}
void enopen(jgnode *h,jgnode *temp){
	jgnode *pt=h->next,*q=h;
	while(pt!=NULL){
		if(temp->h<pt->h){
			temp->next=pt;
			q->next=temp;
			break;
		}
		q=pt;
		pt=pt->next;
	}
	if((pt==NULL)&&(temp->next==NULL))
		q->next=temp;
	//cout<<temp->h<<endl;
	//temp->print();
}

void findzero(int tv[N][N],int tn[2]){
	for(int i=0;i<N;i++)
		for(int j=0;j<N;j++){
			if(tv[i][j]==0){tn[0]=i;tn[1]=j;}
		}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -