这题wqy讲过,完全不懂。
事实上,对于
∀
n
≥
3
\forall n\geq 3
∀n≥3,下面我们都可以给出一个
n
n
n步的构造。这显然是一个下界:考虑定义一个局面的势能是
i
i
i和
i
+
1
i+1
i+1都有箱子且种类不同的个数,初始局面势能是
2
n
−
1
2n-1
2n−1,最终局面势能是
1
1
1,每次操作至多减少
2
2
2的势能,因此至少要
n
n
n步。
如何构造呢?
对于
3
≤
n
≤
7
3\leq n\leq 7
3≤n≤7,我们都可以手构或搜索出一个
n
n
n步的解。事实上,对于
n
=
4
∼
7
n=4\sim 7
n=4∼7,有一个
n
n
n步的解只需要在前面有
2
2
2个空,最后效果相当于前移
2
2
2个。
对于
n
≥
8
n\geq 8
n≥8,我们有下面的方式来变为
n
−
4
n-4
n−4的情况:(
_
\_
_代表空)
_
_
B
A
B
A
[
B
A
…
B
A
]
B
A
B
A
A
B
B
A
B
A
[
B
A
…
B
A
]
B
_
_
A
A
B
B
A
_
_
[
B
A
…
B
A
]
B
B
A
A
⋯
A
B
B
A
[
A
…
A
B
…
B
]
_
_
B
B
A
A
A
_
_
A
[
A
…
A
B
…
B
]
B
B
B
B
A
A
A
A
A
A
[
A
…
A
B
…
B
]
B
B
B
B
_
_
\_\_BABA[BA\ldots BA]BABA \\ ABBABA[BA\ldots BA]B\_\_A \\ ABBA\_\_[BA\ldots BA]BBAA \\ \cdots \\ ABBA[A\ldots AB\ldots B]\_\_BBAA \\ A\_\_A[A\ldots AB\ldots B]BBBBAA \\ AAAA[A\ldots AB\ldots B]BBBB\_\_ \\
__BABA[BA…BA]BABAABBABA[BA…BA]B__AABBA__[BA…BA]BBAA⋯ABBA[A…AB…B]__BBAAA__A[A…AB…B]BBBBAAAAAA[A…AB…B]BBBB__
这样我们就对所有的
n
≥
3
n\geq 3
n≥3构造出了一个
n
n
n步的解。时间复杂度为
O
(
n
)
\mathcal O(n)
O(n)。
#include <bits/stdc++.h>
using namespace std;
inline void move(int x,int y) {
printf("%d to %d\n",x,y);
}
void solve3(int rb) {
move(rb-4,rb-7);
move(rb-1,rb-4);
move(rb-3,rb-9);
}
void solve4(int rb) {
move(rb-2,rb-9);
move(rb-5,rb-2);
move(rb-8,rb-5);
move(rb-1,rb-8);
}
void solve5(int rb) {
move(rb-2,rb-11);
move(rb-7,rb-2);
move(rb-4,rb-7);
move(rb-10,rb-4);
move(rb-1,rb-10);
}
void solve6(int rb) {
move(rb-2,rb-13);
move(rb-5,rb-2);
move(rb-10,rb-5);
move(rb-6,rb-10);
move(rb-12,rb-6);
move(rb-1,rb-12);
}
void solve7(int rb) {
move(rb-6,rb-15);
move(rb-9,rb-6);
move(rb-2,rb-9);
move(rb-11,rb-2);
move(rb-5,rb-11);
move(rb-14,rb-5);
move(rb-1,rb-14);
}
void solve(int n,int rb) {
if (n==4) {
solve4(rb);
return;
}
if (n==5) {
solve5(rb);
return;
}
if (n==6) {
solve6(rb);
return;
}
if (n==7) {
solve7(rb);
return;
}
move(rb-2,rb-2*n-1);
move(rb-2*n+3,rb-2);
solve(n-4,rb-4);
move(rb-2*n,rb-5);
move(rb-1,rb-2*n);
}
int main() {
int n;
scanf("%d",&n);
if (n==3) solve3(2*n);
else solve(n,2*n);
return 0;
}