算法复习——迭代加深搜索(骑士精神bzoj1085)

Posted AseanA

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法复习——迭代加深搜索(骑士精神bzoj1085)相关的知识,希望对你有一定的参考价值。

题目:

Description

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

技术分享

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

题解:

  首先说一下迭代加深搜索:

  迭代加深搜索是搜索算法的一种优化方式,具体方法为在知道搜索最大深度的情况下(如题目中最多15步)从低到高枚举搜索深度上界,则第一个满足的枚举深度就一定是最浅深     度即最优解,另外为了更好的优化,还可以构造一个预估函数,即当前搜索状态到满足题意状态至少要用多少步(注意该函数宁愿估小也不要估大否则可能发生错误),如果当前     搜索深度加上预估函数的值都大于枚举深度那肯定也不满足;

  迭代加深搜索适用于便于预估所有状态下搜索上界的情况,且搜索深度不大的情况;

  不懂的话结合这道题和代码理解即可;

代码:

  

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const char goal[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 sx,sy,T,step;
char map[5][5];
struct node
{
  int gox;
  int goy;
}go[8];
inline void pre()
{
  go[0].gox=1,go[0].goy=2;
  go[1].gox=1,go[1].goy=-2;
  go[2].gox=2,go[2].goy=1;
  go[3].gox=2,go[3].goy=-1;
  go[4].gox=-1,go[4].goy=2;
  go[5].gox=-1,go[5].goy=-2;
  go[6].gox=-2,go[6].goy=1;
  go[7].gox=-2,go[7].goy=-1;
}
inline bool jud(int x,int y)
{
  return x>=0&&x<=4&&y>=0&&y<=4;
}
inline int check()
{
  int dif=0;
  for(int i=0;i<=4;i++)
    for(int j=0;j<=4;j++)
      if(map[i][j]!=goal[i][j])  dif++;
  return dif;
}
inline bool dfs(int x,int y,int now)
{
  if(now==step+1)
  {  
    if(check()==0)  return true;
    else  return false;
  }
  if(now+check()-3>step)  return false;
  for(int i=0;i<=7;i++)  
  {
    int tx=x+go[i].gox;
    int ty=y+go[i].goy;
    if(jud(tx,ty))
    {
      swap(map[x][y],map[tx][ty]);
      if(dfs(tx,ty,now+1))  return true;
      swap(map[x][y],map[tx][ty]);
    }
  }
  return false;
}
int main()
{
  //freopen("a.in","r",stdin);
  scanf("%d",&T);
  pre();
  while(T--)
  {
    sx=sy=0;
    for(int i=0;i<=4;i++)
      scanf("%s",map[i]);
    bool flag=false;
    for(int i=0;i<=4;i++)
    {  
      if(flag==true)  break; 
      for(int j=0;j<=4;j++)
        if(map[i][j]==*)
        {
          sx=i,sy=j;
          flag=true;
          break;
        }
    }
    step=1;
    for(int i=1;i<=15;i++)
    {  
      if(dfs(sx,sy,1))  break;
      step++;
    }
    if(step==16)  cout<<"-1"<<endl;
    else  cout<<step<<endl;
  }
  return 0;
}

 



















以上是关于算法复习——迭代加深搜索(骑士精神bzoj1085)的主要内容,如果未能解决你的问题,请参考以下文章

[BZOJ1085][SCOI2005]骑士精神 搜索

bzoj1085 SCOI2005—骑士精神

A*算法详解 BZOJ 1085骑士精神

bzoj 1085骑士精神 迭代深搜

BZOJ1085SCOI2005骑士精神 [A*搜索]

BZOJ1085: [SCOI2005]骑士精神