链接:https://ac.nowcoder.com/acm/problem/20247
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

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

输入描述:

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

输出描述:

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

输入

复制

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

输出

复制

7
-1

题意:

有一个5*5的棋盘,上面放了24个骑士棋子,和一个空位,每个棋子可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的空位
题目给了一个目标状态,问现在的状态转移到目标状态最少步数是多少,如果最少步数超过15则输出-1

思路:

模拟了第一个样例发现,棋盘中有7个与目标状态不同的骑士,而最少步数为7,也就是说最少步数最少为初始状态中有多少与标准不同的骑士的个数,这样刚好不会浪费格子,
所以枚举最少步数,从空格开始搜索,每次搜索预估代价,当前局面最小移动步数=现在有多少与标准不同的骑士的个数,
步数+预估代价>限制时(到14步时可能会有2个棋子不同但只要一步就能纠正这2个棋子,也就是步数+预估代价==16时是最大可接受范围,所以限制要设为大于等于16的数)或步数大于等于最小可行步数时返回,如果现在局面和标准相同则记录答案(只有步数小于最小可行步数时才会更新答案),
如果搜索越界或现在的操作和上一个操作互逆(如果当前操作和上一个操作互逆却继续搜索那不就返回去了吗)则跳过,
否则交换搜索的棋子和当前棋子并搜索交换棋子的那个位置,且回溯时还原局面

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int amn=10,inf=0x3f3f3f3f;
 4 int a[amn][amn],
 5 mp[amn][amn]={
 6     {1,1,1,1,1},
 7     {0,1,1,1,1},
 8     {0,0,2,1,1},
 9     {0,0,0,0,1},
10     {0,0,0,0,0}
11 },                          ///0^1=1,1^1=0,2^1=3,3^1=2,4^1=5,5^1=4...
12 dt[10][3]={                 ///方向储存时互逆操作相邻,这样就可以通过i^1,判断上一个操作是否和当前操作互逆
13     {-2,-1},{2,1},
14     {-1,-2},{1,2},
15     {1,-2},{-1,2},
16     {2,-1},{-2,1}
17 };
18 int ans,lim;
19 int hst(){          ///预估代价,最小移动步数=现在有多少与标准不同的骑士的个数
20     int h=0;
21     for(int i=0;i<5;i++)
22         for(int j=0;j<5;j++)
23             h+=(a[i][j]!=mp[i][j]);       ///判断现在有多少与标准不同的骑士
24     return h;
25 }
26 void dfs(int x,int y,int step,int last){
27     int h=hst();
28     if(step+h>lim||step>=ans)return;      ///步数+预估代价>限制时(到14步时可能会有2个棋子不同但只要一步就能纠正这2个棋子,也就是步数+预估代价==16时是最大可接受范围,所以限制要设为大于等于16的数)或步数大于等于最小可行步数时返回
29     if(h==0){           ///如果现在局面和标准相同则记录答案(只有步数小于最小可行步数时才会更新答案)
30         ans=step;
31         return ;
32     }
33     for(int i=0;i<8;i++){
34         int dx=x+dt[i][0],dy=y+dt[i][1];
35         if(dx<0||dx>4||dy<0||dy>4||(i^1)==last)continue;    ///如果搜索越界或现在的操作和上一个操作互逆(如果当前操作和上一个操作互逆却继续搜索那不就返回去了吗)则跳过
36             swap(a[dx][dy],a[x][y]);        ///交换
37             dfs(dx,dy,step+1,i);
38             swap(a[dx][dy],a[x][y]);        ///回溯时还原局面
39     }
40 }
41 int main(){
42     int T,stx,sty;
43     char in;
44     scanf("%d",&T);
45     getchar();
46     while(T--){
47         for(int i=0;i<5;i++){
48             for(int j=0;j<5;j++){
49                 scanf("%c",&in);
50                 if(in=='1')
51                     a[i][j]=1;
52                 else if(in=='0')
53                     a[i][j]=0;
54                 else
55                     a[i][j]=2,stx=i,sty=j;
56             }
57             getchar();
58         }
59         ans=inf;
60         int h=hst();
61         for(int i=h;i<=16;i++){             ///枚举限制,最小限制从现在有多少与标准不同的骑士的个数开始,到一个大于等于16的数(太大了会超时),到14步时可能会有2个棋子不同但只要一步就能纠正这2个棋子,也就是步数+预估代价==16时是最大可接受范围,所以限制要设为大于等于16的数
62             lim=i;
63             dfs(stx,sty,0,inf);
64         }
65         printf("%d\n",ans>15?-1:ans);
66     }
67 }
68 /**
69 有一个5*5的棋盘,上面放了24个骑士棋子,和一个空位,每个棋子可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的空位
70 题目给了一个目标状态,问现在的状态转移到目标状态最少步数是多少,如果最少步数超过15则输出-1
71 模拟了第一个样例发现,棋盘中有7个与目标状态不同的骑士,而最少步数为7,也就是说最少步数最少为初始状态中有多少与标准不同的骑士的个数,这样刚好不会浪费格子,
72 所以枚举最少步数,从空格开始搜索,每次搜索预估代价,当前局面最小移动步数=现在有多少与标准不同的骑士的个数,
73 步数-1+预估代价>限制时(到14步时可能会有2个棋子不同但只要一步就能纠正这2个棋子,也就是步数+预估代价==16时是最大可接受范围,所以限制要设为大于等于16的数)或步数大于等于最小可行步数时返回,如果现在局面和标准相同则记录答案(只有步数小于最小可行步数时才会更新答案),
74 如果搜索越界或现在的操作和上一个操作互逆(如果当前操作和上一个操作互逆却继续搜索那不就返回去了吗)则跳过,
75 否则交换搜索的棋子和当前棋子并搜索交换棋子的那个位置,且回溯时还原局面
76 **/

转载于:https://www.cnblogs.com/Railgun000/p/11394778.html

[A*,启发式搜索] [SCOI2005] 骑士精神相关推荐

  1. BZOJ 1085 [SCOI2005]骑士精神 【A*启发式搜索】

    1085: [SCOI2005]骑士精神 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 2838  Solved: 1663 [Submit][St ...

  2. 洛谷 P2324 [SCOI2005]骑士精神 解题报告

    P2324 [SCOI2005]骑士精神 题目描述 输入输出格式 输入格式: 第一行有一个正整数T(T<=10),表示一共有N组数据.接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑士,* ...

  3. bzoj 1085: [SCOI2005]骑士精神(IDA*)

    1085: [SCOI2005]骑士精神 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 2296  Solved: 1328 [Submit][St ...

  4. bzoj1085: [SCOI2005]骑士精神(a*)

    1085: [SCOI2005]骑士精神 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 2555  Solved: 1472 [Submit][St ...

  5. [启发式搜索/A*] [SCOI2005]骑士精神题解

    洛谷-骑士精神 启发式搜索-A* 估价函数 对于当前状态,我们可以将其与目标状态对比,得到一个预估的代价,即最少(不一定满足题意)的代价,得到这个代价的函数叫做估价函数 对于一个最短路问题来说,我们可 ...

  6. BZOJ1085 [SCOI2005] 骑士精神

    [问题描述] 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位.在任何时候一个骑士都能按照骑 士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相 ...

  7. 【题解】P2324[SCOI2005] 骑士精神

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

  8. 1085: [SCOI2005]骑士精神

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

  9. [SCOI2005]骑士精神(C++,启发式搜索)

    题目描述 输入格式 第一行有一个正整数 T T T( T ≤ 10 T \le 10 T≤10),表示一共有 T T T 组数据. 接下来有 T T T 个 5 × 5 5 \times 5 5×5 ...

最新文章

  1. java冒泡排序函数验证_java冒泡排序-选择排序-插入排序-使用API中文文档直接调用函数...
  2. 河南省2013年对口高考 计算机类专业课试题卷答案,河南省对口高考计算机专业课模拟试卷3...
  3. 找不到jar包的解决方法
  4. linux 命令 单词,linux中常用的命令相对应的单词
  5. mmap和munmap对文件进行操作(读写等)
  6. android 背景切换动画效果代码,在Android应用中以模糊效果设置背景图片
  7. 身上的WZSZF01重担开始减轻
  8. 微软web服务器组件,iis8.0安装包微软Web服务器组件 官方版
  9. c#对数据库访问完应关闭连接
  10. mysql show 翻页_mysql show操作
  11. 《卷积神经网络》学习笔记
  12. Django笔记8(模板引擎)
  13. (转)C# System.Diagnostics.Process.Start使用
  14. 永磁电机MTPA控制
  15. wifi信号衰减与距离关系_wifi无线信号传输衰减间隔核算公式
  16. 【Vue】基于Element-UI的文件上传与下载
  17. 智能窗帘电机究竟有何亮点?智汀小米有何优势?
  18. 【JAVA百炼成仙】筑基篇——JAVA筑基
  19. import win32api, sys, os ImportError: DLL load failed: The specified module could not be found.
  20. Uniapp中onShow()的应用

热门文章

  1. 数据库mysql命令
  2. Jsp+mysql在线考试系统论文
  3. Java小白自学7:选择结构练习题
  4. Oracle Flashback 知行合一
  5. 清北 计算机硕士 薪资,行业薪资分析|清北毕业生偏爱不同,这个行业薪资平均最高!...
  6. 应用层: HTTP 与 HTTPS协议
  7. 应用楼宇自控系统降低建筑物设备成本
  8. delphi bde mysql_Delphi- 连接MySQL数据库BDE
  9. GO语言实现P2P网络-客户端实现并且运行和测试
  10. java 调用oracle视图,Oracle视图的使用