@P1242 新汉诺塔

题目描述

设有n个大小不等的中空圆盘,按从小到大的顺序从1到n编号。将这n个圆盘任意的迭套在三根立柱上,立柱的编号分别为A、B、C,这个状态称为初始状态。

现在要求找到一种步数最少的移动方案,使得从初始状态转变为目标状态。

移动时有如下要求:

·一次只能移一个盘;

·不允许把大盘移到小盘上面。

输入输出格式

输入格式:

 

文件第一行是状态中圆盘总数;

第二到第四行分别是初始状态中A、B、C柱上圆盘的个数和从上到下每个圆盘的编号;

第五到第七行分别是目标状态中A、B、C柱上圆盘的个数和从上到下每个圆盘的编号。

 

输出格式:

 

每行一步移动方案,格式为:move I from P to Q

最后一行输出最少的步数。

 

输入输出样例

输入样例#1: 复制
5
3 3 2 1
2 5 4
0
1 2
3 5 4 3
1 1
输出样例#1: 复制
move 1 from A to B
move 2 from A to C
move 1 from B to C
move 3 from A to B
move 1 from C to B
move 2 from C to A
move 1 from B to C
7

说明

圆盘总数≤45

 

#include <bits/stdc++.h>
using namespace std;
#define maxn 100000
typedef long long ll;
#define inf 2147483647
#define ri register int

int ans = 0;
int f1[50], f2[50];
int x, t;
int n;

void dfs(int d, int x, int y, bool k) {
  int z = 1;
  while (x == z || y == z)
    z++;
  if (x == y) {
    if (d > 1)
      dfs(d - 1, f1[d - 1], k ? f2[d - 1] : y, k);
    return;
  }
  if (d > 1)
    dfs(d - 1, f1[d - 1], z, false);
  cout << "move " << d << " from " << char(x + 'A' - 1) << " to "
       << char(y + 'A' - 1) << endl;
  ans++;
  f1[d] = y;
  if (d > 1)
    dfs(d - 1, f1[d - 1], k ? f2[d - 1] : y, k);
}

int main() {
  ios::sync_with_stdio(false);
  // freopen("test.txt", "r", stdin);
  //  freopen("outout.txt","w",stdout);
  cin >> n;
  cin >> t;
  for (int i = 1; i <= t; i++) {
    cin >> x;
    f1[x] = 1;
  }
  cin >> t;
  for (int i = 1; i <= t; i++) {
    cin >> x;
    f1[x] = 2;
  }
  cin >> t;
  for (int i = 1; i <= t; i++) {
    cin >> x;
    f1[x] = 3;
  }
  cin >> t;
  for (int i = 1; i <= t; i++) {
    cin >> x;
    f2[x] = 1;
  }
  cin >> t;
  for (int i = 1; i <= t; i++) {
    cin >> x;
    f2[x] = 2;
  }
  cin >> t;
  for (int i = 1; i <= t; i++) {
    cin >> x;
    f2[x] = 3;
  }
  dfs(n, f1[n], f2[n], true);
  cout << ans;
  return 0;
}

 

posted @ 2018-03-06 14:09  planche  阅读(157)  评论(0)    收藏  举报