迷宫问题的双向BFS

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define STARTVALUE 2012 
#define ENDVALUE 2013
#define QUEUESIZE (1024*1024)	//size of the queue for BFS
#define MAXVALUE (65535)

typedef enum{START=0,MIDDLE=1,END=2,UNREACHABLE=3}State;
typedef enum{ADD=0,MIN=1,MUL=2,DIV=3,DIV2=4,OTHER=5}Opera;
typedef struct Node{
	int value,path;
	Node * parent;
	Node * child[5];  //child[4] is for reverse search when operation is div.
	State state;
}*QuadTree;
QuadTree root,root_rev;
Node** ExistNode;
Node** ExistNode_rev;

Node * NewNode(int v, Node* n,int p, State s){
	Node *q = (Node *)malloc(sizeof(Node));
	q->value = v;
	q->parent = n;
	q->path = p;
	q->child[ADD] = q->child[MIN] = q->child[MUL] = q->child[DIV] = q->child[DIV2] = NULL;
	q->state = s;
	return q;
}

struct Queue{
	Node ** data;
	int size,header,tailer;
}NodeQueue, NodeQueue_rev;
void InitQueue(){
	NodeQueue.data = (Node**)malloc(QUEUESIZE*sizeof(Node *));
	NodeQueue_rev.data = (Node**)malloc(QUEUESIZE*sizeof(Node *));
	NodeQueue.size = NodeQueue_rev.size = QUEUESIZE;
	NodeQueue.header = NodeQueue.tailer = NodeQueue_rev.header = NodeQueue_rev.tailer = 0;
}
void EnQueue(Queue* nodequeue, Node * q){
	if((nodequeue->tailer+1)%nodequeue->size == nodequeue->header) {printf("Queue Overflow\n");return;}
	nodequeue->data[nodequeue->tailer] = q;
	nodequeue->tailer = (nodequeue->tailer+1)%nodequeue->size;
}
Node* DeQueue(Queue* nodequeue){
	if(nodequeue->header == nodequeue->tailer) return NULL;
	Node* temp = nodequeue->data[nodequeue->header];
	nodequeue->header = (nodequeue->header+1)%nodequeue->size;
	return temp;
}
void QueueClear(Queue* nodequeue){	//clear queue
	nodequeue->tailer = nodequeue->header;
}
Node* PopStack(Queue* nodequeue){	//queue also can be used as stack for outputing result
	if(nodequeue->header == nodequeue->tailer) return NULL;
	nodequeue->tailer = (nodequeue->tailer-1+nodequeue->size)%nodequeue->size;
	return nodequeue->data[nodequeue->tailer];
}

int add(int temp){return temp+7;}
int minus(int temp){return temp-5;}
int mul(int temp){return (temp<<1)+temp;}
int div(int temp){return temp>>1;}
int (*fun[5])(int) ={add,minus,mul,div,div};	//function pointer
int add_rev(int temp){return temp-7;}
int minus_rev(int temp){return temp+5;}
int mul_rev(int temp){return temp/3;}
int div_rev(int temp){return temp<<1;}
int div2_rev(int temp){return (temp<<1)+1;}			//
int (*fun_rev[5])(int) ={add_rev,minus_rev,mul_rev,div_rev,div2_rev};	//function pointer

//three-dimensional matrice: according to [State], [Path], [Next operation] return [Next State] 
State StateCompute[3][6][5]={
	{	{UNREACHABLE,UNREACHABLE,UNREACHABLE,MIDDLE,MIDDLE},
		{UNREACHABLE,UNREACHABLE,UNREACHABLE,UNREACHABLE,UNREACHABLE},
		{UNREACHABLE,UNREACHABLE,UNREACHABLE,UNREACHABLE,UNREACHABLE},
		{MIDDLE,UNREACHABLE,UNREACHABLE,UNREACHABLE,UNREACHABLE},
		{MIDDLE,UNREACHABLE,UNREACHABLE,UNREACHABLE,UNREACHABLE},
		{MIDDLE,UNREACHABLE,UNREACHABLE,MIDDLE,MIDDLE}
	},
	{	{UNREACHABLE,END,END,START,START},
		{START,UNREACHABLE,END,START,START},
		{START,END,UNREACHABLE,START,START},
		{START,END,END,UNREACHABLE,UNREACHABLE},
		{START,END,END,UNREACHABLE,UNREACHABLE},
		{UNREACHABLE,UNREACHABLE,UNREACHABLE,UNREACHABLE,UNREACHABLE}
	},
	{	{UNREACHABLE,UNREACHABLE,UNREACHABLE,UNREACHABLE,UNREACHABLE},
		{UNREACHABLE,UNREACHABLE,MIDDLE,UNREACHABLE,UNREACHABLE},
		{UNREACHABLE,MIDDLE,UNREACHABLE,UNREACHABLE,UNREACHABLE},
		{UNREACHABLE,UNREACHABLE,UNREACHABLE,UNREACHABLE,UNREACHABLE},
		{UNREACHABLE,UNREACHABLE,UNREACHABLE,UNREACHABLE,UNREACHABLE},
		{UNREACHABLE,MIDDLE,MIDDLE,UNREACHABLE,UNREACHABLE}
	}
};
Node* IsExistRevTree(Node** existnode, Node* node);
void OutputResult(Node* meet){
	char opera[] = "+7-5*3/2/2";
	int i = 0;
	Node* end = meet;
	while(end->parent!=NULL){
		EnQueue(&NodeQueue,end);
		end = end->parent;
	}
	while((end=PopStack(&NodeQueue))!=NULL)
		printf("%d\t%d%c%c=%d\n",++i,end->parent->value,opera[2*end->path],opera[1+2*end->path],end->value);
	end = IsExistRevTree(ExistNode_rev,meet);
	while(end->parent!=NULL){
		printf("%d\t%d%c%c=%d\n",++i,end->value,opera[2*end->path],opera[1+2*end->path],end->parent->value);
		end = end->parent;
	}
}
void OutputResult_rev(Node* meet){
	char opera[] = "+7-5*3/2";
	int i = 0;
	Node* end = IsExistRevTree(ExistNode, meet);
	while(end->parent!=NULL){
		EnQueue(&NodeQueue,end);
		end = end->parent;
	}
	while((end=PopStack(&NodeQueue))!=NULL)
		printf("%d\t%d%c%c=%d\n",++i,end->parent->value,opera[2*end->path],opera[1+2*end->path],end->value);
	end = meet;
	while(end->parent!=NULL){
		printf("%d\t%d%c%c=%d\n",++i,end->value,opera[2*end->path],opera[1+2*end->path],end->parent->value);
		end = end->parent;
	}
}

void InitPruning(){		// allocate memory for storing existing node, using bitmap algorithm
	ExistNode = (Node**) malloc(3*4*MAXVALUE*sizeof(Node*));
	ExistNode_rev = (Node**) malloc(3*4*MAXVALUE*sizeof(Node*));
	memset(ExistNode,NULL,3*4*MAXVALUE*sizeof(Node*));
	memset(ExistNode_rev,NULL,3*4*MAXVALUE*sizeof(Node*));
}
bool Pruning(Node** existnode, Node* node){
	if(OTHER == node->path||(unsigned)node->value>MAXVALUE)	return true;
	if(existnode[node->state*4*MAXVALUE+(node->path==DIV2?DIV:node->path)*MAXVALUE+node->value]!=NULL)
		return false;
	existnode[node->state*4*MAXVALUE+(node->path==DIV2?DIV:node->path)*MAXVALUE+node->value] = node;
	return true;
}
Node* IsExistRevTree(Node** existnode, Node* node){
	if(OTHER == node->path||(unsigned)node->value>MAXVALUE)	return NULL;
	for(int i =0; i<4;i++){
		if(node->path==i||(node->path==DIV2&&i==DIV)) continue;
		if(existnode[node->state*4*MAXVALUE+i*MAXVALUE+node->value]!=NULL)
			return existnode[node->state*4*MAXVALUE+i*MAXVALUE+node->value];
	}
	return NULL;
}
void Expand(Node * node){
	for(int i = 0; i < 4; i++ ){
		if(UNREACHABLE ==StateCompute[node->state][node->path][i]) continue;
		node->child[i] = NewNode(fun[i](node->value),node,i,StateCompute[node->state][node->path][i]);
		if(Pruning(ExistNode,node->child[i])) EnQueue(&NodeQueue,node->child[i]);
		if(IsExistRevTree(ExistNode_rev,node->child[i])){
			QueueClear(&NodeQueue);
			QueueClear(&NodeQueue_rev);
			OutputResult(node->child[i]);
			break;
		}
	}
}
void Expand_rev(Node * node){
	for(int i = 0; i < 5; i++ ){
		if(UNREACHABLE ==StateCompute[node->state][node->path][i]||(MUL==i&&node->value%3!=0)||(DIV2==i&&node->value%2==1)) continue;
		node->child[i] = NewNode(fun_rev[i](node->value),node,i,StateCompute[node->state][node->path][i]);
		if(Pruning(ExistNode_rev,node->child[i])) EnQueue(&NodeQueue_rev,node->child[i]);
		if(IsExistRevTree(ExistNode,node->child[i])){
			QueueClear(&NodeQueue);
			QueueClear(&NodeQueue_rev);
			OutputResult_rev(node->child[i]);
			break;
		}
	}
}
int main(){
	Node * p = root = NewNode(STARTVALUE,NULL,OTHER,START);
	Node * q = root_rev = NewNode(ENDVALUE,NULL,OTHER,END);
	InitQueue();
	InitPruning();
	EnQueue(&NodeQueue_rev,q);
	EnQueue(&NodeQueue,p);
	while(true)
	{
		if((p=DeQueue(&NodeQueue))==NULL)break;
		Expand(p);
		if((q=DeQueue(&NodeQueue_rev))==NULL)break;
		Expand_rev(q);
	}
	printf("Completion!\n");
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值