P1747 好奇怪的游戏题解

题目背景

《爱与愁的故事第三弹·shopping》娱乐章。

调调口味来道水题。

题目描述

爱与愁大神坐在公交车上无聊,于是玩起了手机。一款奇怪的游戏进入了爱与愁大神的眼帘:***(游戏名被打上了马赛克)。这个游戏类似象棋,但是只有黑白马各一匹,在点x1,y1和x2,y2上。它们得从点x1,y1和x2,y2走到1,1。这个游戏与普通象棋不同的地方是:马可以走“日”,也可以像象走“田”。现在爱与愁大神想知道两匹马到1,1的最少步数,你能帮他解决这个问题么?

输入格式

第1行:两个整数x1,y1

第2行:两个整数x2,y2

输出格式

第1行:黑马到1,1的步数

第2行:白马到1,1的步数

输入输出样例

输入 #1复制

12 16

18 10

输出 #1复制

8

9

说明/提示

100%数据:x1,y1,x2,y2<=20

思路

s4=s3+s2+(x+y-s2*3)/4;


  • 解释一下,x代表行坐标,y代表列坐标

  • s1是x与y的差

  • s2是s1除以4的余数

  • s3是s1除以4的商

  • s4是最终得数

这个公式适用于所有除了(1,2)和(2,1)的情况,就是(10^8,10^9)也能求出正确答案。首先我们画一条对角线,沿着对角线让马走象步,所用步数最少。所以我们要想办法让处在对角线以外的马飞入对角线。因为象步相对比“飞日”快(不绝对,“飞日”在某些情况下比较精确),所以用象步慢慢逼近对角线,再用“飞日”准确插入到对角线中,步数一定最少。

如果本来就在对角线上,即x==y,那么飞到(1,1)的步数为x/2(x>=3,其余加特判)。飞入对角线只需看行列的差是否是4的倍数(拿(16,12)举例,象步即(x-2,y+2),移项得(x+4,y),x-y=4,4是4的倍数,所以可以直接飞入对角线),若有余数,则飞到象步所能飞到的最大位置,用“飞日”飞。 飞入对角线的步数为**(x-y)/4+余数**,两者相加就可求出最短路径。

代码

#include <cstdio>
int i,j,k,m,n,l,o,p,x,y;
int sum(int x,int y)
{
    int t,i,j,s1,s2,s3,s4;
    if(x<y)//有可能x<y,所以交换一下以便求差
    {
        t=x; 
        x=y;
        y=t;
    }
    if(x==2&&y==1) return 2;
    else if(x==2&&y==2) return 3;
    //这两个点过不去,特殊判定
    s1=x-y;//求差
    s2=s1%4;//余数
    s3=s1/4;//商
    s4=s3+s2+(x+y-s2*3)/4;
    return s4;
    /*细节:发现这个return s4不写,函数仍然返回s4的
    值因为定义在函数内部(包括main())的变量用栈来分
    配空间,所以有时是随机数。
    在函数外部的变量用static
    分配,值总是0。函数的返回值在栈底(返回给
    main(),c++用ESP做栈寄存器),这个s4恰好就是栈
    底,如果没有定义变量的话栈底就是随机数了
    所以不写return也可以,大家可以试一试*/
 } 
int main()
{
    int a,b,c,d;
    scanf("%d%d",&a,&b);
    printf("%d\n",sum(a,b));
    scanf("%d%d",&c,&d);
    printf("%d",sum(c,d));
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值