URAL 2029 Towers of Hanoi Strike Back 汉诺塔,从初始状态到任意给出状态需要的次数

F - Towers of Hanoi Strike Back

Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d
& %I64u

Submit Status Practice URAL
2029

Description

The Tower of Hanoi puzzle was invented by French mathematician édouard Lucas in the second half of the 19th century. Here is its formulation.

There are three rods, denoted by the letters A, B, and C, and n disks of different integer sizes from 1 to  n. Initially the disks are stacked

in ascending order of size on rod A, the smallest at the top, thus making a conical shape. Each move consists of taking the upper disk

from one of the rods and placing it on top of the stack at another rod, with the following condition satisfied: no disk may be placed on

top of a smaller disk. The objective of the puzzle is to move the entire stack to rod B in the smallest possible number of moves. The auxiliary rod C can be used in the process.

The state of the rods at each time can be described by a string of n letters A, B, and C: the letter at position i denotes the rod where the disk of size  i is at that time. For example, the initial
state is given by the string containing letters A only, and the final state is described by the string consisting of letters B. The converse is also true: any such string uniquely describes a valid state of the rods, because the order of disks on a rod is
uniquely defined by their size.

Imagine that you are required to pass from the initial state, where all the disks are on rod A, to some prescribed state. What is the

smallest number of moves in which this can be done?

Input

The first line contains an integer n (1 ≤ n ≤ 50).

In the second line you are given n uppercase English letters A, B, C, which describe the final state.

Output

If it is impossible to obtain the final state from the initial state, output “-1” (without quotation marks). Otherwise, output the minimum number of moves. It is guaranteed that, if there is an answer, it does not exceed 10 18.

Sample Input

input output
1
A
0
4
BBBB
15
7
BCCBABC
95

Source

UESTC 2016 Summer Training #17 Div.2

URAL 2029

My Solution

汉诺塔, 得到从初始状态到任意给出状态需要的次数的O(n)算法, 记结论吧??

比如要得到 BCCBABC

则对于原始的AAAAAAA

第一次令 res = ‘A‘, 然后对于给出的state从大的往小的开始扫, 当前是C所以第7个A变成C, ans += 2^(7 - 1), 然后res = ‘B‘, 也就是剩余的移到B上,

然后第二个需要到B上,且已经在B上, 所以不用管, 继续访问下一位

然后是A, 这个时候把当期大小的盘在B上, 所以移到A上, ans += 2^(5 - 1), 然后res = ’C‘, 剩余的全都移到第三个柱子’C‘上。

依次这样下去就好了

比较当前盘需要的在哪个柱子上和当前在那个柱子上, 如果恰好在则直接访问下一个盘子, 如果不是则把该盘移过去 ans += 2^i ( 0 <= i < n), 剩余的盘全移到第三个柱子上

把AAAAAAA.....从右往左, 全部变成state, 就可以得到答案了

此外注意点

用 1<<i得到 2^i次时,如果i很大, 比如50, 这个时候integer 溢出了, 用 (LL)(1<<50)也达不到效果, 还是得到数据丢失的integer大小的数,

然后用了cmath里的那个不大靠谱的pow, ans += (LL)pow(2, i);就可以得到 64位的整数了

复杂度 O(n)

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long LL;
const int maxn = 1e2 + 8;

char val[maxn];

int main()
{
    #ifdef LOCAL
    freopen("a.txt", "r", stdin);
    //freopen("b.txt", "w", stdout);
    int T = 4;
    while(T--){
    #endif // LOCAL
    LL n, ans = 0;
    char res = 'A';
    scanf("%I64d", &n);
    scanf("%s", val);

    for(LL i = n - 1; i >= 0; i--){
        if(res != val[i]){
            ans += (LL)pow(2, i);
            //cout<<ans<<endl;
            if(res == 'A'){
                if(val[i] == 'B') res = 'C';
                else res = 'B';
            }
            else if(res == 'B'){
                if(val[i] == 'A') res = 'C';
                else res = 'A';
            }
            else if(res == 'C'){
                if(val[i] == 'A') res = 'B';
                else res = 'A';
            }
        }
        if(ans < 0 || ans > 1e18) break;
    }
    if(ans < 0 || ans > 1e18) printf("-1");
    printf("%I64d", ans);

    #ifdef LOCAL
    printf("\n");
    }
    #endif // LOCAL
    return 0;
}

Thank you!

------from ProLights

时间: 2024-08-13 08:51:41

URAL 2029 Towers of Hanoi Strike Back 汉诺塔,从初始状态到任意给出状态需要的次数的相关文章

ural 2029 Towers of Hanoi Strike Back (数学找规律)

ural 2029 Towers of Hanoi Strike Back 链接:http://acm.timus.ru/problem.aspx?space=1&num=2029 题意:汉诺塔问题,给定一串只有(A, B, C)的字符串(A代表在第一根柱子,B代表在第二根柱子,C代表在第三根柱子),从前往后代表盘子的大小,第 i 个字母代表di i 个盘子在某个柱子上.问移动给定字母状态的盘子最少需要多少步. 思路:首先,从后往前看(最大的盘子),如果不在当前柱子上,那么移动到目标柱子需要 2

python算法-汉诺塔问题

汉诺塔问题   初始状态: 思考:当盘子的个数是3的时候,大家写出移动顺序 移动的步骤: 3个盘子,从a到c 1.前面两个盘子,从a到b 1)把前面一个盘子,从a到c a->c 2)把第二个盘子,从a到b a->b 3)把c上的盘子,从c到b c->b 2.最后一个盘子,从a到c a->c 3.把b上的两个盘子,从b到c 1)把前面一个盘子,从b到a b->a 2)把第二个盘子,从b到c b->c 3)把a上的盘子,从a到c a->c 总结: n个盘子,从a到c

[CareerCup] 3.4 Towers of Hanoi 汉诺塔

3.4 In the classic problem of the Towers of Hanoi, you have 3 towers and N disks of different sizes which can slide onto any tower. The puzzle starts with disks sorted in ascending order of size from top to bottom (i.e., each disk sits on top of an e

Acdream 1219 The Towers of Hanoi Revisited(递归汉诺塔问题)

传送门 The Towers of Hanoi Revisited Special Judge Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) Submit Statistic Next Problem Problem Description You all must know the puzzle named "The Towers of Hanoi". The puzz

HT for Web 3D游戏设计设计--汉诺塔(Towers of Hanoi)

在这里我们将构造一个基于HT for Web的HTML5+JavaScript来实现汉诺塔游戏. 汉诺塔的游戏规则及递归算法分析请参考http://en.wikipedia.org/wiki/Tower_of_Hanoi. 知道了汉诺塔的规则和算法,现在就开始创建元素.用HT for Web(http://www.hightopo.com)现有的3D模板创建底盘和3根柱子不是问题,问题是要创建若干个中空的圆盘.一开始的想法是:创建一个圆柱体,将圆柱体的上下两端隐藏,设置柱面的宽度来实现圆盘的效果

汉诺塔-Hanoi

1. 问题来源: 汉诺塔(河内塔)问题是印度的一个古老的传说. 法国数学家爱德华·卢卡斯曾编写过一个印度的古老传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针.印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔.不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片:一次只移动一片,不管在哪根针上,小片必须在大片上面.僧侣们预言,当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消灭,而梵塔.

汉诺塔问题(Hanoi)的C++代码实现

1 #include <iostream> 2 using namespace std; 3 //第一个塔为初始塔,第二个塔为中转塔,第三个塔为目标塔 4 5 int i = 1; //记录步数 6 void move(int n,char from,char to) //将编号为N的盘子由from塔转移到to塔 7 { 8 cout<<"第"<<i++<<"步:将"<<n<<"号盘子

Hanoi(汉诺)塔问题(C实现)

Hanoi(汉诺)塔问题.这是一个经典的数学问题:古代有一个梵塔,塔内有3个座A,B,C,开始时A座上有64个盘子,盘子大小不等,大的在下,小的在上.有一个老和尚想把这64个盘子从A座移到C座,但每次只允许移动一个盘子,且在移动过程中在3个座上都始终保持大盘在下,小盘在上.在移动过程中可以利用C座,给出移动过程. #include<stdio.h> #include<stdlib.h> void move(char ch1,char ch2) {  printf("%c-

汉诺塔 Hanoi Tower

一个古老的印度传说:在世界的中心贝拿勒斯的圣庙里,一块黄铜板上插着三支宝石针.印度教的主神梵天在创造世界的时候,在其中一根针上从下到上穿好了由大到小的64片金片,这就是所谓的汉诺塔(Hanoi Tower).不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片:一次只移动一片,不管在哪根针上,小片必须在大片上面. 僧侣们预言,当所有的金片从梵天穿好的金片上移到另一根针上时,世界末日就会来临,而梵塔.寺庙和众生也会随之灭亡...... 故事不多说了,汉诺塔是递归思想的典型应用,上代码: 1 #i