有一排的格子,编号为(-(2n-1))到(2n)。一开始在(1)到(2n)处交替放着(BA)。
进行操作,每次选择相邻两个不为空的位置,将位置上的东西移到相邻两个为空的位置上。
求最少操作次数使得最终形成(AAdots ABdots BB)(连续)?
(nle 100)
首先猜想上界为(n)。
手玩了一下(3,4,5),感觉(3)是特殊情况,其它的时候似乎都满足:只会多用到(-1,0)这两个格子。
后面的手玩不出来于是去看了题解。
实际上当(nge 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
",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;
}