题解 逃离藏宝洞

传送门

首先发现(除了第一次)每个点一定知道是从哪边过来的
那么一次询问至少能让深度上升 1
再考虑怎么让深度多上升一些
那么多走几步之后可以通过始/终深度得到 lca 的深度
那么走 \(k\) 步期望上升 \(\frac{1}{2}\times 1+\frac{1}{4}\times 2+\frac{1}{8}\times 3+\cdots \approx2\)
那么可以用大约 \(\frac{d}{2}\) 步回到地面

点击查看代码
#include "escape.h"
#include <bits/stdc++.h>
using namespace std;
#define N 1000010

int k=40;
int sta[N], rest[3][3], top;
random_device seed;
mt19937 rnd(seed());

void solve(int dep, int back) {
	// cout<<"solve: "<<dep<<' '<<back<<endl;
	int dir[2], now; top=0;
	sta[0]=back;
	for (int i=1; i<=k; ++i) {
		now=0;
		for (int j=0; j<3; ++j) if (j!=sta[top]) dir[now++]=j;
		move(sta[++top]=dir[rnd()&1]);
	}
	int d=query();
	if (d==dep+k) solve(d, sta[top]);
	else {
		int t=(k-(dep-d))/2;
		while (top>t) move(sta[top--]);
		int v=rest[sta[top]][sta[top+1]];
		move(v);
		solve(dep+t+1, v);
	}
}

void escape(int lm, int lq) {
	if (lm==3002) k=1;
	rest[0][1]=rest[1][0]=2;
	rest[1][2]=rest[2][1]=0;
	rest[0][2]=rest[2][0]=1;
	int d=query();
	move(0);
	if (query()>d) solve(d+1, 0);
	move(0);
	move(1);
	if (query()>d) solve(d+1, 1);
	move(1);
	move(2);
	solve(d+1, 2);
}
posted @ 2022-03-29 14:36  Administrator-09  阅读(2)  评论(0编辑  收藏  举报