URAL

来源:互联网 发布:simcms二手车源码 编辑:程序博客网 时间:2024/06/13 00:46
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.
Example
input output

1A04BBBB157BCCBABC95

很有意思的一个汉诺塔问题,ABC表示最开始的三根柱子,给你一个由ABC组成的字符串S,S[i]表示第i小的盘在哪根柱子上。问你从最初的所有盘在A柱摆成这种形式需要多少移动次数。
已知结论:第从上往下第n个盘从A借助B放到C上需要2^(n-1)次移动。
大体思路:比如要得到 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, 就可以得到答案了。———by ProLightsfxjh

#include <bits/stdc++.h>using namespace std;int main(){    string str;    int n;    while(cin >> n)    {        cin >> str;        long long int ans = 0l, cnt = 1l;        string now = "A";        cnt <<= (n - 1);        for(int i = n - 1; i >= 0; i--)        {            if(now == "A")            {                if(str[i] == 'B')                {                    now = "C";                }                else if(str[i] == 'C')                {                    now = "B";                }            }            else if(now == "B")            {                if(str[i] == 'A')                {                    now = "C";                }                else if(str[i] == 'C')                {                    now = "A";                }            }            else if(now == "C")            {                if(str[i] == 'A')                {                    now = "B";                }                else if(str[i] == 'B')                {                    now = "A";                }            }            if(now[0] != str[i])            {                ans += cnt;            }            cnt >>= 1;        }        printf("%lld\n", ans);    }    return 0;}
原创粉丝点击