fzoj 1193 最少步数
题目描述
在各种棋中,一种棋子的走法总是一定的,如中国象棋中马走“日”。有一位小学生就想如果马能有两种走法将更加增加趣味性,因此,他规定马既能按“日”飞,也能各象一样走“田”字。他的同桌平时喜欢下围棋,知道这件事后觉得很有趣,就和他玩一种新游戏,在围棋盘上任选两点A、B,A点放上黑子,B点放上白子,代表两匹马。棋子可以按“日”字走,也可以按“田”字走,俩人一个走黑马,一个走白马。谁用最少的步数走到左上角坐标为(1,1)的点时,谁获胜。现在他请你帮忙,给你A,B两点的坐标,想知道两个位置到(1,1)点的可能最少步数。
输入
每行的两个整数,第一行为A点坐标
第二行为B点坐标
(* 注意:棋盘大小规模为100*100以内 *)
输出
两行第一行为A点到(1,1)的步数
第二行为B点到(1,1)的步数
样例输入
12 1618 10
样例输出
89
这个题由于不是规规矩矩的一种走法,所以可以考虑用贪心。
如下图A点 走的4步我们应该怎么思考呢
首先 由于我们要求步数最少 所以不管横向还是纵向都是以2格为主
这样我们可以找一下对于A点横纵坐标/2之后的较大值 这样的话对于较小的那个不管怎么样都能凑出来 毕竟我有-2,-1,1,2四种选择
不过这样就万事大吉了?
tanπ/2对吧
一定是有特殊情况的
下图给出的特殊情况一下冲击到你
不过在这之前
我要先分析一下特殊情况出现的条件:
刚才我们给出的贪心建立的前提是有一条较长的边不停地向0走去
另外一条边不管怎么走都好
但是!!!!
这样我们就知道了
如果两条边都必须通过走“-”实现的时候 就成了特殊情况
所有的特殊情况如下图:
这样就是所有的特殊情况
具体怎么走 各位可以自己试一试
总之就是不管是横和纵都要往回走 这样我们刚才用的那个/2的招数就不会有用了
所以这几种情况就打表就好
但是最后别忘了
对于A(x,y)--->步数是((max(x,y)+1)/2)针对左上角是0,0才有用
大家可以自己模拟一下(1,1) 发现并不适用
不过无伤大雅
你读入坐标的时候代入自己的函数中都-1就好了
下面是代码实现:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
using
namespace
std;
int
sum=0;
struct
NODE
{
int
heng;
int
zong;
}node[101];
void
zou(
int
n,
int
m)
{
if
(n==0&&m==0) sum=0;
else
if
(n==0&&m==1||n==0&&m==2) sum=2;
else
if
(m==0&&n==1||n==2&&m==0) sum=2;
else
if
(m==1&&n==1) sum=3;
else
if
(m==2&&n==3||m==3&&n==2) sum=3;
else
{
int
maxx=max(m,n);
sum=(maxx+1)/2;
}
}
int
main()
{
int
xyi,yyi,xer,yer;
scanf
(
"%d%d%d%d"
,&xyi,&yyi,&xer,&yer);
zou(xyi-1,yyi-1);
cout<<sum<<endl;
sum=0;
zou(xer-1,yer-1);
cout<<sum<<endl;
}
不过想法真的宝贵
还是谢谢tyk的帮助@Camouflager
写在最后:
我是Michael_Bryant
一个有dalao梦的蒟蒻
最后的最后:
b站 得到的都是是
可以去捧捧场(跑)