您的位置:首页 > 其它

迷宫问题的双向BFS

2012-11-22 13:51 375 查看
#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: