题目链接:https://www.luogu.com.cn/problem/P1852
一个数轴上有3个跳棋,你每次可以将一个跳棋跳到另一个跳棋对称的位置,但是不能一次跨过两个棋子。给出初始状态,和目标状态,求最小步数。
坐标的绝对值不超过109
首先排序+差分一下记为a,b,c,然后四种跳法操作模拟一下发现是
- (a,b,c)→(a,b+c,c)
- (a,b,c)→(a,b−c,c)
- (a,b,c)→(a+b,b,c−b)
- (a,b,c)→(a−b,b,c+b)
然后下一步就不会了
反着考虑,能发现这些操作都是可逆的,也就是说我们可以从终点开始倒着推,或者我们可以正反着一起推,并且只保留两个操作
- (a,b,c)→(a,b−c,c)
- (a,b,c)→(a+b,b,c−b)
然后此时不难发现对于一个a,b,c最多只能执行以上的一个操作。
这个可以视为一个往根跳的过程,然后求两个点的路径长度,而跳的过程可以类似于gcd的复杂度做,因为b+c是一直减少的,以b+c代深度然后二分LCA的深度即可。
时间复杂度:O(log2D)
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
ll a,b,c,A,B,C;
ll jump(ll &a,ll &b,ll &c,ll x){
ll ans=0;
while(b+c>x){
if(b==c)return ans;
if(b>c){
ll k=min((b-1)/c,(b+c-x+c-1)/c);
ans+=k,b-=k*c;
}
else{
ll k=min((c-1)/b,(b+c-x+b-1)/b);
ans+=k,a+=k*b,c-=k*b;
}
}
return ans;
}
bool check(ll w){
ll x=a,y=b,z=c,X=A,Y=B,Z=C;
jump(x,y,z,w);
jump(X,Y,Z,w);
return (X==x)&&(Y==y)&&(Z==z);
}
void cp(ll &x,ll &y)
{if(x>y)swap(x,y);return;}
signed main()
{
scanf("%lld%lld%lld",&a,&b,&c);
cp(b,c);cp(a,b);cp(b,c);c=c-b;b=b-a;
scanf("%lld%lld%lld",&A,&B,&C);
cp(B,C);cp(A,B);cp(B,C);C=C-B;B=B-A;
ll x=a,y=b,z=c,X=A,Y=B,Z=C;
jump(x,y,z,0);
jump(X,Y,Z,0);
if(x!=X||y!=Y||z!=Z)return puts("NO")&0;
ll l=0,r=min(b+c,B+C);
while(l<=r){
ll mid=(l+r)>>1;
if(check(mid))l=mid+1;
else r=mid-1;
}
x=a,y=b,z=c,X=A,Y=B,Z=C;
printf("YES\n%lld\n",jump(x,y,z,r)+jump(X,Y,Z,r));
return 0;
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构