BZOJ4072[Wf2014] baggage

原题链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4072

baggage

Description

给定一排长度为4n的格子,编号从-2n+1到2n。

每个编号为正的格子中有一个物品,其中每个编号为奇数的格子中有一个B类物品,编号为偶数的格子中有一个A类物品。

例如:当n=4时初始状态如下图所示:

附图.png

你只能进行一种操作:选择某两个相邻的格子,要求这两个格子中都有物品,然后移动到另外两个相邻的空格子中,不能改变两个格子的相对位置。

要求进行最少的操作使得所有物品以AAA…ABBB…B(n个A和n个B)的形式排列在一起。

Input

输入数据包含一行一个正整数n,含义如题面中所示

Output

输出一个最短的满足要求的移动序列。

每个操作的格式如下:
x to y

含义为将x和x+1两个格子中的物品移动到y和y+1两个位置。

扫描二维码关注公众号,回复: 2605531 查看本文章

如果有多组方案可以达到要求,你可以输出任意一组。

Sample Input

5

Sample Output

8 to -1
3 to 8
6 to 3
0 to 6
9 to 0

题解

先运用人类的智慧,手动处理 3 7 的解,设 ( B A ) 表示若干个 B A 摆放成的形如 B A B A B A B A 的序列; ( A B ) 表示左半边为 A ,右半边为 B 的形如 A A A A B B B B 的序列,发现除了 n = 3 的情况,其他情况的变化是有规律的:

_   _ ( B A ) ( A B ) _   _

意思说, 4 7 的变化都只会用到最左边的两个多余的空格子,其他空格子都不会用。

再考虑 n > 7 的情况,我们可以做这样的变换:

_   _ B A B A ( B A ) B A B A A B B A B A ( B A ) B _   _ A A B B A _   _ ( B A ) B B A A

这样,我们就留出了中间的序列从 ( B A ) 变到 ( A B ) 的两个格子,然后我们就可以递归下去,把中间的序列变成 ( A B ) _   _ ,再接着改最外面的:

A B B A ( A B ) _   _ B B A A A _   _ A ( A B ) B B B B A A A A A A ( A B ) B B B B _   _

这样我们就成功将整个序列合并成了 ( A B )

代码
#include <bits/stdc++.h>
#define p(x,y) printf("%d to %d\n",x,y)
int n;
void in(){scanf("%d",&n);}
void ac(int l,int r){
    if(r-l+1==6){p(2,-1),p(5,2),p(3,-3);return;}
    if(r-l+1==8){p(l+5,l-2),p(l+2,l+5),p(l-1,l+2),p(l+6,l-1);return;}
    if(r-l+1==10){p(l+7,l-2),p(l+2,l+7),p(l+5,l+2),p(l-1,l+5),p(l+8,l-1);return;}
    if(r-l+1==12){p(l+9,l-2),p(l+6,l+9),p(l+1,l+6),p(l+5,l+1),p(l-1,l+5),p(l+10,l-1);return;}
    if(r-l+1==14){p(l+7,l-2),p(l+4,l+7),p(l+11,l+4),p(l+2,l+11),p(l+8,l+2),p(l-1,l+8),p(l+12,l-1);return;}
    p(r-2,l-2),p(l+2,r-2);ac(l+4,r-4);p(l-1,r-5),p(r-1,l-1);
}
int main(){in();ac(1,n<<1);}

猜你喜欢

转载自blog.csdn.net/ShadyPi/article/details/81285817