首页 > 代码库 > 【bzoj1085】 SCOI2005—骑士精神

【bzoj1085】 SCOI2005—骑士精神

http://www.lydsy.com/JudgeOnline/problem.php?id=1085 (题目链接)

题意

  给出一个初始局面,问能否在15步内走到最终局面,并输出最少步数。

Solution

  迭代加深+A*,估价函数就是有cnt个子不在最终局面的位置,也就是说就算每一步都能将一个子归位,那么至少也需要cnt步。

  终于有点理解估价函数的意义了,估出来的必须必实际的要小,这才能保证答案的正确性。

代码

// bzoj1085#include<algorithm>#include<iostream>#include<cstdlib>#include<cstring>#include<cstdio>#include<cmath>#include<queue>#define LL long long#define inf 2147483640#define Pi acos(-1.0)#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);using namespace std;int ans[5][5]={{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}};int xx[8]={1,2,2,1,-1,-2,-2,-1};int yy[8]={2,1,-1,-2,-2,-1,1,2};int a[5][5],d,flag;char ch[10];bool judge() {	for (int i=0;i<5;i++)		for (int j=0;j<5;j++) if (a[i][j]!=ans[i][j]) return 0;	return 1;}bool eva(int s) {	int cnt=-1;	for (int i=0;i<5;i++)		for (int j=0;j<5;j++) if (a[i][j]!=ans[i][j]) if (++cnt==d-s) return 0;	return 1;}void dfs(int s,int x,int y) {	if (s==d) {if (judge()) flag=1;return;}	for (int i=0;i<8;i++) {		int nx=x+xx[i],ny=y+yy[i];		if (nx<0 || nx>4 || ny<0 || ny>4) continue;		swap(a[x][y],a[nx][ny]);		if (eva(s)) dfs(s+1,nx,ny);		if (flag) return;		swap(a[x][y],a[nx][ny]);	}}int main() {	int T;scanf("%d",&T);	while (T--) {		int x,y;flag=0;		for (int i=0;i<5;i++) {			scanf("%s",ch);			for (int j=0;j<5;j++) {				if (ch[j]==‘*‘) a[i][j]=2,x=i,y=j;				else a[i][j]=ch[j]-‘0‘;			}		}		for (d=0;d<=15;d++) {			dfs(0,x,y);			if (flag) {printf("%d\n",d);break;}		}		if (!flag) puts("-1");	}	return 0;}

 

【bzoj1085】 SCOI2005—骑士精神