题目描述

跳跳棋是在一条数轴上进行的。棋子只能摆在整点上。每个点不能摆超过一个棋子。

我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置。我们要通过最少的跳动把他们的位置移动成x,y,z。(棋子是没有区别的)

跳动的规则很简单,任意选一颗棋子,对一颗中轴棋子跳动。跳动后两颗棋子距离不变。一次只允许跳过1颗棋子。

写一个程序,首先判断是否可以完成任务。如果可以,输出最少需要的跳动次数。

输入输出格式

输入格式:

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

第二行包含三个整数,表示目标位置x y z。(互不相同)

输出格式:

如果无解,输出一行NO。

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

输入输出样例

输入样例#1: 复制

1 2 3
0 3 5

输出样例#1: 复制

YES
2

说明

20% 输入整数的绝对值均不超过10

40% 输入整数的绝对值均不超过10000

100% 绝对值不超过10^9

【解题思路】

为了方便描述,我们把左边的棋子称为a,中间的棋子称为b,右边的为c。仔细观察跳棋规则,我们会发现当左右两跳棋到中间距离不等时有三种转移方式(因为不能跳过两个棋子)

  1. b往a方向跳
  2. b往c方向跳
  3. a,c离b距离近的往里跳

a,c到b距离相等的时候只有1,2两种转移方式。

这TM不就是棵二叉树

往中间跳的是父亲,两旁的是儿子。

根就是没有父亲的节点(想一想,是什么)

现在就好做了,能不能到看根相不相同,移动次数就是他们到LCA的距离之和 ->LCA传送门

问题又来了,状态太多保存不下怎么办???


下面是重点!!!

首先要明白棋子是相同的,所以a,b,c保存的是相对位置,跳一次相当与把两个棋子平移dis,dis为它们之间的距离。我们设d1=b-a,d2=c-b。d1小于d2时我们移动a,然后会发现d1没变,d2减小了d1所以我们可以连续走d2/d1次,反之亦然,此时d2小于d1了换个方向走。注意:d2%d1等于0时走d2/d1-1步就到根了。


那么怎么计算路径呢

先把深度大的节点移到深度小的节点(深度在求根的时候可以顺便求出来)然后二分到LCA的距离,往上走n步和求根差不多这里就不废话了,上代码。

【code】

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<algorithm>
 7 #define ll long long
 8 #define inf 1000000000
 9 using namespace std;
10 int read() {
11     int x=0,f=1;char ch=getchar();
12     while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
13     while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
14     return x*f;
15 }
16 int t1,t2,tmp,ans;
17 int a[5],b[5];
18 struct data {int a[5];};
19 data cal(int *a,int k) { //得到a状态向上走k次的状态
20     data ans;
21     int t1=a[2]-a[1],t2=a[3]-a[2];
22     for(int i=1; i<=3; i++)ans.a[i]=a[i];
23     if(t1==t2)return ans;
24     if(t1<t2) {
25         int t=min(k,(t2-1)/t1);
26         k-=t; tmp+=t;//顺便记录深度
27         ans.a[2]+=t*t1; ans.a[1]+=t*t1;
28     } else {
29         int t=min(k,(t1-1)/t2);
30         k-=t; tmp+=t;
31         ans.a[2]-=t*t2; ans.a[3]-=t*t2;
32     }
33     if(k)return cal(ans.a,k);//辗转相除
34     else return ans;
35 }
36 bool operator!=(data a,data b) {
37     for(int i=1; i<=3; i++)if(a.a[i]!=b.a[i])return 1;
38     return 0;
39 }
40 int main() {
41     for(int i=1; i<=3; i++)a[i]=read();
42     for(int i=1; i<=3; i++)b[i]=read();
43     sort(a+1,a+4); sort(b+1,b+4);
44     data t1=cal(a,inf); int d1=tmp; tmp=0;
45     data t2=cal(b,inf); int d2=tmp; tmp=0;
46     //t1,t2分别为a,b的根,d1,d2为深度
47     if(t1!=t2) { puts("NO"); return 0; }
48     if(d1>d2) {
49         swap(d1,d2);
50         for(int i=1; i<=3; i++)swap(a[i],b[i]);
51     }
52     ans=d2-d1;
53     t1=cal(b,ans);
54     for(int i=1; i<=3; i++)b[i]=t1.a[i]; //较深的向上调整
55     int l=0,r=d1;
56     while(l<=r) { //二分
57         int mid=(l+r)>>1;
58         if(cal(a,mid)!=cal(b,mid))l=mid+1;
59         else r=mid-1;
60     }
61     puts("YES");
62     printf("%d",ans+2*l);
63     return 0;
64 }

转载于:https://www.cnblogs.com/66dzb/p/11229158.html

[国家集训队]跳跳棋相关推荐

  1. [BZOJ2144]国家集训队 跳跳棋

    题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他们的位置移动 ...

  2. 洛谷 P1852 [国家集训队] 跳跳棋

    题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他们的位置移动 ...

  3. P1852 [国家集训队]跳跳棋

    这什么神题啊- https://www.luogu.org/problemnew/show/P1852 想了一个小时一点儿思路也没(头里只有爆搜) 看了题解才知道是树-这谁顶的住啊 考虑中间点到两边距 ...

  4. [国家集训队2011]跳跳棋

    P1852 [国家集训队]跳跳棋https://www.luogu.org/problemnew/show/P1852 Description 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不 ...

  5. 跳跳棋(国家集训队,LCA,洛谷P1852,BZOJ[2144])

    文章目录 题目 思路 代码 题目 题目链接 描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的游戏:棋盘上有333颗棋子,分别在a,b,ca,b ...

  6. bzoj2144 【国家集训队2011】跳跳棋

    Description 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他 ...

  7. 【2011集训队出题】跳跳棋

    [2011集训队出题]跳跳棋 Time Limits: 1000 ms Memory Limits: 128000 KB Description 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点 ...

  8. bzoj2144 [2011集训队出题] 跳跳棋 倍增 lca

    Description 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把 ...

  9. 【BZOJ2117】 [2010国家集训队]Crash的旅游计划

    [BZOJ2117] [2010国家集训队]Crash的旅游计划 Description 眼看着假期就要到了,Crash由于长期切题而感到无聊了,因此他决定利用这个假期和好友陶陶一起出去旅游. Cra ...

  10. 2038: [2009国家集训队]小Z的袜子(hose)+莫队入门

    题目链接:2038: [2009国家集训队]小Z的袜子(hose) 题目: Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再 ...

最新文章

  1. 机器学习XGBoost——后面的明天更
  2. numpy中的axis=0,axis=1
  3. Android Studio开发概要记录
  4. oracle性能优化总结
  5. JavaWeb课程复习资料——中文乱码上下文处理
  6. logstash redis kafka传输 haproxy日志
  7. 多个会话对表加表级读锁和表级写锁后的操作权限分析(表级读锁+表级写锁)
  8. Android官方开发文档Training系列课程中文版:高效显示位图之管理位图内存
  9. e3mall商城的归纳总结10之freemarker的使用和sso单点登录系统的简介
  10. jquery chosen插件的使用(搜索查询下拉列表,多选)
  11. IT桔子2013年度中国互联网创业投资盘点(简版): 群雄逐鹿中,你还在这里坚持
  12. 谷歌软件工程师_这是我曾经在Google担任软件工程师的简历。
  13. 解决Invalid `Podfile` file: no implicit conversion of nil into String
  14. 跨境电商erp管理系统
  15. connection reset by beer问题排查
  16. unity3d 角色 武器 动画 和 blender 工作流
  17. 计算机工作原理【操作系统和进程】
  18. 链接、图像、列表、计数器
  19. PrinTao CANON Home Studio Edition 8.0r12 17 Mac 佳能专业打印软件
  20. html名人名言页面,网页制作:关于生命的名言警句 ― 名人名言  一品故事网,Www.07938.Come...

热门文章

  1. android如何实现环形缓冲区
  2. 第五届模式识别与人工智能国际会议-PRAI 2022
  3. A + B Problem Too
  4. 一文带你熟悉JAVA IO这个看似很神秘的菇凉
  5. 关于传递函数的频率响应和低通滤波器
  6. 测绘 绘图 计算机,20 机械测绘与计算机绘图 草图绘制范例 课件:草图绘制范例.pptx...
  7. 内核编译报错: warning: the frame size of 1072 bytes is larger than 1024 bytes
  8. Vfed大橙子模板 苹果cms自动采集 的方法
  9. 数字科技陪伴企业成长|突破封锁,庚顿数据助力中国名牌全球瞩目
  10. AD学习笔记(二)原理图库以及原理图绘制