首页 > 其他分享 >P1852 跳跳棋

P1852 跳跳棋

时间:2023-11-21 21:02:22浏览次数:21  
标签:node ch return int db 跳棋 read P1852

一个粗略的想法是对于所有状态 \((a,b,c)\) 之间连边,求出图之后跑最短路。

首先钦定 \(a\le b\le c\), 考虑转移有哪些情况:要么从两边到中间距离小的一个往中间跳缩小范围,要么中间往两边跳扩大范围。我们定义第一种到的状态为父亲,第二种到的状态为左右儿子,不难发现整个图是一棵二叉树森林。跳的过程和欧几里得算法十分类似,跳的次数实际不是很大。

于是我们直接暴力跳到根,判断是否在一棵树中,深度是好求的。LCA我们可以跳到同一高度之后二分/倍增得到。

#include <bits/stdc++.h>

using namespace std;

#define int long long

inline int read() {
	register int s = 0, f = 1; register char ch = getchar();
	while (!isdigit(ch)) f = (ch == '-' ? -1 : 1), ch = getchar();
	while (isdigit(ch)) s = (s * 10) + (ch & 15), ch = getchar();
	return s * f;
}

struct node {
	int x, y, z;
	inline node() { }
	inline node(int X, int Y, int Z) : x(X), y(Y), z(Z) { }
	inline void init() {
		if (x > y) swap(x, y);
		if (x > z) swap(x, z);
		if (y > z) swap(y, z);
	}
};

inline bool operator == (node a, node b) {
	return a.x == b.x && a.y == b.y && a.z == b.z;
}

inline pair<node, int> jump(node x, int k) {
	int p = k;
	while (k) {
		int n = x.y - x.x, m = x.z - x.y;
		if (n == m) return make_pair(x, p - k);
		if (n < m) {
			int d = min(k, (m - 1) / n);
			x.x += d * n; x.y += d * n;
			k -= d;
		} else {
			int d = min(k, (n - 1) / m);
			x.y -= d * m; x.z -= d * m;
			k -= d;
		}
	} return make_pair(x, p - k);
}

signed main() {
	node a, b;
	a.x = read(); a.y = read(); a.z = read(); a.init();
	b.x = read(); b.y = read(); b.z = read(); b.init();
	node ta, tb; int da, db;
	tie(ta, da) = jump(a, 1e9); tie(tb, db) = jump(b, 1e9);
	if (!(ta == tb)) { puts("NO"); return 0; }
	if (da < db) { swap(da, db); swap(a, b); }
	a = jump(a, da - db).first;
	if (a == b) { puts("YES"); printf("%lld\n", da - db); return 0; }
	for (int i = 30; ~i; --i) {
		if (!(jump(a, (1 << i)).first == jump(b, 1 << i).first)) {
			a = jump(a, (1 << i)).first;
			b = jump(b, (1 << i)).first;
		}
	} if (!(a == b)) a = jump(a, 1).first;
	int d; tie(a, d) = jump(a, 1e9);
	puts("YES"); printf("%lld\n", da + db - 2 * d);
	return 0;
}

标签:node,ch,return,int,db,跳棋,read,P1852
From: https://www.cnblogs.com/wwlwakioi/p/17847574.html

相关文章

  • 数据结构与算法 #18 下跳棋,极富想象力的同向双指针模拟
    ⭐️本文已收录到AndroidFamily,技术和职场问题,请关注公众号[彭旭锐]和[BaguTreePro]知识星球提问。学习数据结构与算法的关键在于掌握问题背后的算法思维框架,你的思考越抽象,它能覆盖的问题域就越广,理解难度也更复杂。在这个专栏里,小彭将基于Java/Kotlin语言,为你分享常......
  • 我制作的一个简单的跳棋小游戏
    我用虚幻5制作的简单的3D跳棋小游戏,可以本地多人对战以及和AI对战,已经上传到了itch.io。目前跳棋功能已经完善,其他棋类游戏留待以后加入。支持中英文。支持两种棋盘,支持经典玻璃弹珠和其他不透明弹珠。游戏网页链接......
  • P1852 舰长的礼物
    #include<iostream>#include<vector>#include<algorithm>#include<numeric>usingnamespacestd;constdoubleEPS=1e-8;intmain(){intn,k;cin>>n>>k;//读入护心毛长度并求出平均值vector<double>......
  • 「BZOJ2144」跳跳棋-题解
    「BZOJ2144」跳跳棋个人评价挺好的一道题,难点在于想到树这个结构和建树1题面跳跳棋是在一条数轴上进行的。棋子只能摆在整点上。每个点不能摆超过一个棋子。我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置。我们要通过最少的跳动把他们的位置移......
  • 类似于八皇后的国际跳棋问题
    题目描述检查一个如下的6x6的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。上面的布局可以用序列246135来描述,第i个数字表示在第i行的相应位置有一个棋子,如下:行号123456列号2461......
  • 解题报告-跳跳棋
    跳跳棋是在一条数轴上进行的。棋子只能摆在整点上。每个点不能摆超过一个棋子。我们用跳跳棋来做一个简单的游戏:棋盘上有三颗棋子,分别在\(a,b,c\)这三个位置。我们要通过......