【启发式搜索】【A*算法】hdu6171 Admiral

一个舰队的目标状态如上图。红色是旗舰。然后给你初始局面,每一次决策可以把旗舰和其上一层或下一层的两个相邻的进行交换。如果能在20步内出解的话,输出最小步数;否则输出“too difficult”。

把每个方块当成0~5的数,整个状态正好可以压缩成1个21位的6进制数,恰好可以用long long存下,可以用set / 哈希表存储。

定义估价函数f(S)表示局面S的每个格子所在层数与它的目标状态所在层的差的绝对值之和。

这样每一次移动最多使这个值减小2,如果这个值大于(20-已经走的步数)*2,则剪枝。

#include<cstdio>
#include<algorithm>
#include<queue>
#include<set>
using namespace std;
const int dx[]={1,1,-1,-1},dy[]={0,1,0,-1};
typedef long long ll;
typedef pair<int,int> Point;
set<ll>S;
int T;
struct Node{
	ll st;
	Point pos;
	int d;
	Node(){}
	Node(const ll &st,const Point &pos,const int &d){
		this->st=st;
		this->pos=pos;
		this->d=d;
	}
};
int ceng[25];
int Abs(int x){
	return x<0 ? (-x) : x;
}
int calc(ll x){
	int res=0;
	for(int i=0;i<=20;++i){
		res+=Abs((int)(x%6ll)-ceng[i]);
		x/=6;
	}
	return res;
}
queue<Node>q;
int wei[8][8];
ll pw[30];
int main(){
	int x;
//	freopen("1001.in","r",stdin);
//	freopen("1001.out","w",stdout);
	pw[0]=1;
	for(int i=1;i<=20;++i){
		pw[i]=pw[i-1]*6ll;
	}
	scanf("%d",&T);
	ceng[0]=ceng[1]=ceng[2]=ceng[3]=ceng[4]=ceng[5]=5;
	ceng[6]=ceng[7]=ceng[8]=ceng[9]=ceng[10]=4;
	ceng[11]=ceng[12]=ceng[13]=ceng[14]=3;
	ceng[15]=ceng[16]=ceng[17]=2;
	ceng[18]=ceng[19]=1;
	ceng[20]=0;
	int pen=20;
	for(int i=0;i<6;++i){
		for(int j=0;j<=i;++j){
			wei[i][j]=pen;
			--pen;
		}
	}
	ll goal=0;
	for(int i=0;i<6;++i){
		for(int j=0;j<=i;++j){
			goal=goal*6ll+(ll)i;
		}
	}
	for(;T;--T){
		S.clear();
		ll st=0;
		Point stapos;
		for(int i=0;i<6;++i){
			for(int j=0;j<=i;++j){
				scanf("%d",&x);
				if(x==0){
					stapos=Point(i,j);
				}
				st=st*6ll+(ll)x;
			}
		}
		if(st==goal){
			puts("0");
			continue;
		}
		S.insert(st);
		bool ok=0;
		while(!q.empty()){
			q.pop();
		}
		q.push(Node(st,stapos,0));
		while(!q.empty()){
			Node U=q.front(); q.pop();
//			ll now=U.st;
//			for(int i=0;i<6;++i){
//				for(int j=0;j<=i;++j){
//					printf("%I64d ",now/pw[wei[i][j]]%6ll);
//				}
//				puts("");
//			}
//			puts("");
			if(U.d>=20){
				continue;
			}
			for(int i=0;i<4;++i){
				int tx=U.pos.first+dx[i],ty=U.pos.second+dy[i];
				if(tx>=0 && tx<=5 && ty>=0 && ty<=tx){
					ll nextst=U.st-pw[wei[tx][ty]]*(U.st/pw[wei[tx][ty]]%6ll);
					nextst+=pw[wei[U.pos.first][U.pos.second]]*(U.st/pw[wei[tx][ty]]%6ll);
					int tmp=calc(nextst);
					if(S.find(nextst)==S.end() && tmp<=(20-(U.d+1))*2){
						if(nextst==goal){
							ok=1;
							printf("%d\n",U.d+1);
							break;
						}
						S.insert(nextst);
						q.push(Node(nextst,Point(tx,ty),U.d+1));
					}
				}
			}
			if(ok){
				break;
			}
		}
		if(!ok){
			puts("too difficult");
		}
	}
	return 0;
}
时间: 2024-12-24 18:18:14

【启发式搜索】【A*算法】hdu6171 Admiral的相关文章

启发式搜索A*算法

A* 寻路算法 (2011-02-15 10:53:11) 转载▼ 标签: 游戏 分类: 算法 概述 虽然掌握了 A* 算法的人认为它容易,但是对于初学者来说, A* 算法还是很复杂的. 搜索区域(The Search Area) 我们假设某人要从 A 点移动到 B 点,但是这两点之间被一堵墙隔开.如图 1 ,绿色是 A ,红色是 B ,中间蓝色是墙. 图 1 你应该注意到了,我们把要搜寻的区域划分成了正方形的格子.这是寻路的第一步,简化搜索区域,就像我们这里做的一样.这个特殊的方法把我们的搜索

A*搜寻算法(A星算法)

A*搜寻算法[编辑] 维基百科,自由的百科全书 本条目需要补充更多来源.(2015年6月30日) 请协助添加多方面可靠来源以改善这篇条目,无法查证的内容可能会被提出异议而移除. A*搜索算法,俗称A星算法.这是一种在图形平面上,有多个节点的路径,求出最低通过成本的算法.常用于游戏中的NPC的移动计算,或在线游戏的BOT的移动计算上. 该算法综合了BFS(Breadth First Search)和Dijkstra算法的优点:在进行启发式搜索提高算法效率的同时,可以保证找到一条最优路径(基于评估函

【算法入门】深度优先搜索(DFS)

深度优先搜索(DFS) [算法入门] 1.前言深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍历的算法.它的思想是从一个顶点V0开始,沿着一条路一直走到底,如果发现不能到达目标解,那就返回到上一个节点,然后从另一条路开始走到底,这种尽量往深处走的概念即是深度优先的概念. 你可以跳过第二节先看第三节,:) 2.深度优先搜索VS广度优先搜索 2.1演示深度优先搜索的过程还是引用上篇文章的样例图,起点仍然是V0,我们修改一下题目意思,只需要让你找出一条V0到V6的道路,而无需最短

深度优先搜索(DFS)详解

深度优先搜索(DFS) [算法入门] 1.前言 深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍历的算法.它的思想是从一个顶点V0开始,沿着一条路一直走到底,如果发现不能到达目标解,那就返回到上一个节点,然后从另一条路开始走到底,这种尽量往深处走的概念即是深度优先的概念. 你可以跳过第二节先看第三节,:) 2.深度优先搜索VS广度优先搜索 2.1演示深度优先搜索的过程 还是引用上篇文章的样例图,起点仍然是V0,我们修改一下题目意思,只需要让你找出一条V0到V6的道路,而无需

数据结构6——DFS

一.相关定义 深度优先遍历,也有称为深度优先搜索,简称DFS.其实,就像是一棵树的前序遍历. 初始条件:图G所有顶点均未被访问过,任选一点v. 遍历过程:它从图中某个结点v出发,访问此顶点,然后依次从v的未被访问的邻接点出发深度优先遍历图,直至图中所有和v有路径相通的顶点都被访问到.若图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点,重复上述过程,直至图中的所有顶点都被访问到为止. DFS适合此类题目 给定初始状态跟目标状态,要求判断从初始状态到目标状态是否有解. 二.算法过程 以如

对于搜索的新理解

搜索是什么? 1.问题全状态空间 2.搜索空间 3.解路径 分类 一,盲目搜索(只是搜索的顺序不同) 1.深度优先搜索 2.宽度优先搜索 二,启发式搜索 A*算法 分类来讲 1.深度优先搜索 例题:皇后问题 存在的问题:1.深度问题,2.死循环问题 解决办法:1.对搜索深度加以限制                   2.记录从初始状态到当前状态的路径 性质:一般不能保证找到最优解           当深度现在不合理时,可能找不到解,可以将算法改为可变深度限制           最坏的情况,

启发式搜索(heuristic search)———A*算法

在宽度优先和深度优先搜索里面,我们都是根据搜索的顺序依次进行搜索,可以称为盲目搜索,搜索效率非常低. 而启发式搜索则大大提高了搜索效率,由这两张图可以看出它们的差别: (左图类似与盲搜,右图为启发式搜索)(图片来源)   很明显启发式的搜索效率远远大于盲搜. 什么是启发式搜索(heuristic  search) 利用当前与问题有关的信息作为启发式信息,这些信息是能够提升查找效率以及减少查找次数的. 如何使用这些信息,我们定义了一个估价函数 h(x) .h(x)是对当前状态x的一个估计,表示 x

寻路算法之A*算法

A*算法是用于寻找两点之间的最短路径,同时它也是一种静态路网中求解最短路最有效的直搜索方法,公式f(n)=h(n)+g(n)给出了邻居节点到目标节点所需要的总消耗成本,h(n)是当前节点到该邻居节点的所消耗的成本,g(n)是该邻居节点到目标节点的估计消耗成本,比较常用的估计方法是欧几里得方法和曼哈顿方法. A*算法首先要准备两个列表,一个开启列表,一个关闭列表,开启列表存储还未走的节点(但不是一开始就把所有节点加入开启列表),关闭列表存储走过的节点,将起始节点加入到开启列表,在开启列表不为空时,

特征选择常用算法综述

特征选择的一般过程: 1.生成子集:搜索特征子集,为评价函数提供特征子集 2.评价函数:评价特征子集的好坏 3.停止准则:与评价函数相关,一般是阈值,评价函数达到一定标准后就可停止搜索 4.验证过程:在验证数据集上验证选出来的特征子集的有效性 1.生成子集 搜索算法有 完全搜索.启发式搜索.随机搜索 三大类. (1)完全搜索 <1>宽搜(Breadth First Search):时间复杂度高,不实用 <2>分支界限搜索(Branch and Bound):其实就是宽搜加上深度的限