bzoj 1085骑士精神

bzoj 1085骑士精神

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

输入:

2
10110
01*11
10111
01001
00000
01011
110*1
01110
01010
00100

输出:

7
-1

思路

A*算法

题目链接

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;

char mp[5][6];

int init[5][5]= {1,1,1,1,1,
                 0,1,1,1,1,
                 0,0,2,1,1,
                 0,0,0,0,1,
                 0,0,0,0,0
                };
int aim[5][5];
int dirX[] = {1,1,-1,-1,2,2,-2,-2};
int dirY[] = {2,-2,2,-2,1,-1,1,-1};

int flag = 0,ans = 0;

int cal()  //估计接下来需要多少步
{
    int ans = 0;
    for(int i=0; i<5; i++)
        for(int j=0; j<5; j++)
            if(init[i][j]!=aim[i][j])
                ans++;
    return ans;
}

void A_Star(int x,int y,int deep,int limit) 
{
    if(deep==limit)
    {
        if(!cal())
            ans = deep;
        return ;
    }
    if(flag)
        return ;
    for(int i=0; i<8; i++)
    {
        int xx = x+dirX[i],yy = y+dirY[i];
        if(xx<0||yy<0||xx>4||yy>4)continue;
        swap(init[x][y],init[xx][yy]);
        int G = cal();
        if(G==0){flag = 1;}
        if(G+deep <= limit+1)A_Star(xx,yy,deep+1,limit);
        swap(init[x][y],init[xx][yy]);
    }
}

void solve()
{
    flag = 0;
    for(int i=0; i<5; i++)
        scanf("%s",mp[i]);
    int x,y;
    for(int i=0; i<5; i++)
        for(int j=0; j<5; j++)
        {
            if(mp[i][j]=='0')aim[i][j]=0;
            if(mp[i][j]=='1')aim[i][j]=1;
            if(mp[i][j]=='*')aim[i][j]=2,x=i,y=j;
        }
    for(int i=0; i<=15; i++)
    {
        if(!flag){
            A_Star(2,2,0,i);
            if(flag)printf("%d\n",ans);
        }
    }
    if(flag==0)printf("%d\n",-1);
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
        solve();
    return 0;
}
posted @ 2019-06-12 15:22  xcantaloupe  阅读(167)  评论(0编辑  收藏  举报