【BZOJ1085/SCOI2005】骑士精神

                              1085: [SCOI2005]骑士精神

                                             Time Limit: 10 Sec  Memory Limit: 162 MB
                                                      Submit: 3548  Solved: 2113

Description

  在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位。在任何时候一个骑士都能按照骑
士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的格子)移动到空
位上。 给定一个初始的棋盘,怎样才能经过移动变成如下目标棋盘: 为了体现出骑士精神,他们必须以最少的步
数完成任务。

《【BZOJ1085/SCOI2005】骑士精神》

Input

  第一行有一个正整数T(T<=10),表示一共有N组数据。接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑
士,*表示空位。两组数据之间没有空行。

Output

  对于每组数据都输出一行。如果能在15步以内(包括15步)到达目标状态,则输出步数,否则输出-1。

Sample Input

2
10110
01*11
10111
01001
00000
01011
110*1
01110
01010
00100
 

Sample Output

7
-1

 

解析:

       IDA*。

       具体思想就是对每个状态计算一个评估值(即从这个状态到终点状态的步数),但这个评估值必须小等于实际值,不然会算出错误答案。对于这道题,迭代加深,若到达该状态的步数 + 评估值 > 深度限制则回溯。

 

代码:

#include <bits/stdc++.h>
using namespace std;

//const int fx[10]={0,2,2,-2,-2,1,1,-1,-1};
//const int fy[10]={0,1,-1,1,-1,2,-2,2,-2};
const int fx[10]={0,-2,-2,-1,-1,1,1,2,2},fy[10]={0,-1,1,-2,2,-2,2,-1,1};
const char tar[5][5]={
{'1','1','1','1','1'},
{'0','1','1','1','1'},
{'0','0','*','1','1'},
{'0','0','0','0','1'},
{'0','0','0','0','0'}};
int ans,t;
char a[5][5];

inline int find(int &x,int &y)
{
	int sum=0;
	for(int i=0;i<5;i++)
	  for(int j=0;j<5;j++)
	  {
	  	if(a[i][j]=='*') x=i,y=j;
	  	if(a[i][j]!=tar[i][j]) sum++;
	  }
    return sum;
}

inline bool dfs(int step,int lim)
{
	int x,y,rest;
	rest=find(x,y);
	if(rest+step-1>lim) return 0;
	if(!rest) return 1;
	for(int i=1;i<=8;i++)
	{
	  int x1=x+fx[i],y1=y+fy[i];
	  if(x1<0||x1>4||y1<0||y1>4) continue;
	  swap(a[x][y],a[x1][y1]);
	  if(dfs(step+1,lim)) return 1;
	  swap(a[x][y],a[x1][y1]);
	}
	return 0;
}

int main()
{
	scanf("%d",&t);
	while(t--)
	{
	  ans=-1;
	  for(int i=0;i<5;i++) scanf("%s",a[i]);
	  for(int i=0;i<=15;i++) if(dfs(0,i)) {ans=i;break;}
	  printf("%d\n",ans);
	}
	return 0;
}

 

    原文作者:骑士周游问题
    原文地址: https://blog.csdn.net/m0_38083668/article/details/83045540
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞