BZOJ-1085 SCOI 2005 骑士精神 迭代加深 A*爆搜

5 篇文章 0 订阅
3 篇文章 0 订阅

大家都很强, 可与之共勉 。

1085: [SCOI2005]骑士精神
Time Limit: 10 Sec Memory Limit: 162 MB
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

HINT

Source

[Submit]

迭代加深搜索
估价函数设为当前不相同的骑士个数 + 当前步数 <= 期望最大步数

/**************************************************************
    Problem: 1085
    User: Lazer2001
    Language: C++
    Result: Accepted
    Time:588 ms
    Memory:1848 kb
****************************************************************/

# include <cctype>
# include <cstdio>

# define By_Lazer  int main ( ) {  return 0 ;  }

const int N = 100005 ;

struct IO  {
    char buf [1 << 20], *s, *t, ch ;

    inline char pick ( )  {
        return ( s == t ) ? ( t = buf + fread ( s = buf, 1, 1 << 20, stdin ), *s ++ ) : ( *s ++ ) ;
    }

    int x ;

    inline operator int ( )  {
        while ( ! isdigit ( ch = pick ( ) ) ) ;
        for ( x = -48 + ch ; isdigit ( ch = pick ( ) ); x = x * 10 + ch - 48 ) ;
        return x ;
    }

} Read ;

short flag ;
int x, y ;
int a [6] [6] ;
int b [6] [6] = {
    { 1, 1, 1, 1, 1, 0 },
    { 0, 1, 1, 1, 1, 0 },
    { 0, 0, 2, 1, 1, 0 },
    { 0, 0, 0, 0, 1, 0 },
    { 0, 0, 0, 0, 0, 0 }
} ;

const int dx [8] = { -1, 1, -2, 2, -2, 2, -1, 1 }, dy [8] = { -2, -2, -1, -1, 1, 1, 2, 2 } ;

class Main  {
public :

    inline short Check ( )  {
        for ( int i = 0 ; i < 5 ; ++ i )
            for ( int j = 0 ; j < 5 ; ++ j )
                if ( a [i] [j] ^ b [i] [j] )  
                    return 0 ;
        return 1 ;
    }

    inline short Eva ( )  {
        int cnt = 0 ;
        for ( int i = 0 ; i < 5 ; ++ i )
            for ( int j = 0 ; j < 5 ; ++ j )
                if ( a [i] [j] ^ b [i] [j] )  ++ cnt ;
        return cnt ;
    }

    inline void Dfs ( int x, int y, int step, int& expected )  {
        if ( flag )  return ;
        if ( step == expected )  {
            if ( Check ( ) )  flag = 1 ;
            return ;
        }

        for ( int i = 0 ; i < 8 ; ++ i )  {
            int x1 = x + dx [i], y1 = y + dy [i] ;
            if ( x1 < 5 && x1 >= 0 && y1 < 5 && y1 >= 0 )  {
                a [x] [y] ^= a [x1] [y1] ^= a [x] [y] ^= a [x1] [y1] ;
                int val = Eva ( ) ;
                if ( val + step <= expected )
                    Dfs ( x1, y1, step + 1, expected ) ;
                a [x] [y] ^= a [x1] [y1] ^= a [x] [y] ^= a [x1] [y1] ;
            }
        }
    }

    Main ( )  {
        for ( int T = Read ; T ; -- T, flag = 0 )  {

            for ( int i = 0 ; i < 5 ; ++ i )  {
                for ( int j = 0 ; j < 5 ; ++ j )  {
                    static char ch ;
                    while ( ( ch = Read.pick ( ) ) == ' ' || ch == '\n' ) ;
                    if ( ch == '1' )  a [i] [j] = 1 ;
                    else if ( ch == '0' ) a [i] [j] = 0 ;
                    else a [i] [j] = 2, x = i, y = j ;
                }
            }

            if ( Check ( ) )  {
                puts ( "0" ) ;
                continue ;
            }

            for ( int i = 1 ; i <= 15 ; ++ i )  {
                Dfs ( x, y, 0, i ) ;
                if ( flag )  {
                    printf ( "%d\n", i ) ;
                    goto end ;
                }
            }
            puts ( "-1" ) ;
            end : ;
        }
    }
} Z ;

By_Lazer
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值