[bzoj2144]: 跳跳棋
来源:互联网 发布:淘宝联盟个人可以买吗 编辑:程序博客网 时间:2024/05/02 02:38
2144: 跳跳棋
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 689 Solved: 326
[Submit][Status][Discuss]
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
0 3 5
Sample Output
YES
2
【范围】
100% 绝对值不超过10^9
2
【范围】
100% 绝对值不超过10^9
思路
bzoj 2144 跳跳棋 2017.6.2 by xlj
难题一道 很不好想
从题目条件中看似6种状态
但因为一个棋子不能跳过两个棋子
如果 1 4 10 此时右边的就不能跳 因为越过两个棋子了
所以只有三种(中间的可以跳两边&离中间棋子距离近的可以跳)
可以把这三种状态看成一棵树
此时可以设棋子为x,y,z;
设y-x=t1 z-y=t2
当t1==t2的时候就没有办法跳了 这个状态就是树根了
如果t1<t2 最多跳(t2-1)/t1步 t2>t1 同理
然后类似gcd的方法求树根 (t1,t2)->(t1-t2,t2)
从给出的a1,b1,c1往上推出数根
a2,b2,c2也是一样
如果树根不同 代表不能完成 输出NO
如果相同 先把两个状态深度调为一样 再往上找(LCA)
这里用的是二分法找
难题一道 很不好想
从题目条件中看似6种状态
但因为一个棋子不能跳过两个棋子
如果 1 4 10 此时右边的就不能跳 因为越过两个棋子了
所以只有三种(中间的可以跳两边&离中间棋子距离近的可以跳)
可以把这三种状态看成一棵树
此时可以设棋子为x,y,z;
设y-x=t1 z-y=t2
当t1==t2的时候就没有办法跳了 这个状态就是树根了
如果t1<t2 最多跳(t2-1)/t1步 t2>t1 同理
然后类似gcd的方法求树根 (t1,t2)->(t1-t2,t2)
从给出的a1,b1,c1往上推出数根
a2,b2,c2也是一样
如果树根不同 代表不能完成 输出NO
如果相同 先把两个状态深度调为一样 再往上找(LCA)
这里用的是二分法找
#include<cstdio>#include<iostream>#include<cstring>#include<cstdlib>#include<algorithm>#include<cmath>#define inf 1000000000using namespace std;int a[5],b[5];struct node{int a[5];};int tmp,ans;node cal(int *a,int k)//在树上往上跳的 函数 k是跳的步数 跳到根就结束 {node ans;int t1=a[2]-a[1];int t2=a[3]-a[2];for(int i=1;i<=3;i++) ans.a[i]=a[i];if(t1==t2) return ans;if(t1<t2){int t=min(k,(t2-1)/t1);k-=t;tmp+=t;ans.a[2]+=t*t1;ans.a[1]+=t*t1;}else {int t=min(k,(t1-1)/t2);k-=t;tmp+=t;ans.a[2]-=t*t2;ans.a[3]-=t*t2;}if(k) return cal(ans.a,k);else return ans;}bool operator !=(node xx,node yy){//重载!比较结构体 for(int i=1;i<=3;i++) if(xx.a[i]!=yy.a[i]) return 1;return 0;}int main(){for(int i=1;i<=3;i++)scanf("%d",&a[i]);for(int i=1;i<=3;i++) scanf("%d",&b[i]);sort(a+1,a+4);sort(b+1,b+4);node t1=cal(a,inf);int d1=tmp;tmp=0;node t2=cal(b,inf);int d2=tmp;tmp=0;//往上找 找到最上面 y-x==z-y 的树根 if(t1!=t2) {puts("NO");return 0;}if(d1>d2) {swap(d1,d2);for(int i=1;i<=3;i++)swap(a[i],b[i]); } ans=d2-d1;//深度大的就往上调 t1=cal(b,ans); for(int i=1;i<=3;i++) b[i]=t1.a[i]; int l=0,r=d1; while(l<=r)//二分法找LCA {int mid=(l+r)>>1;if(cal(a,mid)!=cal(b,mid))l=mid+1;//不等就网上找 else r=mid-1;//如果相等了 还可能在答案那个节点的下面 } puts("YES"); printf("%d",ans+2*l); return 0;}
阅读全文
1 0
- 【BZOJ2144】跳跳棋
- 【杂题】bzoj2144跳跳棋
- 【bzoj2144】跳跳棋
- [bzoj2144]: 跳跳棋
- [bzoj2144]跳跳棋 LCA
- bzoj2144 跳跳棋 二分+lca
- bzoj2144 跳跳棋 二分&lca 神题
- bzoj2144 【国家集训队2011】跳跳棋
- 【BZOJ2144】跳跳棋 模拟gcd以及倍增LCA
- 2144: 跳跳棋
- BZOJ 2144 跳跳棋
- 2144: 跳跳棋
- BZOJ 2144: 跳跳棋
- bzoj 2144: 跳跳棋
- 【bzoj2145】【跳跳棋】【二分+lca】
- 【LCA】bzoj 2144:跳跳棋
- 【数学】2011集训队出题 跳跳棋
- [BZOJ]2144: 跳跳棋 二分+LCA
- 无向图的邻接表广度优先算法
- Unity场景打包AssetBundle并加载
- Android开发之渐变效果gradient属性
- 四、RxJava基础 ---合并操作(Combining Observables)
- LaTex入门(一)
- [bzoj2144]: 跳跳棋
- 噪声估计的主要方法简要概述
- javascript中检测某个字符串在数组中是否存在
- PHP7扩展开发
- SVN使用总结
- CSS Modules用法教程
- MySQL函数
- 第一个Java程序(HelloWorld)的编写
- 网页js获取视频帧图片