yzoi2226最小步数的详细解法
Description - 问题描述
在各种棋中,棋子的走法总是一定的,如中国象棋中马走“日”。有一位小学生就想如果马能有两种走法将增加其趣味性,因此,他规定马既能按“日”走,也能如象一样走“田”字。他的同桌平时喜欢下围棋,知道这件事后觉得很有趣,就想试一试,在一个(100*100)的围棋盘上任选两点A、B,A点放上黑子,B点放上白子,代表两匹马。棋子可以按“日”字走,也可以按“田”字走,俩人一个走黑马,一个走白马。谁用最少的步数走到左上角坐标为(1,1)的点时,谁获胜。现在他请你帮忙,给你A、B两点的坐标,想知道两个位置到(1,1)点可能的最少步数。
Input - 输入数据
两行:第一行A点的坐标,第二行B点的坐标,坐标都是不超过100的自然数。
Output - 输出数据
两行,第一行A点走到(1,1)位置的最少步数;第二行是B点走到(1,1)位置的最少步数。
详细解法
读完题目我们可以知道,这里的马可以走“日”字,亦可以走“田”字,那么我们假设该点的坐标为(x,y),那么其可以到达的坐标便有12种情况,分别为:走“日”字:(x-2,y-1),(x-1,y-2),(x-2,y+1),(x-1,y+2),(x+2,y-1),(x+1,y-2),(x+1,y+2),(x+2,y+1);走“田”字:(x-2,y-2),(x-2,y+2),(x+2,y+2),(x+2,y-2)。这样分析下来,我们便可将所有x的增量以及其所对应的y的增量保存到两个数组dx[],dy[]中,每次通过对数组对应元素的选择来完成移动。代码如下:
int dx[]={-,-,-,,,,,,,-,-,-};
int dy[]={-,-,-,-,-,-,,,,,,};
其后,题目要求是分别有两颗棋子进行移动,其最终目的地都是(1,1),那么,我们需要对每个棋子的移动方式进行探讨吗?其实不然,对于每一颗棋子,虽然他们的出发点不同,但其终点都为(1,1)。以是,我们便可看成是有一颗棋子从(1,1)出发,分别移动到(x1,y1),(x2,y2)的步数。这样一来,便可以通过bfs(百度定义:宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。)来完成整个的搜索最少步数的工作了。
既然确定了bfs的算法,那么我们就需要使用队列的结构了,我们可以用STL里的queue来定义一个队列数组,代码如下:
#include<queue>
queue<int>q[];
其中,q[1]存储从(1,1)可到达点的横坐标,q[2]存储从(1,1)可到达点的纵坐标,q[3]则表示到达该点所需要的最短步数。假如你说用不惯STL里的queue,那么我们也可以自己写队列,如下所示:
int que[maxn][]={};
同时也需要定义一个头指针与一个尾指针,其二者的初值都为1,以表示队列为空,代码如下:
int head=,tail=;
其次,为了最后输出的方便,我们还要定义一个s[maxn][maxn]数组来存储到达s[x][y]的最小步数,最后只需要输出s[x1][y1],s[x2][y2]的值即可。同时,也得将s[1][1]赋值为0,其他元素赋值为1,代码如下:
memset(s,-,sizeof(s));
s[][]=;
(接下来,我们全部用自己写的队列,进行操作,使用STL代码将在最后给出)
一开始,我们将初始状态入队,即q[1][1]=1,q[1][2]=1,q[1][3]=0,代码如下:
q[][]=;
q[][]=;
q[][]=;
接着,我们便使用一个循环进行拓展的操作,和1777的倒水一样,循环成立的条件是head<=tail(即队列不为空).然后,对于前面所列出的12种情况,我们每一种都要进行探讨,即使用一个for循环,从0枚举到11.其步骤大致如下:①取队首元素所能到达的位置②判断当前位置是否越界③判断当前位置是否到达过(根据bfs的原理先前到达过的步数一定小于当前的步数,故不需要再继续拓展)④将当前的s[x][y]的值更新,即其值就等于当前q[head][3]+1⑤将新得到的x,y的值入队⑥判断是否已将(x1,y1),(x2,y2)的最少步数都搜索到,即判断s[x1][y1],s[x2][y2]的值是否都>0,是的话就输出后结束程序否则就弹出队首元素(前面只是取出,并没有弹出)并重复①。其代码如下:
while(head<=tail)
{
for(int d=;d<;d++)
{
int x=q[head][]+dx[d]; //取队首元素所能到达横坐标的位置
int y=q[head][]+dy[d]; //取队首元素所能到达纵坐标的位置
if(x>&&y>&&x<=&&y<=) //判断是否在界内
if(s[x][y]==-) //判断是否已经拓展过
{
s[x][y]=q[head][]+; //更新s[x][y]的值
tail++; //将新状态入队
q[tail][]=x;
q[tail][]=y;
q[tail][]=s[x][y];
if(s[x1][y1]>&&s[x2][y2]>) //判断是否达到了目标状态
{
cout<<s[x1][y1]<<endl; //输出
cout<<s[x2][y2]<<endl;
return ;
}
}
}
head++; //弹出队首元素
}
最后,给出OJ上ac的代码,仅供参考:
以下下为自己写的队列:
#include<iostream>
#include<cstring>
using namespace std;
int const maxn=+;
int const area=+;
int dx[]={-,-,-,,,,,,,-,-,-};
int dy[]={-,-,-,-,-,-,,,,,,};
int s[area][area],q[maxn][]={};
int x1,y1,x2,y2;
int head=,tail=;
int main()
{
memset(s,0xff,sizeof(s));
cin>>x1>>y1>>x2>>y2;
q[][]=;
q[][]=;
q[][]=;
while(head<=tail)
{
for(int d=;d<;d++)
{
int x=q[head][]+dx[d]; //取队首元素所能到达横坐标的位置
int y=q[head][]+dy[d]; //取队首元素所能到达纵坐标的位置
if(x>&&y>&&x<=&&y<=) //判断是否在界内
if(s[x][y]==-) //判断是否已经拓展过
{
s[x][y]=q[head][]+; //更新s[x][y]的值
tail++; //将新状态入队
q[tail][]=x;
q[tail][]=y;
q[tail][]=s[x][y];
if(s[x1][y1]>&&s[x2][y2]>) //判断是否达到了目标状态
{
cout<<s[x1][y1]<<endl; //输出
cout<<s[x2][y2]<<endl;
return ;
}
}
}
head++; //弹出队首元素
}
}
以下为直接用STL的队列,其大致入队出队的操作都与前者相似,故不再介绍:
/*
Name: lwq
Copyright:
Author:
Date: 14-12-14 14:17
Description: 2226STL
*/ #include<iostream>
#include<cstring>
#include<queue>
using namespace std;
int const maxn=+;
int const area=+;
int dx[]={-,-,-,,,,,,,-,-,-};
int dy[]={-,-,-,-,-,-,,,,,,};
int s[area][area];
queue<int>q[];
int x1,y1,x2,y2;
int main()
{
memset(s,-,sizeof(s));
cin>>x1>>y1>>x2>>y2;
q[].push();
q[].push();
q[].push();
while((!q[].empty())&&(!q[].empty())&&(!q[].empty()))
{
for(int d=;d<;d++)
{
int x=q[].front()+dx[d];
int y=q[].front()+dy[d];
if(x>&&y>&&x<=&&y<=)
if(s[x][y]==-)
{
s[x][y]=q[].front()+;
q[].push(x);
q[].push(y);
q[].push(s[x][y]);
if(s[x1][y1]>&&s[x2][y2]>)
{
cout<<s[x1][y1]<<endl;
cout<<s[x2][y2]<<endl;
return ;
}
}
}
q[].pop();
q[].pop();
q[].pop();
}
}
最后,欢迎大家的指教。
yzoi2226最小步数的详细解法的更多相关文章
- POJ 1753 Flip Game (高斯消元 枚举自由变元求最小步数)
题目链接 题意:4*4的黑白棋,求把棋全变白或者全变黑的最小步数. 分析:以前用状态压缩做过. 和上题差不多,唯一的不同是这个终态是黑棋或者白棋, 但是只需要把给的初态做不同的两次处理就行了. 感觉现 ...
- One Person Game(扩展欧几里德求最小步数)
One Person Game Time Limit: 2 Seconds Memory Limit: 65536 KB There is an interesting and simple ...
- Algorithm --> 棋盘中求出A到B的最小步数
求出A到B的最小步数 给定象棋盘,以及位置A和B, 求出从A到B的最小步数 代码: #include <cstdio> #include <iostream> #include ...
- 1到n的最小步数
1到n的最小步数 Time Limit: 1 Sec Memory Limit: 128 MB 给你一个数n,让你求从1到n的最小步数是多少. 对于当前的数x有三种操作: 1: x+1 2: x ...
- [leetcode]45. Jump Game II青蛙跳(跳到终点最小步数)
Given an array of non-negative integers, you are initially positioned at the first index of the arra ...
- ny58 最小步数
最少步数 时间限制:3000 ms | 内存限制:65535 KB 难度:4 描述 这有一个迷宫,有0~8行和0~8列: 1,1,1,1,1,1,1,1,1 1,0,0,1,0,0,1,0,1 1 ...
- ZOJ 3593 One Person Game(拓展欧几里得求最小步数)
One Person Game Time Limit: 2 Seconds Memory Limit: 65536 KB There is an interesting and simple ...
- 带你学习BFS最小步数模型
最小步数模型 一.简介 最小步数模型和最短路模型的区别? 最短路模型:某一个点到另一个点的最短距离(坐标与坐标之间) 最小步数模型:不再是点(坐标),而是状态到另一个状态的转变 BFS难点所在(最短路 ...
- yzoi1109&&viojs1042最小步数的一点看法——回文数
Description - 问题描述 有一天,雄霸传授本人风神腿法第一式:捕风捉影..............的步法(弟子一:堂主,你大喘气呀.风:你给我闭嘴.)捕风捉影的关键是换气(换不好就会大喘气 ...
随机推荐
- javad的Collection集合
集合框架:★★★★★,用于存储数据的容器. 特点: 1:对象封装数据,对象多了也需要存储.集合用于存储对象. 2:对象的个数确定可以使用数组,但是不确定怎么办?可以用集合.因为集合是可变长度的. 集合 ...
- mysql 学习(1)
1.从图中看到mysql是客户服务器模式. 2.我们如何操纵数据库? a.直接sql,各种编程语言, 3.客户端和服务器如何通信呢? 凡是c/s模式的都会自己的协议,但是都是基于TCP/IP协议,在l ...
- Corn Fields - POJ 3254(状态压缩)
题目大意:有一个M*N的牧场,G(i, j) = 1表示这块地营养丰富,可以喂养牛,等于0表示贫瘠,不能喂养牛,所有的牛都讨厌与别的牛相邻,求有多少种放置牛的方式. 分析:算是炮兵那个题的弱化版吧,先 ...
- 410. Split Array Largest Sum
做了Zenefits的OA,比面经里的简单多了..害我担心好久 阴险的Baidu啊,完全没想到用二分,一开始感觉要用DP,类似于极小极大值的做法. 然后看了答案也写了他妈好久. 思路是再不看M的情况下 ...
- Qt对话框QDialog
QDialog是Qt中所有对话框窗口的基类 当QWidget无父组件的时候作为一个独立的窗口,有父组件的时候,将作为一个可见的部件嵌入到父组件里面. QDialog不能作为子部件嵌入到其他容器中 对话 ...
- CSS3 新增属性
1Css3概述 从2010年开始,HTML5与CSS3就一直是互联网技术中最受关注的两个话题. 从前端技术的角度可以把互联网的发展分为三个阶段:第一阶段是web1.0以内容为主的网络 前端主流技术是H ...
- c#基础语言编程-正则表达式基础
引言 正则表达式是一种用高度抽象的字符串来描述字符串特征,进而实现对字符串的匹配.提取.替换等等.正则表达式(以下简称正则,Regex)通常不独立存在,各种编程语言和工具作为宿主语言提供对正则的支持, ...
- TreeComboBox控件范例
本文转载:http://www.cnblogs.com/hoodlum1980/archive/2008/01/30/1058140.html 在我印象中有很多各种各样的自定义控件(例如TreeLis ...
- PHP问题Parse error: syntax error, unexpected end of file in
检查一下你的php文件中是否存在这样的语法错误:<<php{>或者<?{?>以上两种写法都是有错误的,修改为下面的就可以了: <?php}?>
- 有关Transaction not successfully started问题解决的方法
我的项目配置:struts2+hibernate3.3+spring3.2.5 主要问题:在进行更新和提交操作时出现下面异常 org.springframework.transaction.Trans ...