• 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*算法,也就是迭代深搜。我们考虑每一步,如果当前状态中某一个位置的棋子与目标状态不同,则至少需要一步才能走到。因此我们可以从小到大深度,估计步数超出范围的则不搜索,在范围内如果找到对应解则必定为最优解。在15步内没有走到则输出-1。具体实现可以看代码。

    代码

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<cmath>
     7 using namespace std;
     8 int a[5][5];
     9 int ans[5][5]={{1,1,1,1,1},
    10                {0,1,1,1,1},
    11                {0,0,-1,1,1},
    12                {0,0,0,0,1},
    13                {0,0,0,0,0}};
    14 int t,an;
    15 int dx[8]={1,1,-1,-1,2,2,-2,-2};
    16 int dy[8]={2,-2,2,-2,1,-1,1,-1};
    17 char ch[10];
    18 bool can=false;
    19 bool che(){
    20     int i,j;
    21     for(i=0;i<5;++i){
    22         for(j=0;j<5;++j){
    23             if(a[i][j]!=ans[i][j])  return false;
    24         }
    25     }
    26     return true;
    27 }
    28 bool val(int now){
    29     int i,j,bu=0;
    30     for(i=0;i<5;++i){
    31         for(j=0;j<5;++j){
    32             if(a[i][j]!=ans[i][j]){
    33                 bu++;if(bu+now>an)  return false;
    34             }
    35         }
    36     }
    37     return true;
    38 }
    39 void dfs(int s,int x,int y){
    40     if(s==an){
    41         if(che()){
    42             can=true;
    43         }
    44         return ;
    45     }
    46     if(can==true)  return ;
    47     int i,j;
    48     for(i=0;i<8;++i){
    49         int nx=x+dx[i],ny=y+dy[i];
    50         if(nx<0 || nx>=5 || ny<0 || ny>=5)  continue ;
    51         swap(a[x][y],a[nx][ny]);
    52         if(val(s))  dfs(s+1,nx,ny);
    53         swap(a[x][y],a[nx][ny]);
    54     }
    55 }
    56 int main(){
    57     scanf("%d",&t);
    58     int i,j;
    59     while(t--){
    60         memset(a,0,sizeof(a));
    61         int x,y;
    62         for(i=0;i<5;++i){
    63             scanf("%s",ch);
    64             for(j=0;j<5;++j){
    65                 if(ch[j]=='*'){
    66                     a[i][j]=-1;x=i;y=j;
    67                 }
    68                 else  a[i][j]=ch[j]-'0';
    69             }
    70         }
    71         for(an=1;an<=15;++an){
    72             dfs(0,x,y);
    73             if(can){
    74                 printf("%d
    ",an);break ;
    75             }
    76         }
    77         if(!can)  printf("-1
    ");
    78         else  can=false; 
    79     }
    80     return 0;
    81 }
  • 相关阅读:
    Java Math 取整的方式
    Java final 关键词修饰类、方法、变量
    Android Activity 开发常用技巧整理
    Java override 和 overload 的区别
    Android TextView 常用技巧
    Android Adb 常用命令
    Android 实现应用升级方案(暨第三方自动升级服务无法使用后的解决方案)
    Git 常用命令
    Android 常见Crash Log汇总
    Java Annotation 总结
  • 原文地址:https://www.cnblogs.com/lazytear/p/8999504.html
Copyright © 2020-2023  润新知