bfs.cpp

来自「宽度优先算法解决八码难题」· C++ 代码 · 共 230 行

CPP
230
字号
#include<iostream>
#include<stdio.h>
#define N 3              //九宫二维数组大小
#define M 100000         //closed表的大小,可进行设置

using namespace std;


class jgnode{
public:
	int value[N][N];                 //记录九宫各位置的值
	int num[2];                      //记录0的位置
	jgnode *pre;                  //指向父辈节点的指针
	jgnode *next;                 //open表中连接后面节点的指针
	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];
		next=NULL;
	}

	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 isgnode(jgnode *t,jgnode *g,int tv[N][N]);
int printnode(jgnode *g,int c);
void evalue(jgnode *t,int tv[N][N]);
int expnode(jgnode *h,jgnode *t,int tv[N][N],int tn[2]);

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];*/
	char cho='n';
do{	int ecount=1,ocount=0,ccount=0,j=0,temp=0,counter=0;
	//ecount记录open表末端,ocount记录open表始端,ccount记录closed表末端
	jgnode *head=NULL,*end=NULL,*closed[M]={NULL};
	jgnode *snode=NULL,*gnode=NULL,*tnode=NULL,*tt=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];
	findzero(vs,tnum);
	cout<<tnum[0]<<tnum[1]<<endl;
	snode=new jgnode(vs,NULL,tnum);
/*	cout<<"出入目标节点(如0,1,2,3,4,5,6,7,8):"<<endl;
	for(m=0;m<N;m++)
		for(int n=0;n<N;n++)
			cin>>vg[m][n];*/
	gnode=new jgnode(vg,NULL,tnum);
	cout<<"开始节点:"<<endl;
	snode->print();
	cout<<"目标节点:"<<endl;
	gnode->print();
	head=snode;end=head;tt=head;
	cout<<"start:"<<endl;
	if(snode->isequal(vg)==0){
		cout<<"find with th snode."<<endl;
		return 0;
	}
	ecount=expand(head,snode,gnode);
//	while(tt!=NULL){
//		tt->print();
//		tt=tt->next;
//	}
	tt=head;
	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);
		if(ecount==-1)
			break;
		}
		temp=0;counter=0;
/*		while(tt!=NULL){
		tt->print();
		tt=tt->next;
		}
	    tt=head;*/
	}
	cout<<"扩展次数为:  "<<j<<endl;
/*	int ccc=0;
	while(closed[ccc]!=NULL){
		closed[ccc++]->print();
	}
	while(head!=NULL){
		head->print();
		head=head->next;
	}*/
	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]){
	jgnode *temp,*p=h;
	if((t->pre)!=NULL){
		if(((t->pre)->isequal(tv))!=0){
			temp=new jgnode(tv,t,tn);
			temp->pre=t;
			while(p->next!=NULL)
				p=p->next;
			p->next=temp;
			temp=NULL;
			return 1;
		}
		else return 0;
	}
	else{
		temp=new jgnode(tv,t,tn);
		temp->pre=t;
		while(p->next!=NULL)
			p=p->next;
		p->next=temp;
		temp=NULL;
		return 1;
	}
}
//扩展当前节点,并判断是否为目标
int expand(jgnode *h,jgnode *t,jgnode *g){
	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);
	}
    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);
	}
    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);
	}
    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);
	}
	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];
}

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 + =
减小字号Ctrl + -
显示快捷键?