uva10422(Knights in FEN)-bfs+哈希(隐式图搜索)

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1363

#include<stdio.h>
#include<string.h>
#define MAX 5000000
int dx[8]={1,2,2,1,-1,-2,-2,-1},dy[8]={-2,-1,1,2,2,1,-1,-2};
int st[MAX][25];
int temp[25],aim[25]={1,1,1,1,1,0,1,1,1,1,0,0,2,1,1,0,0,0,0,1,0,0,0,0,0},head[MAX],next[MAX],dist[MAX];
/*哈希函数*/
int has(int s){
	int i,ha=0;
	for(i=0;i<25;i++) ha=2*ha+st[s][i];
	return ha%MAX;
}
/*判断是否可以插入*/
int try_to_inser(int s){
	int h=has(s);
	int u=head[h];//得到头结点的位置
	while(u){//若是其为0则说明这个位置没有存放结点,若是不为0则继续寻找下一个结点是否存在有被访问过的结点
		if(memcmp(st[u],st[s],sizeof(st[s]))==0) return 0;
		u=next[u];
	}
	next[s]=head[h];//将头结点移到s的下一个结点的位置
	head[h]=s;//头结点存储s,完成插入
	return 1;
}
void init_look_uptabl(){
	memset(head,0,sizeof(head));
	memset(next,0,sizeof(next));
}
int dfs(){
	init_look_uptabl();
	int fron=0,rear=1;
	dist[1]=0;
	while(fron<rear){
		fron++;
		if(dist[fron]>10) return -1;//若是操作次数大于10,则说明不能在10步以内到达目标状态
		else if(memcmp(st[fron],aim,sizeof(aim))==0) return dist[fron];//到达目标状态,返回操作步骤
		else{
			int i;
			for(i=0;i<25;i++) if(st[fron][i]==2) break;
			int x,y,mark=i;
			y=i/5,x=i%5;
			for(i=0;i<8;i++){
				int ty=y+dy[i],tx=x+dx[i];
				if(ty>=0&&ty<5&&tx>=0&&tx<5){
					rear++;
					int tc[25];
					memcpy(&tc,&st[fron],sizeof(tc));
					tc[mark]=st[fron][ty*5+tx],tc[ty*5+tx]=2;
					memcpy(&st[rear],&tc,sizeof(tc));
					dist[rear]=dist[fron]+1;//操作步数等于上一次的步数+1;
					if(try_to_inser(rear)==0) rear--;
				}
			}
		}
	}
	return -1;
}
int main(){
	int t;
	scanf("%d",&t);
	char s[5];
	getchar();
	while(t--){
		int i,j;
		for(i=0;i<5;i++){
			gets(s);
			for(j=0;j<5;j++){
				if(s[j]==' ') st[1][i*5+j]=2;
				else st[1][i*5+j]=s[j]-'0';
			}
		}
		int te=dfs();
		if(te==-1)
			printf("Unsolvable in less than 11 move(s).\n");
		else
			printf("Solvable in %d move(s).\n",te);
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值