POJ 1915 Knight Moves
POJ 1915 Knight Moves
| Time Limit: 1000MS | Memory Limit: 30000K | |
| Total Submissions: 29912 | Accepted: 14058 |
Description
Mr Somurolov, fabulous chess-gamer indeed, asserts that no one else
but him can move knights from one position to another so fast. Can you
beat him?
The Problem
Your task is to write a program to calculate the minimum number of
moves needed for a knight to reach one point from another, so that you
have the chance to be faster than Somurolov.
For people not familiar with chess, the possible knight moves are shown in Figure 1.
Input
Next follow n scenarios. Each scenario consists of three lines
containing integer numbers. The first line specifies the length l of a
side of the chess board (4 <= l <= 300). The entire board has size
l * l. The second and third line contain pair of integers {0, ...,
l-1}*{0, ..., l-1} specifying the starting and ending position of the
knight on the board. The integers are separated by a single blank. You
can assume that the positions are valid positions on the chess board of
that scenario.
Output
each scenario of the input you have to calculate the minimal amount of
knight moves which are necessary to move from the starting point to the
ending point. If starting point and ending point are equal,distance is
zero. The distance must be written on a single line.
Sample Input
3
8
0 0
7 0
100
0 0
30 50
10
1 1
1 1
Sample Output
5
28
0
Source
TUD Programming Contest 2001, Darmstadt, Germany
这题算是比较简单的BFS了,但数据较大,普通的BFS会超时,但用双向BFS就没有这个问题。
双向BFS
双向BFS的原理是起点和终点同时扩展节点,当遇到相同的节点时,记录答案退出。双向BFS减少了节点的扩展,效率比普通的BFS高出几倍,且内存开销小,是NOIP必备的技能。
code
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std; int read()
{
int x=0,f=1;char c=getchar();
while (c<'0' || c>'9'){if (c=='-')f=-1;c=getchar();}
while (c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
return x*f;
} const int MAXN=310;
const int dx[]={0,1,1,-1,-1,2,2,-2,-2};
const int dy[]={0,2,-2,2,-2,1,-1,1,-1};
int n,ans;
bool flag; struct dot
{
int x,y,step;
void in()
{
x=read();y=read();
step=0;
} bool operator == (struct dot tmp)
{
if (x==tmp.x && y==tmp.y)return true;
return false;
}
}Start,End;
int step[MAXN][MAXN];
bool vis[2][MAXN][MAXN];
queue<dot> Q[2]; bool ok(int x,int y)
{
if (x<0 || x>=n)return false;
if (y<0 || y>=n)return false;
return true;
} void get_next(int z)
{
struct dot top,tmp;
top=Q[z].front();Q[z].pop();
for (int i=1;i<=8;i++)
{
tmp.step=top.step+1;
tmp.x=top.x+dx[i];
tmp.y=top.y+dy[i];
if (!ok(tmp.x,tmp.y))continue;
if (vis[1-z][tmp.x][tmp.y])
{
ans=tmp.step+step[tmp.x][tmp.y];
flag=true;
return ;
}
if (!vis[z][tmp.x][tmp.y])
{
vis[z][tmp.x][tmp.y]=true;
Q[z].push(tmp);
step[tmp.x][tmp.y]=tmp.step;
}
}
} void bfs()
{
while (!Q[0].empty())Q[0].pop();
while (!Q[1].empty())Q[1].pop();
Q[0].push(Start);Q[1].push(End);
while (!Q[0].empty()||!Q[1].empty())
{
if (Q[0].front()==End)
{
ans=Q[0].front().step;
return ;
}
if (!Q[0].empty()&&Q[0].size()<Q[1].size())get_next(0);
else get_next(1);
if (flag)return ;
}
} int main()
{
int cas;cas=read();
while (cas--)
{
flag=0;
memset(step,0,sizeof(step));
memset(vis,0,sizeof(vis));
n=read();
Start.in();End.in();
vis[0][Start.x][Start.y]=1;
vis[1][End.x][End.y]=1;
bfs();
printf("%d\n",ans);
}
return 0;
}
双向BFS的优化
双向BFS效率是惊人的如果运用的好,效率将会更高
让我们来分析一下,当出现一边节点特别多时,扩展节点多的一边会使节点数成指数倍增长,最终导致效率退化到单向BFS,所以我的程序便用了一个if语句,使两个BFS中的节点尽量平衡。
PS:其实这题并不需要这样判断,数据规模和节点的扩展都使得两边会差不多平衡。但这也不失是一种好的优化技巧。
点个赞吧
POJ 1915 Knight Moves的更多相关文章
- OpenJudge/Poj 1915 Knight Moves
1.链接地址: http://bailian.openjudge.cn/practice/1915 http://poj.org/problem?id=1915 2.题目: 总Time Limit: ...
- POJ 1915 Knight Moves(BFS+STL)
Knight Moves Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 20913 Accepted: 9702 ...
- POJ 2243 Knight Moves(BFS)
POJ 2243 Knight Moves A friend of you is doing research on the Traveling Knight Problem (TKP) where ...
- POJ 2243 Knight Moves
Knight Moves Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 13222 Accepted: 7418 Des ...
- 【POJ 2243】Knight Moves
题 Description A friend of you is doing research on the Traveling Knight Problem (TKP) where you are ...
- POJ Knight Moves 2243 x
Knight Moves Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 13974 Accepted: 7797 Des ...
- POJ---2243 Knight Moves 使用A*算法的广度优先搜索
题目链接:http://poj.org/problem?id=2243 启发式搜索:启发式搜索就是在状态空间中的搜索对每一个搜索的位置进行评估,得到最好的位置,再从这个位置进行搜索直到目标.这样可以省 ...
- poj2243 Knight Moves(BFS)
题目链接 http://poj.org/problem?id=2243 题意 输入8*8国际象棋棋盘上的两颗棋子(a~h表示列,1~8表示行),求马从一颗棋子跳到另一颗棋子需要的最短路径. 思路 使用 ...
- POJ2243 Knight Moves —— A*算法
题目链接:http://poj.org/problem?id=2243 Knight Moves Time Limit: 1000MS Memory Limit: 65536K Total Sub ...
随机推荐
- 目标检测 IOU(交并比) 理解笔记
交并比(Intersection-over-Union,IoU): 目标检测中使用的一个概念 是产生的候选框(candidate bound)与原标记框(ground truth bound)的交叠率 ...
- [开源]基于Log4Net简单实现KafkaAppender
背景 基于之前基于Log4Net本地日志服务简单实现 实现本地日志服务,但是随着项目开发演进,本地日志服务满足不了需求,譬如在预发布环境或者生产环境,不可能让开发人员登录查看本地日志文件分析. Kaf ...
- Python:黑板课爬虫闯关第三关
第三关开始才算是进入正题了. 输入网址 http://www.heibanke.com/lesson/crawler_ex02/,直接跳转到了 http://www.heibanke.com/acco ...
- 一个多阶段库存订货问题的 +Leapms 求解要点
一个多阶段库存订货问题的 +Leapms 求解要点 问题来自微信公众号“运筹分享交流”——“互助·运筹擂台3 多阶段库存订货问题”. 数学概念模型 求解结果 +Leapms>mip relexe ...
- js数组去重排序(封装方法)
<script type="text/javascript"> // arr代表数组,index代表下标 function lihua(arr, index){ arr ...
- Thread之十:停止线程方法汇总
在上篇文章<多线程的使用——Thread类和Runnable接口>中提到中断线程的问题.在JAVA中,曾经使用stop方法来停止线程,然而,该方法具有固有的不安全性,因而已经被抛弃(Dep ...
- .Net Framework项目引用.NetStandard标准库出现版本冲突解决办法
今天在工作中出现一个引用问题,害我找问题找了很久.起因是在一个Winform项目下需要引用一个.NetStandard标准库,标准库引用了System.ComponentModel.Annotatio ...
- 点击菜单选项,右侧主体区新增子界面(Tab)的实现
今天是2019年小年后一天,还有三天回家过年. 今天记录一下一种前端页面的效果的实现,这种效果很常见,一般用于网站后台系统的前端页面.一般后台系统会分为顶部导航栏,左边的菜单栏和右边的主体区.有一种效 ...
- 表单数据验证方法(一)—— 使用validate.js实现表单数据验证
摘要:使用validate.js在前端实现表单数据提交前的验证 好久没写博客了,真的是罪过,以后不能这样了,只学习不思考,学的都是白搭,希望在博客园能记录下自己学习的点滴,虽然记录的都是些浅显的技术, ...
- phpcms V9 二次开发------(获取点击数详解)
关于phpcms V9的点击数的使用应该有不少数是直接调用网上搜索到的代码,但是对于一些想要深入研究开发的人来说,看到网上的代码后更是不解,本人这几天看了看,了解了一些东西,在这里写出来分享一下,首先 ...
