【洛谷2324】[SCOI2005]骑士精神 IDA*
[SCOI2005]骑士精神
描述
在一个\(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
输出样例1:
7
-1
题解
题意:给你一个初始棋盘,要求用最少的步数移动马达到如上图的目标状态(要求棋盘中的马只能走“日”)。
咱们先抛开\(IDA^*\),先如何优化爆搜;
这里的马和象棋里的马走法相同,但题目中要求让马走,但是要是马的话,搜索分支比较多,所以我们要考虑让空格走(很显然吧)。
下面步入正题:
\(IDA^*\)就是带有迭代加深和估价函数优化的搜索。
可能某些人对以上两个名词很陌生,下面一些前置知识可能会带你透彻一下。
前置知识1:迭代加深
定义:
每次限定一个\(maxdep\)最大深度,使搜索树的深度不超过\(maxdep\)。
for(R int maxdep=1;maxdep<=题目中给的最大步数;maxdep++){
dfs(0,maxdep);//0为出入函数中当前步数,maxdep为传入的最大深度。
if(success)break;//如果搜索成功则会在dfs函数中将success赋值为1。
}
使用范围:
1.在有一定的限制条件时使用(例如本题中“如果能在\(15\)步以内(包括\(15\)步)到达目标状态,则输出步数,否则输出\(-1\)。“)。
2.题目中说输出所以解中的任何一组解。
为什么能够降低时间复杂度:
我们可能会在一个没有解(或解很深的地方无限递归然而题目中要求输出任何的一组解),所以我们限制一个深度,让它去遍历更多的分支,去更广泛地求解,(其实和\(BFS\)有异曲同工之妙)。
前置知识2:估价函数
定义:
\(f(n)=g(n)+h(n)\)
其中\(f(n)\)是节点的估价函数,\(g(n)\)是现在的实际步数,\(h(n)\)是对未来步数的最完美估价(“完美”的意思是可能你现实不可能实现,但你还要拿最优的步数去把\(h(n)\)算出来,可能不太好口胡,可以参考下面的实例)。
应用:
void dfs(int dep,int maxdep){
if(evaluate()+dep>maxdep)return;
//evaluate函数为对未来估价的函数,若未来估价加实际步数>迭代加深的深度则return。
if(!evaluate){
success=1;
printf("%d\n",dep);
return;
}
......
}
前置知识3:\(A^*\)和\(IDA^*\)的区别
\(A^*\)是用于对\(BFS\)的优化;
\(IDA^*\)是对结合迭代加深的\(DFS\) 的优化。
本质上只是在\(BFS\)和\(DFS\)上加上了一个估价函数。
何时使用因题而定:
\(A^*\)([SCOI2007]k短路);\(IDA^*\)([SCOI2005]骑士精神和UVA11212 Editing a Book 就是上面的两道题)。
前置知识毕!!!
现在就是要想一个比较好的估价函数(若估价函数不好的话,优化效率就并不高,例如若估价函数一直为0,那就是爆搜)。
我们可以想一下,每次空白格子和黑白棋子交换,最优的情况就是每次都把黑白棋子移动到目标格子。
那么你的估价函数就出来了:
const int goal[7][7]={
{0,0,0,0,0,0},
{0,1,1,1,1,1},
{0,0,1,1,1,1},
{0,0,0,2,1,1},
{0,0,0,0,0,1},
{0,0,0,0,0,0}
};
inline int evaluate(){
R int cnt=0;
for(R int i=1;i<=5;i++)
for(R int j=1;j<=5;j++)
if(mp[i][j]!=goal[i][j])cnt++;
return cnt;
}
下面就是爆搜了:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cctype>
#define ll long long
#define R register
using namespace std;
template<typename T>inline void read(T &a){
char c=getchar();T x=0,f=1;
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
a=f*x;
}
int n,m,t,mp[7][7],stx,sty,success;
char ch;
const int dx[]={0,1,1,-1,-1,2,2,-2,-2};
const int dy[]={0,2,-2,2,-2,1,-1,1,-1};
const int goal[7][7]={
{0,0,0,0,0,0},
{0,1,1,1,1,1},
{0,0,1,1,1,1},
{0,0,0,2,1,1},
{0,0,0,0,0,1},
{0,0,0,0,0,0}
};
inline int evaluate(){
R int cnt=0;
for(R int i=1;i<=5;i++)
for(R int j=1;j<=5;j++)
if(mp[i][j]!=goal[i][j])cnt++;
return cnt;
}
inline int safe(R int x,R int y){
if(x<1||x>5||y<1||y>5)return 0;
return 1;
}
inline void A_star(R int dep,R int x,R int y,R int maxdep){
if(dep==maxdep){
if(!evaluate())success=1;
return;
}
for(R int i=1;i<=8;i++){
R int xx=x+dx[i];
R int yy=y+dy[i];
if(!safe(xx,yy))continue;
swap(mp[x][y],mp[xx][yy]);
int eva=evaluate();
if(eva+dep<=maxdep)
A_star(dep+1,xx,yy,maxdep);
swap(mp[x][y],mp[xx][yy]);//回溯
}
}
int main(){
read(t);
while(t--){
success=0;
for(R int i=1;i<=5;i++){
for(R int j=1;j<=5;j++){
cin>>ch;
if(ch=='*')mp[i][j]=2,stx=i,sty=j;//记录起点即为空白格子
else mp[i][j]=ch-'0';
}
}
if(!evaluate()){printf("0\n");continue;}
for(R int maxdep=1;maxdep<=15;maxdep++){
A_star(0,stx,sty,maxdep);
if(success){printf("%d\n",maxdep);goto ZAGER;}
}
printf("-1\n");
ZAGER:;
}
return 0;
}
【洛谷2324】[SCOI2005]骑士精神 IDA*的更多相关文章
- 洛谷 P2324 [SCOI2005]骑士精神 解题报告
P2324 [SCOI2005]骑士精神 题目描述 输入输出格式 输入格式: 第一行有一个正整数T(T<=10),表示一共有N组数据.接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑士,* ...
- 洛谷P2324 [SCOI2005] 骑士精神
题目 方法很多,最经典的是用搜索的算法,也就是\(IDA*\)算法搜索. \(IDA*\)算法是每次规定一个搜索深度,并在搜索的时候限制该搜索深度,从而达到把深搜的优点和广搜的优点结合起来优化时间的一 ...
- 洛谷 P2324 [SCOI2005]骑士精神
题目描述 输入输出格式 输入格式: 第一行有一个正整数T(T<=10),表示一共有N组数据.接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑士,*表示空位.两组数据之间没有空行. 输出格式 ...
- [BZOJ 1085] [SCOI2005] 骑士精神 [ IDA* 搜索 ]
题目链接 : BZOJ 1085 题目分析 : 本题中可能的状态会有 (2^24) * 25 种状态,需要使用优秀的搜索方式和一些优化技巧. 我使用的是 IDA* 搜索,从小到大枚举步数,每次 DFS ...
- bzoj 1085: [SCOI2005]骑士精神 IDA*
题目链接 给一个图, 目标位置是确定的, 问你能否在15步之内达到目标位置. 因为只有15步, 所以直接ida* #include<bits/stdc++.h> using namespa ...
- bzoj1085 [SCOI2005]骑士精神——IDA*
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1085 搜索,IDA*,估价就是最少需要跳的步数: 代码意外地挺好写的,memcmp 用起来好 ...
- bzoj 1085 [SCOI2005]骑士精神——IDA*
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1085 迭代加深搜索. 估价函数是为了预计步数来剪枝,所以要优于实际步数. 没错,不是为了确定 ...
- 【洛谷】2324:[SCOI2005]骑士精神【IDA*】
P2324 [SCOI2005]骑士精神 题目描述 输入输出格式 输入格式: 第一行有一个正整数T(T<=10),表示一共有N组数据.接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑士,* ...
- BZOJ1085: [SCOI2005]骑士精神 [迭代加深搜索 IDA*]
1085: [SCOI2005]骑士精神 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1800 Solved: 984[Submit][Statu ...
随机推荐
- Spring学习九 Servlet相关
servlet作用: 它驻留在 Web 服务器上,处理新来的请求和输出的响应.它与表示无关,实际上也不它应该与表示有关. 作为一名专业编程人员,您碰到的大多数 Java servlet 都是为响应 W ...
- stdin和STDIN_FILENO的区别
STDIN_FILENO与stdin的区别: STDIN_FILENO: 1).数据类型:int 2).层次:系统级的API,是一个文件句柄,定义在<unistd.h>中. 3).相应的函 ...
- X509 文件扩展名
编码 (也用于扩展名) .DER = 扩展名DER用于二进制DER编码的证书.这些证书也可以用CER或者CRT作为扩展名.比较合适的说法是“我有一个DER编码的证书”,而不是“我有一个DER证书”. ...
- 类型:Jquery;问题:jquery调用后台带参数方法;结果:利用JQuery的$.ajax()可以很方便的调用asp.net的后台方法。
利用JQuery的$.ajax()可以很方便的调用asp.net的后台方法. [WebMethod] 命名空间 1.无参数的方法调用, 注意:1.方法一定要静态方法,而且要有[WebMethod] ...
- VS2008 C++ 项目怎样添加“依赖”、“库目录”和“包含目录”
随笔 - 79, 文章 - 0, 评论 - 7, 引用 - 0 1. 添加编译所需要(依赖)的 lib 文件 [解决方案资源管理器]“项目->属性->配置属性->连接器->输入 ...
- 基于Flask框架的Python web程序的开发实战 <一> 环境搭建
最近在看<Flask Web开发基于Python的Web应用开发实战>Miguel Grinberg著.安道译 这本书,一步步跟着学习Flask框架的应用,这里做一下笔记 电脑只安装一个P ...
- java之控制多幅图片
package xxj.thread0904; import java.awt.Image; import javax.swing.ImageIcon; import javax.swing.JFra ...
- WPA密码攻击宝典
原则:密码以8-10位为主.11位仅限于当地手机号.一般人的多年用数字做密码的习惯和心理,先数 字.再字母,或数字.字母重复几遍,字符几乎全用小写,所以淘汰大写及"~!@#$%^&* ...
- SpringBoot12 QueryDSL02之利用QueryDSL实现多表关联查询
1 业务需求 有的系统业务逻辑比较复杂,存在着多表关联查询的的情况,查询的内容不仅仅是单张表的的内容而是多张表的字段组合而成的,直接使用SplringDataJPA实现是比较复杂的,但是如果使用Que ...
- JAVA语法规则总结
单继承多实现 抽象类 抽象方法 使用关键字:abstract修饰的方法就是抽象方法; 抽象方法的形式:只有方法的声明,没有方法体; 抽象方法一般存在于父类中,相当于强制要求子类必须重写该方法,相当于 ...