Codeforces gym 101221 A

这篇博客介绍了如何解决Codeforces Gym 101221 A问题。针对n>=3的情况,提出了一种构造n步解决方案的方法,初始和最终局面的势能分析表明至少需要n步。对于3≤n≤7,可以手动构造或搜索解,而n≥8时,通过特定模式将问题转换为n-4的情况,提供了一个时间复杂度为O(n)的构造过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这题wqy讲过,完全不懂。
事实上,对于 ∀ n ≥ 3 \forall n\geq 3 n3,下面我们都可以给出一个 n n n步的构造。这显然是一个下界:考虑定义一个局面的势能是 i i i i + 1 i+1 i+1都有箱子且种类不同的个数,初始局面势能是 2 n − 1 2n-1 2n1,最终局面势能是 1 1 1,每次操作至多减少 2 2 2的势能,因此至少要 n n n步。
如何构造呢?
对于 3 ≤ n ≤ 7 3\leq n\leq 7 3n7,我们都可以手构或搜索出一个 n n n步的解。事实上,对于 n = 4 ∼ 7 n=4\sim 7 n=47,有一个 n n n步的解只需要在前面有 2 2 2个空,最后效果相当于前移 2 2 2个。
对于 n ≥ 8 n\geq 8 n8,我们有下面的方式来变为 n − 4 n-4 n4的情况:( _ \_ _代表空)
_ _ 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[BABA]BABAABBABA[BABA]B__AABBA__[BABA]BBAAABBA[AABB]__BBAAA__A[AABB]BBBBAAAAAA[AABB]BBBB__
这样我们就对所有的 n ≥ 3 n\geq 3 n3构造出了一个 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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值