BZOJ1085: [SCOI2005]骑士精神

Posted mt-li

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ1085: [SCOI2005]骑士精神相关的知识,希望对你有一定的参考价值。

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
 
 
首先一个奇妙的想法:我们不让棋子跳,反而让空格跳
这样才有效率
话说棋盘这么小,那就DFS咯。。。
但是还是会T,所以要用到传说中的算法——A*
如果把DFS比作千里马的话,那A*就是伯乐了
起到一个引导的作用,在代码里我会给点注释
 
代码如下:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
int a[6][6];
const int dx[8]={1,1,-1,-1,2,2,-2,-2};
const int dy[8]={2,-2,2,-2,1,-1,1,-1};
int w;
bool bk;
int ans[6][6]={{0,0,0,0,0,0},{0,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}};
bool pd()
{
    for(int i=1;i<=5;i++)
        for(int j=1;j<=5;j++)
            if(a[i][j]!=ans[i][j])
                return false;
    return true;
}
bool A_star(int k,int w)//要求w步之内走完
{
    int s=0;
    for(int i=1;i<=5;i++)
        for(int j=1;j<=5;j++)
            if(a[i][j]!=ans[i][j])
            {
                s++;
                if(s+k>w)return false;
            }
    return true;
}
void dfs(int x,int y,int k)
{
    if(k==w)
    {
        if(pd()==true)bk=true;
        return ;
    }
    for(int i=0;i<8;i++)
    {
        int tx=x+dx[i],ty=y+dy[i];
        if(tx<1||ty<1||tx>5||ty>5)continue;
        swap(a[x][y],a[tx][ty]);
        if(A_star(k,w)==true)dfs(tx,ty,k+1);
        swap(a[x][y],a[tx][ty]);
    }
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        char st[11];
        int stx,sty;
        for(int i=1;i<=5;i++)
        {
            scanf("%s",st+1);
            for(int j=1;j<=5;j++)
            {
                if(st[j]==*)
                {
                    a[i][j]=2;
                    stx=i,sty=j;
                }
                else a[i][j]=st[j]-0;
            }
        }
        bk=false;
        for(w=1;w<=15;w++)//枚举15步
        {
            dfs(stx,sty,0);
            if(bk)
            {
                printf("%d\n",w);
                break;
            }
        }
        if(bk==false) printf("-1\n");
    }
    return 0;
}

by_lmy

 

以上是关于BZOJ1085: [SCOI2005]骑士精神的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1085 [SCOI2005]骑士精神

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

bzoj1085: [SCOI2005]骑士精神(a*)

BZOJ 1085 [SCOI2005]骑士精神

BZOJ1085: [SCOI2005]骑士精神

[BZOJ]1085 骑士精神(SCOI2005)