链接: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的数)或步数大于等于最小可行步数时返回,如果现在局面和标准相同则记录答案(只有步数小于最小可行步数时才会更新答案),
如果搜索越界或现在的操作和上一个操作互逆(如果当前操作和上一个操作互逆却继续搜索那不就返回去了吗)则跳过,
否则交换搜索的棋子和当前棋子并搜索交换棋子的那个位置,且回溯时还原局面

 #include<bits/stdc++.h>
using namespace std;
const int amn=,inf=0x3f3f3f3f;
int a[amn][amn],
mp[amn][amn]={
{,,,,},
{,,,,},
{,,,,},
{,,,,},
{,,,,}
}, ///0^1=1,1^1=0,2^1=3,3^1=2,4^1=5,5^1=4...
dt[][]={ ///方向储存时互逆操作相邻,这样就可以通过i^1,判断上一个操作是否和当前操作互逆
{-,-},{,},
{-,-},{,},
{,-},{-,},
{,-},{-,}
};
int ans,lim;
int hst(){ ///预估代价,最小移动步数=现在有多少与标准不同的骑士的个数
int h=;
for(int i=;i<;i++)
for(int j=;j<;j++)
h+=(a[i][j]!=mp[i][j]); ///判断现在有多少与标准不同的骑士
return h;
}
void dfs(int x,int y,int step,int last){
int h=hst();
if(step+h>lim||step>=ans)return; ///步数+预估代价>限制时(到14步时可能会有2个棋子不同但只要一步就能纠正这2个棋子,也就是步数+预估代价==16时是最大可接受范围,所以限制要设为大于等于16的数)或步数大于等于最小可行步数时返回
if(h==){ ///如果现在局面和标准相同则记录答案(只有步数小于最小可行步数时才会更新答案)
ans=step;
return ;
}
for(int i=;i<;i++){
int dx=x+dt[i][],dy=y+dt[i][];
if(dx<||dx>||dy<||dy>||(i^)==last)continue; ///如果搜索越界或现在的操作和上一个操作互逆(如果当前操作和上一个操作互逆却继续搜索那不就返回去了吗)则跳过
swap(a[dx][dy],a[x][y]); ///交换
dfs(dx,dy,step+,i);
swap(a[dx][dy],a[x][y]); ///回溯时还原局面
}
}
int main(){
int T,stx,sty;
char in;
scanf("%d",&T);
getchar();
while(T--){
for(int i=;i<;i++){
for(int j=;j<;j++){
scanf("%c",&in);
if(in=='')
a[i][j]=;
else if(in=='')
a[i][j]=;
else
a[i][j]=,stx=i,sty=j;
}
getchar();
}
ans=inf;
int h=hst();
for(int i=h;i<=;i++){ ///枚举限制,最小限制从现在有多少与标准不同的骑士的个数开始,到一个大于等于16的数(太大了会超时),
到14步时可能会有2个棋子不同但只要一步就能纠正这2个棋子,也就是步数+预估代价==16时是最大可接受范围,所以限制要设为大于等于16的数
lim=i;
dfs(stx,sty,,inf);
}
printf("%d\n",ans>?-:ans);
}
}
/**
有一个5*5的棋盘,上面放了24个骑士棋子,和一个空位,每个棋子可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的空位
题目给了一个目标状态,问现在的状态转移到目标状态最少步数是多少,如果最少步数超过15则输出-1
模拟了第一个样例发现,棋盘中有7个与目标状态不同的骑士,而最少步数为7,也就是说最少步数最少为初始状态中有多少与标准不同的骑士的个数,这样刚好不会浪费格子,
所以枚举最少步数,从空格开始搜索,每次搜索预估代价,当前局面最小移动步数=现在有多少与标准不同的骑士的个数,
步数-1+预估代价>限制时(到14步时可能会有2个棋子不同但只要一步就能纠正这2个棋子,也就是步数+预估代价==16时是最大可接受范围,所以限制要设为大于等于16的数)或步数大于等于最小可行步数时返回,如果现在局面和标准相同则记录答案(只有步数小于最小可行步数时才会更新答案),
如果搜索越界或现在的操作和上一个操作互逆(如果当前操作和上一个操作互逆却继续搜索那不就返回去了吗)则跳过,
否则交换搜索的棋子和当前棋子并搜索交换棋子的那个位置,且回溯时还原局面
**/

[A*,启发式搜索] [SCOI2005] 骑士精神的更多相关文章

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

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

  2. BZOJ1085: [SCOI2005]骑士精神 [迭代加深搜索 IDA*]

    1085: [SCOI2005]骑士精神 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1800  Solved: 984[Submit][Statu ...

  3. 【bzoj1085】[SCOI2005]骑士精神

    1085: [SCOI2005]骑士精神 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1757  Solved: 961[Submit][Statu ...

  4. BZOJ 1085: [SCOI2005]骑士精神( IDDFS + A* )

    一开始写了个 BFS 然后就 T 了... 这道题是迭代加深搜索 + A* -------------------------------------------------------------- ...

  5. BZOJ_1085_[SCOI2005]骑士精神_IDDFS

    BZOJ_1085_[SCOI2005]骑士精神_DFS Description 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位.在任何时候一个骑士都能按照骑 士的走法(它可 ...

  6. [luogu P2324] [SCOI2005]骑士精神

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

  7. 【洛谷】2324:[SCOI2005]骑士精神【IDA*】

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

  8. BZOJ1085 SCOI2005 骑士精神【IDA* 启发式迭代加深】

    BZOJ1085 SCOI2005 骑士精神 Description 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位.在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐 ...

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

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

随机推荐

  1. Oracle中的列转行实现字段拼接用例

    文章目录 Oracle中的列转行实现字段拼接 场景 在SQL使用过程中经常有这种需求:将某列字段拼接成in('XX','XX','XX','XX','XX','XX' ...)做为查询条件. 实现 s ...

  2. 曹工说Spring Boot源码(21)-- 为了让大家理解Spring Aop利器ProxyFactory,我已经拼了

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  3. 攻防世界Mobile6 app1 XCTF详解

    XCTF_app1 先安装看看 点击芝麻开门之后会弹出“年轻人不要耍小聪明噢” 这大概就能看懂是点击之后进行判断,那就直接去看JEB,看看判断条件是什么 V1是输入的字符串,V2获取包信息(百度的), ...

  4. SQL Server 最小日志记录

    SQL Server之所以记录事务日志,首要目的是为了把失败或取消的操作还原到最原始的状态,但是,并不是所有的操作都需要完全记录事务日志,比如,在一个空表上放置排他锁,把大量的数据插入到该空表中.即使 ...

  5. 20170813-CSRF 跨站请求伪造

    CSRF CSRF是Cross Site Request Forgery的缩写,翻译过来就是跨站请求伪造. 跨站:顾名思义,就是从一个网站到另一个网站. 请求:即HTTP请求. 伪造:在这里可以理解为 ...

  6. vue 实现 裁切图片 同时有放大、缩小、旋转功能

    实现效果: 裁切指定区域内的图片 旋转图片 放大图片 输出bolb 格式数据 提供给 formData 对象 效果图 大概原理: 利用h5 FileReader 对象, 获取 <input ty ...

  7. cocoapods相关的知识点

    目录 1.安装和卸载cocoapods 安装 卸载 2.常规问题解决思路 50%报错问题可以通过 pod install或者pod update解决 指定swift编译版本 由于墙的原因,可能会ins ...

  8. vue项目用sha256、md5、base64加密密码

    无论你开发什么样的项目,你可能都会要开发登录.注册.修改密码.忘记密码这些功能,少数项目除外!!要实现这些功能,对于保护用户或者管理员账号密码,这是我们程序员肯定要做的事情.要是用户密码不加密,用明文 ...

  9. EF多租户实例:如何快速实现和同时支持多个DbContext

    前言 上一篇随笔我们谈到了多租户模式,通过多租户模式的演化的例子.大致归纳和总结了几种模式的表现形式. 并且顺带提到了读写分离. 通过好几次的代码调整,使得这个库更加通用.今天我们聊聊怎么通过该类库快 ...

  10. IOS 项目release版本中关闭NSlog的打印

    在-Prefix.pch文件中添加如下代码: #ifdef DEBUG #define NSLog(...) NSLog(__VA_ARGS__) #define debugMethod() NSLo ...