[qoj4208]Flight to the Ford

维护两个集合\(S\)\(T\),表示当前最后一个询问正确/错误时可能的答案

初始\(S=[1,10^{9}]\)\(T=\empty\),每次划分\(\begin{cases}S=S_{1}\cup S_{2}\\ T=T_{1}\cup T_{2}\end{cases}\),并返回\([x\in S_{1}\cup T_{1}]\)

若收到\(1\),则\(\begin{cases}S'=S_{1}\cup T_{1}\\T'=S_{2}\end{cases}\),收到\(0\)类似,并用区间的形式存储即可

\(|S_{1}|=\lceil\frac{|S|}{2}\rceil,|T_{1}|=\lfloor\frac{|T|}{2}\rfloor\),则\(\begin{cases}|S'|\le \lceil\frac{|S|+|T|}{2}\rceil\\|T'|\le \lceil\frac{|S|}{2}\rceil\end{cases}\)

事实上,这样的策略并不一定最优,因此在\(|S|\)\(|T|\)较小时可以dp求出最优解

经计算,\(80\)轮后有\(|S|+|T|<50\),此时dp求出至多\(17\)次,总次数\(\le 97\)

#include<bits/stdc++.h>
#include "communication.h"
using namespace std;
#define fi first
#define se second
typedef pair<int,int> pii;
const int N=50;
int s,t,f[N][N],fI[N][N],fJ[N][N];
struct Node{
	int sz;
	vector<pii>v;
	Node(){
		sz=0,v.clear();
	}
	Node(int n){
		sz=n;
		v=vector<pii>{make_pair(1,n)};
	}
}S,T,S1,S2,T1,T2;
Node merge(Node x,Node y){
	Node k;
	k.sz=x.sz+y.sz;
	for(pii i:x.v)k.v.push_back(i);
	for(pii i:y.v)k.v.push_back(i);
	return k;
}
void divide(Node k,int s,Node &x,Node &y){
	x=Node(),y=Node();
	x.sz=s,y.sz=k.sz-s;
	for(pii i:k.v){
		int l=i.se-i.fi+1;
		if (!s)y.v.push_back(i);
		else{
			if (s>=l)x.v.push_back(i),s-=l;
			else{
				x.v.push_back(make_pair(i.fi,i.fi+s-1));
				y.v.push_back(make_pair(i.fi+s,i.se));
				s=0;
			}
		}
	}
}
void init(){
	memset(f,0x3f,sizeof(f));
	for(int s=0;s<N;s++)
		for(int i=0;i<=s;i++){
			int j=s-i;
			if (s<3){f[i][j]=0;continue;}
			for(int I=0;I<=i;I++)
				for(int J=0;J<=j;J++){
					if (f[i][j]>max(f[I+J][i-I],f[i+j-I-J][I])+1){
						fI[i][j]=I,fJ[i][j]=J;
						f[i][j]=max(f[I+J][i-I],f[i+j-I-J][I])+1;
					}
				}
		}
}
void encode(int n,int x){
	init(),S=Node(n),T=Node();
	while (S.sz+T.sz>2){
		if (S.sz+T.sz<N)s=fI[S.sz][T.sz],t=fJ[S.sz][T.sz];
		else s=(S.sz+1>>1),t=(T.sz>>1);
		divide(S,s,S1,S2),divide(T,t,T1,T2);
		bool flag=0;
		for(pii i:S1.v)
			if ((i.fi<=x)&&(x<=i.se))flag=1;
		for(pii i:T1.v)
			if ((i.fi<=x)&&(x<=i.se))flag=1;
		if (send(flag))S=merge(S1,T1),T=S2;
		else S=merge(S2,T2),T=S1;
	}
}
pair<int,int> decode(int n){
	init(),S=Node(n),T=Node();
	while (S.sz+T.sz>2){
		if (S.sz+T.sz<N)s=fI[S.sz][T.sz],t=fJ[S.sz][T.sz];
		else s=(S.sz+1>>1),t=(T.sz>>1);
		divide(S,s,S1,S2),divide(T,t,T1,T2);
		if (receive())S=merge(S1,T1),T=S2;
		else S=merge(S2,T2),T=S1;
	}
	int x=0,y=0;
	for(pii i:S.v)
		for(int j=i.fi;j<=i.se;j++){
			if (!x)x=j;
			else y=j;
		}
	for(pii i:T.v)
		for(int j=i.fi;j<=i.se;j++){
			if (!x)x=j;
			else y=j;
		}
	if (!y)y=x;
	return make_pair(x,y);
}
posted @ 2023-01-27 19:26  PYWBKTDA  阅读(34)  评论(0编辑  收藏  举报