1085: [SCOI2005]骑士精神

1085: [SCOI2005]骑士精神

Time Limit: 10 Sec   Memory Limit: 162 MB
Submit: 534   Solved: 280
[ Submit][ Status]

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

这题数据较小,所以可以考虑搜索
这题的估价函数是比较好写的,对于每个格子,如果他与标准格子不同计数器+1,最后计数器-1一定《=实际代价,鉴于这题状态数多,而且只有15层,所以可以用IDA*
下面贴代码
/**************************************************************
    Problem: 1085
    User: SKYDEC
    Language: C++
    Result: Accepted
    Time:1436 ms
    Memory:804 kb
****************************************************************/
 
#include<stdio.h>
using namespace std;
struct chess{
    long h[6][6];
}stdp;
long dx[10]={0,-1,-1,1,1,-2,-2,2,2};
long dy[10]={0,-2,2,-2,2,-1,1,-1,1};
long f(chess a)
{
    long ans=0;
    for(long i=1;i<=5;i++)
    for(long j=1;j<=5;j++)
    if(a.h[i][j]!=stdp.h[i][j])ans++;
    ans--;
    return ans;
}
bool flag=false;
void swap(long &a,long &b)
{
    long t=a;a=b;b=t;
}
void A_star(long x,long y,chess now,long up,long step)
{
    if(flag)return;
    if(step>up)return;
    if(f(now)==-1){flag=true;return;}
    if(f(now)+step>up)return;
    for(long i=1;i<=8;i++)
    if(dx[i]+x>=1&&dx[i]+x<=5&&dy[i]+y>=1&&dy[i]+y<=5)
    {
        swap(now.h[x][y],now.h[x+dx[i]][y+dy[i]]);
        //if(f(now)+step>up)return;
        A_star(x+dx[i],y+dy[i],now,up,step+1);
        swap(now.h[x][y],now.h[x+dx[i]][y+dy[i]]);
    }
}
int main()
{
    for(long i=1;i<=5;i++){stdp.h[1][i]=1;stdp.h[5][i]=0;}
    stdp.h[2][1]=stdp.h[3][1]=stdp.h[3][2]=stdp.h[4][1]=stdp.h[4][2]=stdp.h[4][3]=stdp.h[4][4]=0;
    stdp.h[2][2]=stdp.h[2][3]=stdp.h[2][4]=stdp.h[2][5]=stdp.h[3][4]=stdp.h[3][5]=stdp.h[4][5]=1;stdp.h[3][3]=2;
    long test;scanf("%ld\n",&test);char goe;
    for(long cao=1;cao<=test;cao++)
    {
        chess start;long sx,sy;
        for(long i=1;i<=5;i++)
        {
            for(long j=1;j<=5;j++)
            {
                scanf("%c",&goe);
                if(goe!='*')start.h[i][j]=goe-'0';else{start.h[i][j]=2;sx=i;sy=j;}
            }
            scanf("%c",&goe);
        }
        flag=false;
        if(f(start)==-1)printf("0\n");
        else
        {
            for(long i=1;i<=15;i++)
            if(!flag)
            {
                A_star(sx,sy,start,i,0);
                if(flag)printf("%ld\n",i);
            }
            if(!flag)printf("-1\n");
        }
    }
    //for(;;);
    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值