题目链接 : BZOJ 1085

题目分析 :

  本题中可能的状态会有 (2^24) * 25 种状态,需要使用优秀的搜索方式和一些优化技巧。

  我使用的是 IDA* 搜索,从小到大枚举步数,每次 DFS 验证在当前枚举的步数之内能否到达目标状态。

  如果不能到达,就枚举下一个步数,重新搜索,即使某些状态在之前的 DFS 中已经搜索过,我们仍然搜索。

  并且在一次 DFS 中,我们不需要判定重复的状态。

  在 IDA* 中,重要的剪枝优化是 估价函数 ,将一些不可能存在可行解的枝条剪掉。

  如果估价函数写得高效,就能有极好的效果。我们写估价函数的原则是,绝对不能剪掉可能存在可行解的枝条。

  因此,在预估需要步数时,应让估计值尽量接近实际步数,但一定不能大于实际需要的步数。

  本题的一个很有效的估价函数是,比较当前状态的黑白骑士与目标状态的黑白骑士有多少不同,我们把这个值作为估价函数值,因为每一步最多将当前状态的一个骑士改变为与目标状态相同。但是应该注意的是,空格所在的格子不要算入其中。

代码如下:

  

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
 
using namespace std;
 
const int MaxStep = ;
const int Dx[] = {, , -, -, , , -, -}, Dy[] = {, -, , -, , -, , -};
 
int Te, Ans;
 
char Str[];
 
struct ES
{
    int num, pos;
    bool operator == (const ES &e) const {
        return (num == e.num) && (pos == e.pos);
    }
} S, T;
 
inline bool Inside(int x, int y) {
    if (x < || x > ) return false;
    if (y < || y > ) return false;
    return true;
}
 
void Print(ES x) {
    for (int i = ; i < ; ++i) {
        for (int j = ; j < ; ++j) {
            if (x.pos == (i * + j)) printf("*");
            else {
                if (x.num & ( << (i * + j))) printf("");
                else printf("");
            }
        }
        printf("\n");
    }
}
 
inline int Expect(ES x) {
    int Temp, Cnt;
    Temp = x.num ^ T.num;
    Cnt = ;
    if (x.pos != T.pos) {
        if (Temp & ( << T.pos)) --Cnt;
        if (Temp & ( << x.pos)) --Cnt;
    }
    while (Temp) {
        ++Cnt;
        Temp -= Temp & -Temp;
    }
    return Cnt;
}
 
bool DFS(ES Now, int Step, int Limit) {
    if (Now == T) return true;
    if (Step == Limit) return false;
    if (Expect(Now) > Limit - Step) return false;
    int x, y, xx, yy;
    ES Next;
    x = Now.pos / ; y = Now.pos % ;
    for (int i = ; i < ; i++) {
        xx = x + Dx[i]; yy = y + Dy[i];
        if (!Inside(xx, yy)) continue;
        Next = Now;
        Next.pos = xx * + yy;
        Next.num &= ( << ) - - ( << (xx * + yy));
        if (Now.num & ( << (xx * + yy))) Next.num |= ( << (x * + y));
        if (DFS(Next, Step + , Limit)) return true;
    }
    return false;
}
 
int IDAStar(ES S) {
    if (S == T) return ;
    for (int i = ; i <= MaxStep; ++i)
        if (DFS(S, , i)) return i;
    return -;
}
 
int main()
{
    scanf("%d", &Te);
    T.num = ; T.pos = ;
    for (int Case = ; Case <= Te; ++Case) {
        S.num = ;
        for (int i = ; i < ; ++i) {
            scanf("%s", Str);
            for (int j = ; j < ; ++j) {
                if (Str[j] == '') S.num |= ( << (i * + j));
                if (Str[j] == '*') S.pos = i * + j;
            }
        }
        Ans = IDAStar(S);
        printf("%d\n", Ans);
    }
    return ;
}

  

[BZOJ 1085] [SCOI2005] 骑士精神 [ IDA* 搜索 ]的更多相关文章

  1. bzoj 1085 [SCOI2005]骑士精神——IDA*

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1085 迭代加深搜索. 估价函数是为了预计步数来剪枝,所以要优于实际步数. 没错,不是为了确定 ...

  2. bzoj 1085: [SCOI2005]骑士精神 IDA*

    题目链接 给一个图, 目标位置是确定的, 问你能否在15步之内达到目标位置. 因为只有15步, 所以直接ida* #include<bits/stdc++.h> using namespa ...

  3. Bzoj 1085: [SCOI2005]骑士精神 (dfs)

    Bzoj 1085: [SCOI2005]骑士精神 题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1085 dfs + 剪枝. 剪枝方法: ...

  4. BZOJ 1085: [SCOI2005]骑士精神( IDDFS + A* )

    一开始写了个 BFS 然后就 T 了... 这道题是迭代加深搜索 + A* -------------------------------------------------------------- ...

  5. BZOJ 1085 [SCOI2005]骑士精神 【A*启发式搜索】

    1085: [SCOI2005]骑士精神 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 2838  Solved: 1663 [Submit][St ...

  6. bzoj 1085: [SCOI2005]骑士精神

    Description 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士,且有一个空位.在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵 ...

  7. [BZOJ 1085][SCOI2005]骑士精神(IDA*)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1085 分析: 首先第一感觉是宽搜,但是空间需要8^15*5*5,明显不够,又鉴于最大深 ...

  8. BZOJ.1085.[SCOI2005]骑士精神(迭代加深搜索)

    题目链接 最小步数这类,适合用迭代加深搜索. 用空格走代替骑士. 搜索时记录上一步防止来回走. 不需要每次判断是否都在位置,可以计算出不在对应位置的骑士有多少个.而且每次复原一个骑士至少需要一步. 空 ...

  9. BZOJ 1085: [SCOI2005]骑士精神(A*算法)

    第一次写A*算法(这就是A*?如果这就是A*的话,那不就只是搜索的一个优化了= =,不过h函数如果弄难一点真的有些难设计) 其实就是判断t+h(x)(t为当前步数,h(x)为达到当前状态的最小步数) ...

随机推荐

  1. HTML Canvas 鼠标画图

    原文来自:http://www.williammalone.com/articles/create-html5-canvas-javascript-drawing-app(已被墙) 译文: http: ...

  2. export 命令 设置环境变量

    export KERN_DIR=/usr/src/kernels/2.6.18-194.11.1.el5-x86_64 设置环境变量 内核加载目录

  3. 如何更改应用在app store的名称

    如何修改应用在app store 的名称,我修改了plist里面的bundle display name,现在安装后在设备上会显示修改后的名称,可是app store里面还是原来的名称. 何把app ...

  4. [AngularJS + Webpack] Production Setup

    Using Angular with webpack makes the production build a breeze. Simply alter your webpack configurat ...

  5. 【译】Android应用架构

    Android开发生态圈的节奏非常之快.每周都会有新的工具诞生,类库的更新,博客的发表以及技术探讨.如果你外出度假一个月,当你回来的时候可能已经发布了新版本的Support Library或者Play ...

  6. Java基础知识强化02:import static 和 import

    1.import static静态导入是JDK1.5中的新特性.一般我们导入一个类都用 import com.....ClassName;而静态导入是这样:import static com..... ...

  7. Android 布局

    转自:http://www.cnblogs.com/chiao/archive/2011/08/24/2152435.html Android布局是应用界面开发的重要一环,在Android中,共有五种 ...

  8. 快速记忆JavaScript中exec和match的使用

    JS模式匹配中exec,match用得非常多,所以掌握其用法对我们进行字符串的处理帮助非常大 1.exec的定义其用法        exec与match主要的不同是,exec是正则表达式里面的方法. ...

  9. ImageView 设置OnTouchListener

    ImageView的OnTouchListener,onTouch方法要返回true,MotionEvent.ACTION_UP,MotionEvent.ACTION_MOVE 才有效. 其实关于返回 ...

  10. nest 'for' loop.

    /* nest for loop demo. Note that,'upside' triangle controls 'inner condition'. */ import kju.print.P ...