C++高級搜索算法迭代加深—————騎士精神

 

題目描述:

在一個5×5的棋盤上有12個白色的騎士和12個黑色的騎士,且有一個空位。在任何時候一個騎士都能按照騎士的走法(它可以走到和它橫座標相差爲1,縱座標相差爲2或者橫座標相差爲2,縱座標相差爲1的格子)移動到空位上。

給定一個初始的棋盤,怎樣才能經過移動變成如下目標棋盤:

爲了體現出騎士精神,他們必須以最少的步數完成任務。

輸入:

輸出:

輸入樣例:

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

輸出樣例:

7

-1

思路分析:

根據迭代加深搜索,我們可以將移動步數爲搜索深度,然後步步搜索,然後我們可以用一個目標數組置爲答案。

之後,我們再用一個樂觀估計函數做剪枝,但是可是這該如何定義呢?

我們可以設想,假設我們現在的數組與目標數組的相差值與接下來的可用步數大,

那麼我們不可能得到答案,所以我們可以返回。

代碼實現;

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int find1=0,dx[9]={0,1,1,-1,-1,2,2,-2,-2},dy[9]={0,2,-2,2,-2,1,-1,1,-1},t,a[10][10],sx,sy;
char w;
int goal[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 check()
{
	int dif=0;
	for(int i=0;i<5;i++)
		for(int j=0;j<5;j++)
		{
			if(goal[i][j]!=a[i][j])
				dif++;
		}
	return dif;
}
void iddfs(int x,int y,int de,int k)
{
	if(de==k)
	{
		if(!check())
			find1=1;
		return;
	}
	for(int i=1;i<=8;i++)
	{
		int x1=x+dx[i];
		int y1=y+dy[i];
		if(x1<0||x1>4||y1<0||y1>4)
			continue;
		swap(a[x][y],a[x1][y1]);
		if(de+check()<=k)
            iddfs(x1,y1,de+1,k);
		swap(a[x][y],a[x1][y1]);
	}
}
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		for(int i=0;i<5;i++){
            getchar();
			for(int j=0;j<5;j++)
			{
				scanf("%c",&w);
				if(w=='*')
				{
					a[i][j]=2;
					sx=i;
					sy=j;
				}
				else
					a[i][j]=w-'0';
			}
		}
		int k;
		for(k=0;k<=15;k++)
		{
			iddfs(sx,sy,0,k);
			if(find1)
				break;
		}
		if(k>15)
			printf("-1\n");
		else
			printf("%d\n",k);
		find1=0;
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章