zoukankan      html  css  js  c++  java
  • sss

    <更新提示>

    <第一次更新>


    <正文>

    骑士精神(SCOI2005)

    Description

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

    给定一个初始的棋盘,怎样才能经过移动变成如下目标棋盘:

    enter image description here

    为了体现出骑士精神,他们必须以最少的步 数完成任务。

    Input Format

    第一行有一个正整数T(T<=10),表示一共有N组数据。接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑士。*表示空位。两组数据之间没有空行。

    Output Format

    对于每组数据都输出一行。如果能在15步以内(包括15步)到达目标状态,则输出步数,否则输出-1。

    Sample Input

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

    Sample Output

    7
    -1
    

    解析

    骑士的移动方式就是中国象棋中马的移动方式,可以使用方位数组处理,我们不难到这样一个简单的(dfs)算法:搜索尝试对每一头马进行合法的移动,并直接对目标状态进行匹配。

    由于马的数量较多,显然有很多移动是不合法的。每一次合法的移动只可能与唯一的空格交换位置,所以我们改变搜索策略,枚举空格的移动。

    题目中明显给出了步数不大于十五的限制,所以我们不妨使用迭代加深的(dfs)算法。但是本题使用该算法仍然会超时,我们需要改进为(IDA^*)算法,可以如下简单地设置估价函数:

    [f(s)=sum_{s_{i,j} !=goal_{i,j}}1 ]

    即:当前状态与目标状态存在差异的位置个数,可以保证实际步数大于等于预估步数。

    (Code:)

    #include<bits/stdc++.h>
    using namespace std;
    #define mset(name,val) memset(name,val,sizeof name)
    #define filein(str) freopen(str".in","r",stdin)
    #define fileout(str) freopen(str".out","w",stdout)
    const int T=15,INF=0x3f3f3f3f;
    const int dx[]={1,-1,2,-2,1,-1,2,-2},dy[]={2,2,1,1,-2,-2,-1,-1};
    const int goal[7][7]=
    {
        {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}
    };
    int Map[10][10],beginx,beginy,ans=INF,Maxdep;
    inline void input(void)
    {
    	for(int i=1;i<=5;i++)
    	{
    		for(int j=1;j<=5;j++)
    		{
    			char c=' ';
    			while(isspace(c))c=getchar();
    			if(c=='*')Map[i][j]=2,beginx=i,beginy=j;
    			else Map[i][j]=c-'0';
    		}
    	}
    }
    inline int fspend(void)
    {
    	int res=0;
    	for(int i=1;i<=5;i++)
    		for(int j=1;j<=5;j++)
    			if(Map[i][j]!=goal[i][j])
    				res++;
    	return res;
    }
    inline bool dfs(int x,int y,int dep)
    {
    	if(dep==Maxdep)
    	{
    		if(!fspend())ans=dep;
    		return true;
    	}
    	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(Map[x][y],Map[tx][ty]);
    		if(fspend()+dep<=Maxdep)
    			if(dfs(tx,ty,dep+1))return true; 
    		swap(Map[tx][ty],Map[x][y]);
    	}
    	return false;
    }
    int main(void)
    {
    	int T;
    	scanf("%d",&T);
    	while(T--)
    	{
    		input();
    		ans=0;
    		for(Maxdep=1;Maxdep<=15;Maxdep++)
    		{
    			if(dfs(beginx,beginy,0))
    			{
    				printf("%d
    ",ans);
    				break;
    			}
    		}
    		if(!ans)printf("-1
    ");
    	}
    	return 0;
    }
    

    <后记>

  • 相关阅读:
    zoj1942Frogger
    阿里云api调用做简单的cmdb
    约瑟夫环
    Bag标签之中的一个行代码实行中文分词实例3
    用lua扩展你的Nginx(整理)
    Single Number III
    TCP/IP ---分层
    TCP/IP --概述
    adb命令学习
    How to set Selenium Python WebDriver default timeout?
  • 原文地址:https://www.cnblogs.com/Parsnip/p/10610681.html
Copyright © 2011-2022 走看看