【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;
}

 

posted @ 2016-12-27 21:27  MashiroSky  阅读(228)  评论(1编辑  收藏  举报