IOI2021集训队作业125AA Baggage

有一排的格子,编号为\(-(2n-1)\)\(2n\)。一开始在\(1\)\(2n\)处交替放着\(BA\)

进行操作,每次选择相邻两个不为空的位置,将位置上的东西移到相邻两个为空的位置上。

求最少操作次数使得最终形成\(AA\dots AB\dots BB\)(连续)?

\(n\le 100\)


首先猜想上界为\(n\)

手玩了一下\(3,4,5\),感觉\(3\)是特殊情况,其它的时候似乎都满足:只会多用到\(-1,0\)这两个格子。

后面的手玩不出来于是去看了题解。

实际上当\(n\ge 8\)时,可以划归成子问题:

..BABA[]BABA
ABBABA[]B..A
ABBA..[]BBAA
...
ABBA[]..BBAA
A..A[]BBBBAA
AAAA[]BBBB

最终需要分别处理\(n=4,5,6,7\)的情况。手玩或暴力即可。


using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
int n;
void move(int x,int y){
	printf("%d to %d\n",x,y);
}
void work(int n,int o){
	if (n==4){
		move(6+o,-1+o);
		move(3+o,6+o);
		move(0+o,3+o);
		move(7+o,0+o);
	}
	else if (n==5){
		move(8+o,-1+o);
		move(3+o,8+o);
		move(6+o,3+o);
		move(0+o,6+o);
		move(9+o,0+o);
	}
	else if (n==6){
		move(10+o,-1+o);
		move(7+o,10+o);
		move(2+o,7+o);
		move(6+o,2+o);
		move(0+o,6+o);
		move(11+o,0+o);
	}
	else if (n==7){
		move(8+o,-1+o);
		move(5+o,8+o);
		move(12+o,5+o);
		move(3+o,12+o);
		move(9+o,3+o);
		move(0+o,9+o);
		move(13+o,0+o);
	}
	else{
		move(n*2-2+o,-1+o);
		move(3+o,n*2-2+o);
		work(n-4,o+4);
		move(0+o,n*2-5+o);
		move(n*2-1+o,0+o);
	}
}
int main(){
	scanf("%d",&n);
	if (n==3){
		move(2,-1);
		move(5,2);
		move(3,-3);
		return 0;
	}
	work(n,0);
	return 0;
}
posted @ 2020-11-26 08:22  jz_597  阅读(96)  评论(0编辑  收藏  举报