【BZOJ】1085 [SCOI2005]骑士精神 IDA*

80 篇文章 1 订阅
4 篇文章 0 订阅

题目传送门

好吧,对于一个初学者,我连自己打的是A*还是IDA*都不知道……

这题如果用BFS来做肯定是要TLE的,那么我们就能想到用BFS的进化版——A*来做。

可以说BFS是一种特殊的A*:因为用A*的思想来考虑BFS,就会发现BFS的估价函数永远等于0。

A*比BFS就多了一个估价函数,但是A*却比BFS更快、更强!

设估价函数f(i)=g(i)+h(i),g(i)为当前搜索层数,h(i)为当前状态和目标状态的错位个数。

若当前的估价函数f(i)已经大于了当前的ans,那么接着搜索下去也不可能比当前的ans更优,所以就返回。

以上就是估价函数的基本思想,其实还是挺好理解的。

IDA*就是把A*的广搜改成了深搜,省了空间。

就这样吧,希望我的博客对各位同学有所帮助:)

附上AC代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int n=5;
const int e[6][6]={	{0,0,0,0,0,0},
					{0,1,1,1,1,1},
					{0,0,1,1,1,1},
					{0,0,0,-6,1,1},
					{0,0,0,0,0,1},
					{0,0,0,0,0,0}};
const int dx[9]={0,1,1,-1,-1,2,2,-2,-2};
const int dy[9]={0,2,-2,2,-2,1,-1,1,-1};
int t,ans,xx,yy,map[6][6];
char c;
bool b[6][6];

bool pd(){
	for (int i=1; i<=n; ++i)
		for (int j=1; j<=n; ++j)
			if (map[i][j]!=e[i][j]) return 0;
	return 1;
}

int astar(int sum){
	for (int i=1; i<=n; ++i)
		for (int j=1; j<=n; ++j)
			if (map[i][j]!=e[i][j]) ++sum;
	return sum;
}

void so(int x,int y,int sum){
	if (pd()) ans=min(ans,sum);
	if (sum>=ans) return;
	for (int i=1; i<=8; ++i){
		int fx=x+dx[i],fy=y+dy[i];
		if (fx<1||fx>n||fy<1||fy>n) continue;
		swap(map[x][y],map[fx][fy]);
		if (astar(sum)<=ans) so(fx,fy,sum+1);
		swap(map[x][y],map[fx][fy]);
	}
	return;
}

int main(void){
	scanf("%d",&t);
	while (t--){
		for (int i=1; i<=n; ++i)
			for (int j=1; j<=n; ++j){
				c=getchar();
				while (c!='1'&&c!='0'&&c!='*') c=getchar();
				if (c=='*') xx=i,yy=j;
				map[i][j]=c-'0';
			}
		ans=16;
		so(xx,yy,0);
		printf("%d\n",ans>15?-1:ans);
	}
	return 0;
}
P.S:洛谷真的是个神奇的OJ,我在BZOJ上测是可以过的程序,放到洛谷上就会TLE——O2真的是个好东西。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值