链接: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. Gradle的依赖方式——Lombok在Gradle中的正确配置姿势

    写过java的都知道,lombok几乎在项目中处于不可或缺的一部分,但是lombok在Gradle的项目中配置并非人人都知道. 很多人在项目依赖中直接这样写 1 compile "org.p ...

  2. Animate.css动画库,简单的使用,以及源码剖析

    animate.css是什么?能做些什么? animate.css是一个css动画库,使用它可以很方便的快捷的实现,我们想要的动画效果,而省去了操作js的麻烦.同时呢,它也是一个开源的库,在GitHu ...

  3. Leetcode 24题 两两交换链表中的节点(Swap Nodes in Pairs))Java语言求解

    题目描述: 给定一个链表,两两交换其中相邻的节点,并返回交换后的链表. 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换. 示例: 给定 1->2->3->4,你应该返回 ...

  4. C++扬帆远航——1

    问题及代码: /* * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:test.cpp * 作者:常轩 * 完成日期:2 ...

  5. Redis(3)——分布式锁深入探究

    一.分布式锁简介 锁 是一种用来解决多个执行线程 访问共享资源 错误或数据不一致问题的工具. 如果 把一台服务器比作一个房子,那么 线程就好比里面的住户,当他们想要共同访问一个共享资源,例如厕所的时候 ...

  6. python 读取 execl 文件 之 xlrd 模块

    1. 安装 xlrd模块 pip install xlrd 2. 读取文件内容 #!/usr/bin/env python3 import xlrd name = r"E:\excel\yo ...

  7. mysql中用SQL增加、删除字段,修改字段名

    CREATE TABLE `tuser` ( `id` int(11) NOT NULL, `name` varchar(32) DEFAULT NULL, PRIMARY KEY (`id`) ) ...

  8. 前端每日实战:62# 视频演示如何用纯 CSS 创作一只蒸锅

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/YvOzNy 可交互视频 此视频是可 ...

  9. 前端面试题(HTML、CSS部分)

    HTML.CSS部分: 一.html5有哪些新特性.移除了那些元素?如何处理HTML5新标签的浏览器兼容问题?如何区分 HTML 和 HTML5?   新特性: HTML5 现在已经不是 SGML 的 ...

  10. 基于sklearn的metrics库的常用有监督模型评估指标学习

    一.分类评估指标 准确率(最直白的指标)缺点:受采样影响极大,比如100个样本中有99个为正例,所以即使模型很无脑地预测全部样本为正例,依然有99%的正确率适用范围:二分类(准确率):二分类.多分类( ...