zoukankan      html  css  js  c++  java
  • 【BZOJ 2144】 2144: 跳跳棋 (倍增LCA)

    2144: 跳跳棋

    Time Limit: 10 Sec  Memory Limit: 259 MB
    Submit: 642  Solved: 307

    Description

    跳跳棋是在一条数轴上进行的。棋子只能摆在整点上。每个点不能摆超过一个棋子。我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置。我们要通过最少的跳动把他们的位置移动成x,y,z。(棋子是没有区别的)跳动的规则很简单,任意选一颗棋子,对一颗中轴棋子跳动。跳动后两颗棋子距离不变。一次只允许跳过1颗棋子。  写一个程序,首先判断是否可以完成任务。如果可以,输出最少需要的跳动次数。

    Input

    第一行包含三个整数,表示当前棋子的位置a b c。(互不相同)第二行包含三个整数,表示目标位置x y z。(互不相同)

    Output

    如果无解,输出一行NO。如果可以到达,第一行输出YES,第二行输出最少步数。

    Sample Input

    1 2 3
    0 3 5

    Sample Output

    YES
    2

    【范围】
    100% 绝对值不超过10^9

    HINT

    Source

    【分析】

      神奇的题目。!!

    ORZ hzwer

      这样考虑只用考虑往中间跳了,这样的话你当然不会傻傻地一步步跳,跟辗转相除差不多的,可以快速求出连续跳x步到的地方。

      于是你用倍增求LCA就能知道两点间路径的长度了。

      【我觉得厉害的地方就是转成树形,看出来是只用两边考虑往中间跳的。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 using namespace std;
     7 #define INF 0x7fffffff
     8 
     9 int a[5][5];
    10 int mymin(int x,int y) {return x<y?x:y;}
    11 
    12 int ffind(int x,int y)
    13 {
    14     int t1=a[x][2]-a[x][1],t2=a[x][3]-a[x][2];
    15     if(t1==t2) return 0;
    16     int xx;
    17     if(t1<t2)
    18     {
    19         xx=mymin(y,(t2-1)/t1);
    20         y-=xx;
    21         a[x][1]+=xx*t1;a[x][2]+=xx*t1;
    22     }
    23     else
    24     {
    25         xx=mymin(y,(t1-1)/t2);
    26         y-=xx;
    27         a[x][2]-=xx*t2;a[x][3]-=xx*t2;
    28     }
    29     if(y) return ffind(x,y)+xx;
    30     else return xx;
    31 }
    32 
    33 int main()
    34 {
    35     for(int i=1;i<=3;i++) scanf("%d",&a[0][i]);
    36     for(int i=1;i<=3;i++) scanf("%d",&a[1][i]);
    37     sort(a[0]+1,a[0]+1+3);
    38     sort(a[1]+1,a[1]+1+3);
    39     int d1,d2;
    40     for(int i=1;i<=3;i++) a[3][i]=a[0][i]; d1=ffind(3,INF);
    41     for(int i=1;i<=3;i++) a[4][i]=a[1][i]; d2=ffind(4,INF);
    42     if(a[3][1]!=a[4][1]||a[3][2]!=a[4][2]||a[3][3]!=a[4][3]) printf("NO
    ");
    43     else
    44     {
    45         if(d1<d2)
    46         {
    47             swap(d1,d2);
    48             for(int i=1;i<=3;i++) swap(a[0][i],a[1][i]);
    49         }
    50         int ans=ffind(0,d1-d2);
    51         int l=0,r=INF;
    52         while(l<r)
    53         {
    54             int mid=(l+r)>>1;
    55             for(int i=1;i<=3;i++) a[3][i]=a[0][i]; d1=ffind(3,mid);
    56             for(int i=1;i<=3;i++) a[4][i]=a[1][i]; d2=ffind(4,mid);
    57             if(a[3][1]!=a[4][1]||a[3][2]!=a[4][2]||a[3][3]!=a[4][3])
    58             {
    59                 l=mid+1;
    60                 // for(int i=1;i<=3;i++) a[0][i]=a[3][i];
    61                 // for(int i=1;i<=3;i++) a[1][i]=a[4][i];
    62             }
    63             else r=mid;
    64         }
    65         printf("YES
    %d
    ",ans+2*l);
    66     }
    67     return 0;
    68 }
    View Code

    2017-04-05 09:13:21

  • 相关阅读:
    创建和查看数据库
    初识数据库
    类似京东商城客户端应用源码
    高仿拼多多应用源码
    读者汇app项目案例源码
    Win10系统配置Apache虚拟主机
    Firefox+PHPStorm 8+XDebug单步调试
    Swing带TrayIcon(托盘小图标)的Hello world示例
    HttpClient v4.5 简单抓取主页数据
    23种设计模式的代码分析
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6667285.html
Copyright © 2011-2022 走看看