算法复习——迭代加深搜索(骑士精神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;
}
时间: 2024-10-05 05:46:24

算法复习——迭代加深搜索(骑士精神bzoj1085)的相关文章

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

转载1:A*算法入门 http://www.cppblog.com/mythit/archive/2009/04/19/80492.aspx 在看下面这篇文章之前,先介绍几个理论知识,有助于理解A*算法. 启发式搜索:启发式搜索就是在状态空间中的搜索对每一个搜索的位置进行评估,得到最好的位置,再从这个位置进行搜索直到目标.这样可以省略大量无畏的搜索路径,提到了效率.在启发式搜索中,对位置的估价是十分重要的.采用了不同的估价可以有不同的效果. 估价函数:从当前节点移动到目标节点的预估费用:这个估计

IDDFS(迭代加深搜索)精选题and总结

引入:什么是IDDFS? 在计算机科学中,迭代深化搜索(iterative deepening search)或者更确切地说迭代深化深度优先搜索 (iterative deepening depth-first search (IDS or IDDFS)) 是一个状态空间(状态图)搜索策略.在这个搜索策略中,一个具有深度限制的深度优先搜索算法会不断重复地运行,并且同时放宽对于搜索深度的限制,直到找到目标状态.IDDFS 与广度优先算法是等价的,但对内存的使用会少很多:在每一步迭代中,它会按深度优

【迭代加深搜索】埃及分数问题

谢谢阿苏~http://blog.csdn.net/urecvbnkuhbh_54245df/article/details/5856756 [迭代加深搜索(ID,iterative deepening)]:从小到大枚举上限maxd,每次执行只考虑深度不超过maxd的结点. ------对于可以用回溯法求解但解答树的深度没有明显上限的题目,可以考虑ID算法: ------优点:它主要是在递归搜索函数的开头判断当前搜索的深度是否大于预定义的最大搜索深度,如果大于,就退出这一层的搜索,如果不大于,就

uva 11212 - Editing a Book(迭代加深搜索 IDA*) 迭代加深搜索

迭代加深搜索 自己看的时候第一遍更本就看不懂..是很水,但智商捉急也是没有办法的事情. 好在有几个同学已经是做过了这道题并且对迭代加深搜索的思路有了一定的了解,所以在某些不理解的地方询问了一下他们的见解, 真的是很有帮助,也许自己想要想很久才能想明白,还会很痛苦,稍微问一下别人的想法,点上一个方向,剩下的自己就能想得明白了. 迭代加深. 把answer(需要的步数或其他)在主函数里面从零往上递加,此之谓 "层数",亦可谓之"深度".用书上的话就是: 从小到大枚举深度

迭代加深搜索[codevs1004 四子连棋]

迭代加深搜索 一.算法简介 迭代加深搜索是在速度上接近广度优先搜索,空间上和深度优先搜索相当的搜索方式.由于在使用过程中引入了深度优先搜索,所以也可以当作深度优先搜索的优化方案. 迭代加深搜索适用于当搜索深度没有明确上限的情况. 例如上图的一棵搜索树,在进行深度优先搜索前先规定好这次搜索的最大深度dep,当搜索到达dep却还没搜索到结果时回溯. 之后不断加大搜索深度,重新搜索,直到找到结果为止.虽然这样搜索次数会累计很多次,但每一次搜索的范围和下一次搜索的范围相比微不足道,所以整体搜索速度不会受

“埃及分数”问题浅谈对迭代加深搜索的理解

迭代加深搜索(IDDFS)的思想 迭代加深搜索一般用来求解状态树"非常深",甚至深度可能趋于无穷,但是"目标状态浅"的问题.如果用普通的DFS去求解,往往效率不够高.此时我们可以对DFS进行一些改进.最直观的一种办法是增加一个搜索的最大深度限制maxd,一般是从1开始.每次搜索都要在maxd深度之内进行,如果没有找到解,就继续增大maxd,直到成功找到解,然后break. 如下图所示,如果用DFS,需要15步才能找到结点3,但是用迭代加深搜索,很快即可找到结点3.

Power Calculus UVA - 1374 迭代加深搜索

迭代加深搜索经典题目,好久不做迭代加深搜索题目,拿来复习了,我们直接对当前深度进行搜索,注意剪枝,还有数组要适当开大,因为2^maxd可能很大 题目:题目链接 AC代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cmath> 5 #include <algorithm> 6 #include <cstring> 7 #incl

UVA-11214 Guarding the Chessboard (迭代加深搜索)

题目大意:在一个国际象棋盘上放置皇后,使得目标全部被占领,求最少的皇后个数. 题目分析:迭代加深搜索,否则超时. 小技巧:用vis[0][r].vis[1][c].vis[2][r+c].vis[c-r+N]分别标志(r,c)位置相对应的行.列.主.副对角线有没有被占领(详见<入门经典(第2版)>P193),其中N表示任意一个比行数和列数都大(大于等于)的数. 代码如下: # include<iostream> # include<cstdio> # include&l

USACO/fence8 迭代加深搜索+剪枝

题目链接 迭代加深搜索思想. 枚举答案K,考虑到能否切出K个木头,那么我们当然选最小的K个来切. 1.对于原材料,我们是首选最大的还是最小的?显然,首选大的能够更容易切出,也更容易得到答案. 2.对于目标木头,我们是优先得到最大的还是最小的?显然,由于K个木头我们都要得到,那么当然先把最大的(最难得到的)先得到,这种搜索策略更优. 3.假设总原材料为all,前K个木头总和为sum,那么all-sum就是这一次切割过程中能[浪费]的最大数目.对于一个切剩下的原材料,若它比最小的目标木头还要小,则它