首页 > 其他分享 >P1242 新汉诺塔

P1242 新汉诺塔

时间:2023-02-07 19:23:03浏览次数:41  
标签:P1242 tar int move pos 圆盘 汉诺塔 圆片

新汉诺塔

题目描述

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

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

移动时有如下要求:

  • 一次只能移一个盘;
  • 不允许把大盘移到小盘上面。

输入格式

第一行一个整数,状态中圆盘总数 n。

接下来三行每行若干个整数,分别代表初始状态下 A , B , C 柱子上的圆盘从上到下的编号,如果只有一个数 0 就代表这根柱子上没有数。

接下来三行每行若干个整数,分别代表目标状态下 A , B , C 柱子上的圆盘从上到下的编号,如果只有一个数 0 就代表这根柱子上没有数。

输出格式

若干行每行一个字符串,格式为 move I from P to Q ,代表一个移动的操作。

接下来一行一个整数,代表从初始状态到目标状态的最少步数。

样例 #1

样例输入 #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

提示

数据规模与约定

对于 100% 的数据,1 <= n <= 45 ,1 <= 每个圆盘的编号 <= n 。

每行的圆盘描述是从下到上的圆盘编号。

分析

广大人民群众所喜闻乐见的汉诺塔。

我的思路是这样的:将某个圆片v从a移到b,必须要先将所有比v小的圆片从a、b移到c,所以从v-1开始从大到小依次把所有圆片移到c上,这就可以抽象出递归过程了:

void dfs(int v, int from, int to, int by) { // 将圆片v从from移到to
    if (from == to)return;
    for (int i = v - 1; i > 0; i--) { // 先将所有比v小的圆片移到by
        dfs(i, pos[i], by, 3 - pos[i] - by);
    }
    mov(v, from, to);
}

易证这样得到的是最简方案。

提交答案

完整代码:

#include<iostream>

using namespace std;

int stack[3][66];
int p[3];
int tar[66];
int pos[66];
int ans = 0;

void mov(int v, int from, int to) {
    cout << "move " << v << " from " << (char) (from + 'A') << " to " << (char) (to + 'A') << endl;
    p[from]--;
    stack[to][p[to]++] = v;
    pos[v] = to;
    ans++;
}

void dfs(int v, int from, int to, int by) { // 将圆片v从from移到to
    if (from == to)return;
    for (int i = v - 1; i > 0; i--) { // 先将所有比v小的圆片移到by
        dfs(i, pos[i], by, 3 - pos[i] - by);
    }
    mov(v, from, to);
}

int main() {
    ios::sync_with_stdio(false);
    int n, m, t;
    cin >> n;
    for (int i = 0; i < 3; i++) {
        cin >> m;
        p[i] = m + 1;
        stack[i][0] = 66;
        for (int j = 1; j <= m; j++) {
            cin >> stack[i][j];
            pos[stack[i][j]] = i;
        }
    }
    for (int i = 0; i < 3; i++) {
        cin >> m;
        for (int j = 0; j < m; j++) {
            cin >> t;
            tar[t] = i;
        }
    }
    for (int i = n; i > 0; i--) {
        if (pos[i] != tar[i]) {
            dfs(i, pos[i], tar[i], 3 - pos[i] - tar[i]);
        }
    }
    cout << ans;
}

标签:P1242,tar,int,move,pos,圆盘,汉诺塔,圆片
From: https://www.cnblogs.com/bujidao1128/p/17099549.html

相关文章

  • P4285 [SHOI2008]汉诺塔
    [SHOI2008]汉诺塔题目描述汉诺塔由三根柱子(分别用A、B、C表示)和n个大小互不相同的空心盘子组成。一开始n个盘子都摞在柱子A上,大的在下面,小的在上面,形成了一个塔状的锥形......
  • 汉诺塔系列
    汉诺塔1:a上面的盘子借助b到c公式:n=2^n-1;#include<iostream>#include<cstdio>usingnamespacestd;voidf(intn,charA,charB,charC){if(n>=1){f(n......
  • #yyds干货盘点# LeetCode程序员面试金典:汉诺塔问题
    题目:在经典汉诺塔问题中,有3根柱子及N个不同大小的穿孔圆盘,盘子可以滑入任意一根柱子。一开始,所有盘子自上而下按升序依次套在第一根柱子上(即每一个盘子只能放在更大的......
  • 关于汉诺塔问题一些体会(大学复健的第一篇随笔)
    递归条件相同结构的子问题————考察子问题与当前问题的关系存在可以单独计算基础结构所以我们考察第一个条件,汉诺塔的移动方式第一步将所有上层移动到一......
  • 汉诺塔(经典递归问题)及个人目前的一些感想与心得
    汉诺塔(TowerofHanoi),又称河内塔,是一个源于​​​​印度​​​​​古老传说的​​​​益智玩具​​​​。​​​​大梵天​​​​创造世界的时候做了三根金刚石柱子,在一根柱......
  • 递归:汉诺塔问题
    问题背景汉诺塔问题源自印度一个古老的传说,印度教的“创造之神”梵天创造世界时做了3根金刚石柱,其中的一根柱子上按照从小到大的顺序摞着64个黄金圆盘。梵天命令一个叫......
  • 如何使用C语言实现汉诺塔
    现有3个柱子A、B、C,有n个圆盘在A柱上,要实现n个圆盘要从A柱从大到小移动到C柱。思路:先将n-1个圆盘移动到B柱上,然后将最后一个圆盘移动到C柱上,最后将B柱上的n-1个圆盘移动到C......
  • CP1242. 将字符数组中第m个字符开始的n个字符逆序存放
    只是打卡:#include<stdio.h>#include<ctype.h>#include<string.h>#include<math.h>inty=0;voidinverse(charstr[1000],charb[1000],intm,intn,intk);int......
  • 面试题08. 06 汉诺塔
    问题链接https://leetcode.cn/problems/hanota-lcci/description/解题思路首先我们要定义递归函数。汉诺塔问题是典型的递归问题(缩小规模,小规模问题是大规模问题的子集),......
  • 在见奇怪的汉诺塔
    题目连接:https://www.acwing.com/activity/content/problem/content/330/二刷,利用递推的思想来解决问题code:1//递推、dp思想2#include<bits/stdc++.h>3using......