zoukankan      html  css  js  c++  java
  • 2449 骑士精神

    2449 骑士精神

     

    2005年省队选拔赛四川

     时间限制: 1 s
     空间限制: 128000 KB
     题目等级 : 大师 Master
     
     
     
    题目描述 Description

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

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

                             

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

    输入描述 Input Description

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

    输出描述 Output Description

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

    样例输入 Sample Input
    2
    10110
    01*11
    10111
    01001
    00000
    01011
    110*1
    01110
    01010
    00100
    样例输出 Sample Output

    7

    -1

    数据范围及提示 Data Size & Hint

    见题面

    分类标签 Tags 点此展开 

     
     
    解题思路:骑士的跳动实质上是空格的跳动,搜索同时判断是否与目标状态一致,记录一下步数。
     
    IDA*
    时间:玄学
    #include<iostream>
    using namespace std;
    const char goal[5][6]={{"11111"},{"01111"},{"00*11"},{"00001"},{"00000"}};
    const int dx[]={1,2,2,1,-1,-2,-2,-1};
    const int dy[]={2,1,-1,-2,-2,-1,1,2};
    char s[5][6];int T,ans;bool flag;
    inline int deal(){//估价函数(A*的标志) 
        int res=0;
        for(int i=0;i<5;i++)
            for(int j=0;j<5;j++)
                if(s[i][j]!=goal[i][j]) res++;
        return res;
    }
    void dfs(int now,int x,int y,int limit){
        int c=deal();
        if(now==limit){if(!c) ans=limit,flag=1;return ;}//同层的ans是一样的 
        if(now-1+c>limit) return ;//c个不同的至少需要c-1操作,超过限制,剪枝 
        for(int i=0;i<8;i++){
            int nx=x+dx[i],ny=y+dy[i];
            if(nx>=0&&nx<5&&ny>=0&&ny<5){
                swap(s[x][y],s[nx][ny]);
                if(flag) return ;//已有答案,迅速跳出 
                dfs(now+1,nx,ny,limit);
                swap(s[x][y],s[nx][ny]);
            }
        }
    }
    int main(){
        cin>>T;
        while(T--){
            int x,y;
            ans=16;
            for(int i=0;i<5;i++)
                for(int j=0;j<5;j++){
                    cin>>s[i][j];
                    if(s[i][j]=='*') x=i,y=j;//空格点 
                }
            for(int k=0;k<=15;k++){//枚举限制层数 
                flag=0;ans=16;
                dfs(0,x,y,k);
                if(ans==k)break;//前面有答案,后面就不更新了 
            }
            cout<<(ans==16?-1:ans)<<endl;//判一下是否超过15步 
        }
        return 0;
    }

    A*算法

    时间:玄学

    #include<iostream>//朴素A*,没有上面的剪枝部分,当然跑的不如上面的快,但是便于理解 
    #include<cstring>
    using namespace std;
    const char goal[5][6]={{"11111"},{"01111"},{"00*11"},{"00001"},{"00000"}};
    const int dx[]={1,2,2,1,-1,-2,-2,-1};
    const int dy[]={2,1,-1,-2,-2,-1,1,2};
    char s[5][6];int T,ans;
    inline bool same(){
        return !memcmp(s,goal,sizeof s); 
    }
    inline int deal(int dep){
        for(int i=0;i<5;i++)
            for(int j=0;j<5;j++)
                if(s[i][j]!=goal[i][j]) dep++;
        return dep;
    }
    void dfs(int dep){
        if(same()) ans=min(ans,dep-1);
        if(dep>=ans) return ;
        int x,y;
        for(int i=0;i<5;i++)
            for(int j=0;j<5;j++)
                if(s[i][j]=='*') x=i,y=j;
        for(int i=0;i<8;i++){
            x+=dx[i];y+=dy[i];
            if(x>=0&&x<5&&y>=0&&y<5){
                swap(s[x][y],s[x-dx[i]][y-dy[i]]);
                if(deal(dep)<=ans) dfs(dep+1);
                swap(s[x][y],s[x-dx[i]][y-dy[i]]);
            }
            x-=dx[i];y-=dy[i];
        }
    }
    int main(){
        cin>>T;
        while(T--){
            ans=16;
            for(int i=0;i<5;i++)
                for(int j=0;j<5;j++)
                    cin>>s[i][j];
            dfs(1);
            cout<<(ans==16?-1:ans)<<endl;
        }
        return 0;
    }
  • 相关阅读:
    ‘Found duplicate PV’ warnings when using LVM with multipath storage in RHEL/CentOS
    如何卸载windows的服务?卸载服务
    富文本wangeditor层级太高覆盖问题
    vue wangeditor
    vue消息提示this.$message方法
    MySQL之查询指定时间的数据
    企业微信第三方应用PC端实现用户点击注册的三种方式
    两款不带广告的輸入法
    jquery、css 的选择器
    广信可视电话设置可安装应用权限
  • 原文地址:https://www.cnblogs.com/shenben/p/5717059.html
Copyright © 2011-2022 走看看