文章目录

  • 题目
  • 思路
  • 代码

题目

题目链接
描述
跳跳棋是在一条数轴上进行的。棋子只能摆在整点上。每个点不能摆超过一个棋子。我们用跳跳棋来做一个简单的游戏:棋盘上有333颗棋子,分别在a,b,ca,b,ca,b,c这三个位置。我们要通过最少的跳动把他们的位置移动成x,y,zx,y,zx,y,z。(棋子是没有区别的)跳动的规则很简单,任意选一颗棋子,对一颗中轴棋子跳动。跳动两颗棋子距离不变。一次只允许跳过111颗棋子。

写一个程序,首先判断是否可以完成任务。如果可以,输出最少需要的跳动次数。
输入
第一行包含三个整数,表示当前棋子的位置abca b cabc。(互不相同)
第二行包含三个整数,表示目标位置xyzx y zxyz。(互不相同)
输出
如果无解,输出一行NO。如果可以到达,第一行输出YES,第二行输出最少步数。
样例输入
1 2 3
0 3 5
样例输出
YES
2
范围
100%100\%100% 绝对值不超过10910^9109

思路

设有a,b,c三点,且a≤b≤ca\leq b \leq ca≤b≤c
则有两种方式跳
一、b跳
则只有两种状态(2a−b,a,c)(2a-b,a,c)(2a−b,a,c)和(a,c,2c−b)(a,c,2c-b)(a,c,2c−b),可看做无限扩展
二、a,c绕着b跳,则有一下三种情况:
我们设d1=b−a,d2=c−bd_1 = b-a,d_2 = c-bd1​=b−a,d2​=c−b。
1、d1>d2d_1 > d_2d1​>d2​,即ccc绕bbb跳,也可理解为bbb和ccc向左平移d2d_2d2​个单位
2、d1&lt;d2d_1 &lt; d_2d1​<d2​,即aaa绕bbb跳,也可理解为aaa和bbb向右平移d1d_1d1​个单位
3、d1=d2d_1 = d_2d1​=d2​,即无法再绕bbb跳
如果一直按第二种方式跳,我们可以发现一定会得到d1=d2d_1=d_2d1​=d2​的状态,之后就不能再按第二种方式跳了,所以我们可以把此时的状态当作根

所以我们把某一状态按第一种方式跳之后的状态当做子节点,按第二种方式跳之后的状态作为父亲(这里还用不到求LCA)

我们把d1=d2d_1=d_2d1​=d2​的状态看做根,所以说当前状态到根的步数其实就是当前状态的深度
注意,我可没说要把状态储存起来

跳的优化
有这样一个状态

如果你一步一步的跳,也许就会耗费时间。而我们可以知道,d1=k∗d2+q(q&lt;d1)d_1 = k*d_2+q(q&lt;d_1)d1​=k∗d2​+q(q<d1​),我们就可以把bbb和ccc都向左平移k∗d2k*d_2k∗d2​个单位,因为题目说了,三个棋子是完全相同的,所以不用去细分次序。而a,ba,ba,b的距离就是qqq了

此题其实可以分为两个问题:

  1. 如何判断有无解
    其实很好搞,只要我们一直按第二种方式跳,如果它们跳到不能再跳(到了根节点),判断根节点相不相同就行了(你莫给老子说不同子树下还有路径相连,你有毒吧)
  2. 如何搞到最小步数
    这里才是LCA最大的用处。
    我们知道LCA有两种思想:
    1、先把两个点弄到同一深度,再一起爬山(暴力)
    2、tarjan
    在之前判断同一子树的时候我们就可以把深度处理出来,然后再把它们搞到同一深度,在二分枚举它们到LCA的深度,再看是否一样就行了

代码

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;struct node{int a[4];inline void sor_t(){sort(a+1, a+1+3);return;}}fir, goal;int dep1, dep2, cnt, ans, l1, l2;bool flag;inline int dfs(node x, int &dep, int &len){int d1 = x.a[2] - x.a[1];int d2 = x.a[3] - x.a[2];while( d1 != d2 ){if( d1 >= d2 ){int s_step = d1/d2, yu = d1%d2;if( !yu ){dep += s_step-1;len = d1;return x.a[1];}d1 = yu, x.a[3] -= s_step*d2;dep += s_step, x.a[2] -= s_step*d2;}else{int s_step = d2/d1, yu = d2%d1;if( !yu ){dep += s_step-1;x.a[1] += (s_step-1)*d1;len = d2;return x.a[1];}d2 = yu, x.a[1] += s_step*d1;dep += s_step, x.a[2] += s_step*d1;}}len = d1;return x.a[1];
}inline void check(int &x, int &y, int &z, int lim){int d1 = y-x, d2 = z-y;while( lim ){if( d1 > d2 ){int s_step = d1/d2, yu = d1%d2;if( s_step >= lim ){y -= lim*d2;z -= lim*d2;if( x == y ){y = z;z = y+d2;}return;}d1 = yu, lim-=s_step;y = x + yu, z = y + d2;}else{int s_step = d2/d1, yu = d2%d1;if( s_step >= lim ){x += lim*d1, y += lim*d1;if( y == z ){y = x;x = y-d1;}return;}d2 = yu, lim -= s_step;y = z - yu, x = y - d1;}}
}int main(){for(int i = 1; i < 4; i ++)scanf("%d", &fir.a[i]);for(int i = 1; i < 4; i ++)scanf("%d", &goal.a[i]);fir.sor_t(), goal.sor_t();if(dfs(fir, dep1, l1) != dfs(goal, dep2, l2) || l1 != l2)printf("NO\n");else{puts("YES");if( dep1 > dep2 ){cnt = dep1 - dep2;check(fir.a[1], fir.a[2], fir.a[3], cnt);}else if( dep2 > dep1 ){cnt = dep2 - dep1;check(goal.a[1], goal.a[2], goal.a[3], cnt);}int l = 0, r = min(dep1, dep2);int ab[3] = {};int bc[3] = {};while( l <= r ){int mid = (l+r) >> 1;check(ab[0]=fir.a[1], ab[1]=fir.a[2], ab[2]=fir.a[3], mid);check(bc[0]=goal.a[1], bc[1]=goal.a[2], bc[2]=goal.a[3], mid);if( ab[0] == bc[0] && ab[1] == bc[1] && ab[2] == bc[2] ){ans = 2*mid;r = mid-1;}else l = mid+1;}printf("%d\n", cnt + ans);}return 0;
}

跳跳棋(国家集训队,LCA,洛谷P1852,BZOJ[2144])相关推荐

  1. P1497[洛谷]P1852跳跳棋

    P1497[洛谷]P1852跳跳棋 标签(空格分隔): 信息 图论 二分 洛谷 考题,看到就觉得是不可能写出来的那种,于是打了个bfs直接走人. 考完之后听吕大佬讲过之后觉得此题可谓绝妙啊%%% 屁颠 ...

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

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

  3. 洛谷P1852 奇怪的字符串

    题目描述 输入两个01串,输出它们的最长公共子序列的长度 输入输出格式 输入格式: 一行,两个01串 输出格式: 最长公共子序列的长度 输入输出样例 输入样例#1: 复制 01010101010 00 ...

  4. 洛谷 P4175: bzoj 1146: [CTSC2008]网络管理

    令人抓狂的整体二分题.根本原因还是我太菜了. 在学校写了一个下午写得头晕,回家里重写了一遍,一个小时就写完了--不过还是太慢. 题目传送门:洛谷P4175. 题意简述: 一棵 \(n\) 个结点的树, ...

  5. 洛谷 P4151 BZOJ 2115 [WC2011]最大XOR和路径

    //bzoj上的题面太丑了,导致VJ的题面也很丑,于是这题用洛谷的题面 题面描述 XOR(异或)是一种二元逻辑运算,其运算结果当且仅当两个输入的布尔值不相等时才为真,否则为假. XOR 运算的真值表如 ...

  6. 洛谷 P2046 BZOJ 2007 海拔(NOI2010)

    题目描述 YT市是一个规划良好的城市,城市被东西向和南北向的主干道划分为n×n个区域.简单起见,可以将YT市看作 一个正方形,每一个区域也可看作一个正方形.从而,YT城市中包括(n+1)×(n+1)个 ...

  7. 洛谷 3784(bzoj 4913) [SDOI2017]遗忘的集合——多项式求ln+MTT

    题目:https://www.luogu.org/problemnew/show/P3784 https://www.lydsy.com/JudgeOnline/problem.php?id=4913 ...

  8. 洛谷 P4546 bzoj 5020 在美妙的数学王国中畅游 —— LCT+泰勒展开

    题目:https://www.luogu.org/problemnew/show/P4546 先写了个55分的部分分,直接用LCT维护即可,在洛谷上拿了60分: 注意各处 pushup,而且 spla ...

  9. 洛谷P1852:跳跳棋(LCA,树形结构)

    解析 考虑一个三元组(x,y,z)(x,y,z)(x,y,z),看它能如何跳 要么是yyy往左右跳,左右边界会变大 要么是两边往中间跳,由于最多跨过一个棋子,所以左右边界会变小 当三点等距时,无法往中 ...

最新文章

  1. 软路由 文件服务器拒绝,软路由踩坑
  2. NLP:Transformer的架构详解之详细攻略(持续更新)
  3. 你还在用 Swagger?试试这个神器!
  4. JAVA WEB_中间件
  5. ImportError: numpy.core.multiarray failed to import
  6. Kevin专栏---自定义安装对话框的界面
  7. 使用vh来制作高度自适应页面和元素垂直居中
  8. 用键盘怎么直接打出小于等于和大于等于
  9. 计算机基础知识表格加密管理,【事业单位考试】计算机网络知识:数据加密技术之密钥管理...
  10. python绘制剖面图_用python绘制剖面图
  11. SMTP连接器的使用
  12. C#以对象为成员的例子
  13. TypeScript 素描 - 接口
  14. iphone pop服务器没有响应,iPhone 6 Plus跳屏或者触摸失灵的解决办法
  15. SpringBoot part4 day15
  16. CRAFT:Character region awareness for text detection 论文阅读
  17. python计算日期间的差值,python 计算时间、日期差值类
  18. 程序员成为“备胎”的5年,我一直在等...(外包——字节跳动)
  19. Redis-学习笔记整理+汇总
  20. Java——API(接口)

热门文章

  1. [Linux] Linux中/tmp目录下文件莫名丢失
  2. Activiti表结构
  3. 关于中文字体的设置说明(font:12px/1.5 tahoma,arial,\5b8b\4f53)
  4. C++编写任意次clampedB样条曲线(曲线分别与第一个控制点和最后一个控制点的第一边和最后一边相切)
  5. 用三色带摄像管替换电视机显像管的摄像机
  6. 算法复习-Akari Puzzle
  7. 午饭加喝酸奶可减轻电脑辐射
  8. leetcode报数题
  9. mysql 从从(主主)复制(故障转移)
  10. 运算放大器分析----虚短和虚断(转载)