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;
}