uva 10422 Knights in FEN

这道题目不可能只用bfs就解决,因为这样效率太低了,跟八数码问题的A*算法如出一辙,使用启发式搜索,要估计当前状态至少还需要多少步才能到最终状态,这个估计值加上当前状态已经经历的步数就是决定优先队列中出队状态节点的权重值,这个值越小,越应该优先出队,如果这个值相等再比较当前已经走的步数,小的那个再出队,其实估计还需要多少步并不复杂,不需要推测地非常准,只需要大概估计剪枝效果就很明显了,不剪枝直接dfs肯定超时,其实只需要统计当前状态中的矩阵里面不在其应该在的位置的小方格的个数,那么要到最终的状态,这些小方格要到其应该到的位置,至少需要空格位置来替换它一次,所以这个还需要多少步的估计值使用上面说的方块的统计值就行了,虽然不精确,但是剪枝的效果已经可以达到要求了。虽然只是一点点改进,但是带来的效率的提升对比起直接bfs确实非常明显。

#include <stdio.h>
#include <queue>
#include <map>
#include <list>
#include <string.h>
using namespace std;

#define		MAX_HASH		50000

char last_state[6][7];

void init()
{
	strcpy(last_state[1], " 11111\0");
	strcpy(last_state[2], " 01111\0");
	strcpy(last_state[3], " 00 11\0");
	strcpy(last_state[4], " 00001\0");
	strcpy(last_state[5], " 00000\0");
}


struct state
{
	char m[6][7];
	int blank_i, blank_j;
	int step;
	int min_step; //最少还需多少步
};

void get_min_step(struct state &sta)
{
	int i, j;
	int sum;

	sum = 0;
	for(i=1; i<=5; i++)
	{
		for(j=1; j<=5; j++)
		{
			if(sta.m[i][j]!=' ' && sta.m[i][j]!=last_state[i][j])
				sum += 1;
		}
	}

	sta.min_step = sum;
}

bool operator < (const struct state &a, const struct state &b)
{
	if(a.step+a.min_step > b.step+b.min_step)
		return true;
	else if(a.step+a.min_step < b.step+b.min_step)
		return false;
	else
	{
		if(a.step > b.step)
			return true;
		else
			return false;
	}
}

map<int, list<struct state> > hash_table;
priority_queue<struct state> pq;

unsigned int _hash(const struct state sta)
{
	int i, j;
	unsigned int v;

	v = 1;
	for(i=1; i<=5; i++)
	{
		for(j=1; j<-5; j++)
		{
			if(sta.m[i][j] == '1')
				v = v*i*431 + j;
		}
	}

	return v%MAX_HASH;
}

bool is_visited(const struct state &sta)
{
	unsigned int hv;
	bool same;
	int i, j;

	hv = _hash(sta);
	if(hash_table.find(hv) == hash_table.end())
		return false;
	else
	{
		list<struct state> &l = hash_table[hv];
		list<struct state>::iterator it;
		for(it=l.begin(); it!=l.end(); it++)
		{
			same = true;
			for(i=1; i<=5; i++)
				for(j=1; j<=5; j++)
					if(it->m[i][j] != sta.m[i][j])
					{
						same = false;
						goto l1;
					}
			l1:
			if(same)
				return true;
			else
				continue;
		}
	}

	return false;
}

void insert2hashtalbe(const struct state &sta)
{
	unsigned int hv;

	hv = _hash(sta);
	hash_table[hv].push_back(sta);
}

bool is_last_state(const struct state &sta)
{
	int i;
	bool same;
	
	same = true;
	for(i=1; i<=5; i++)
	{
		if(strcmp(sta.m[i]+1, last_state[i]+1))
		{
			same = false;
			break;
		}
	}

	return same;
}

bool find_target;
int change[8][2] =
{
	1, 2,
	-1, 2,
	1, -2,
	-1, -2,
	2, 1,
	-2, 1, 
	2, -1,
	-2, -1
};

void print_arr(const struct state &sta)
{
	for(int i=1; i<=5; i++)
	{
		printf("%s\n", sta.m[i]+1);
	}
	printf("\n");
}

void bfs()
{
	struct state sta_top, sta;
	int from_i, from_j;
	int i;

	while(!pq.empty())
	{
		memcpy(&sta_top, &(pq.top()), sizeof(struct state));
		pq.pop();

		//printf("pop: step=%d\n", sta_top.step);
		//print_arr(sta_top);


		if(is_last_state(sta_top))
		{
			find_target = true;
			printf("Solvable in %d move(s).\n", sta_top.step);
			break;
		}

		for(i=0; i<8; i++)
		{
			memcpy(&sta, &sta_top, sizeof(struct state));
			from_i = sta.blank_i+change[i][0];
			from_j = sta.blank_j+change[i][1];
			if(from_i>=1 && from_i<=5 && from_j>=1 && from_j<=5)
			{
				sta.m[sta.blank_i][sta.blank_j] = sta.m[from_i][from_j];
				sta.m[from_i][from_j] = ' ';
				sta.blank_i = from_i;
				sta.blank_j = from_j;
				sta.step ++;
				get_min_step(sta);
				if(!is_visited(sta) && (sta.step+sta.min_step) <= 10)
				{
					pq.push(sta);
					insert2hashtalbe(sta);
				}
			}
		}
	}
}

void func(const struct state &sta)
{
	while(!pq.empty()) pq.pop();
	hash_table.clear();

	find_target = false;
	if(sta.step+sta.min_step<=10)
	{
		pq.push(sta);
		insert2hashtalbe(sta);
	}
	bfs();

	if(!find_target)
		printf("Unsolvable in less than 11 move(s).\n");
}

char buffer[100];
int main(void)
{
	int n, i, j;
	struct state sta;

	//freopen("input.dat", "r", stdin);
	init();
	gets(buffer);
	sscanf(buffer, "%d", &n);
	while(n--)
	{
		for(i=1; i<=5; i++)
			gets(sta.m[i]+1);

		for(i=1; i<=5; i++)
			for(j=1; j<=5; j++)
			{
				if(sta.m[i][j] == ' ')
				{
					sta.blank_i = i;
					sta.blank_j = j;
					goto run_func;
				}
			}
		
		run_func:
		sta.step = 0;
		get_min_step(sta);
		func(sta);
	}

	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值