HDU 2184 汉诺塔VIII

来源:互联网 发布:java设计界面美观 编辑:程序博客网 时间:2024/05/21 17:33

汉诺塔经典模型的一个问题,根本思想是基于汉诺塔递归模拟写法的剪枝统计,此题就是给你盘子的个数n,问你步数为m时,三个柱子上的盘子的分布情况?

解题思路:在汉诺塔递归的DFS中讨论剩下m的步数,然后选择进入不同的递归层数,并模拟盘子的移动,整体复杂度为:O(n^2)

递归代码写之纠结,详见代码:

/*  * File:   main.cpp * Author: hit-acm * * Created on 2012年8月27日, 下午7:40 */#include <iostream>#include <cstring>#include <algorithm>#include <cstdio>#include <cmath>using namespace std;const int MAXN = 65;int a[3][MAXN];int size[3];unsigned long long ans[MAXN];void init() {    ans[0] = 0;    for (int i = 1; i < MAXN; i++) {        ans[i] = 2 * ans[i - 1] + 1;    }}void DFS(int n, unsigned long long m, int s, int e, int mid) {    if (n <= 0) {        return;    }    if (m < ans[n - 1]) {        DFS(n - 1, m, s, mid, e);    } else if (m == ans[n - 1]) {        size[s] -= n - 1;        for (int i = 1; i < n; i++) {            a[mid][size[mid]++] = a[s][size[s] + i - 1];        }    } else {        a[e][size[e]++] = n;        size[s] -= n;        for (int i = 1; i < n; i++) {            a[mid][size[mid]++] = a[s][size[s] + i];        }        DFS(n - 1, m - ans[n - 1] - 1, mid, e, s);    }}void get_result(int n, unsigned long long m) {    for (int i = 0; i < 3; i++) {        size[i] = 0;    }    size[0] = n;    for (int i = 0; i < n; i++) {        a[0][i] = n - i;    }    DFS(n, m, 0, 2, 1);    for (int i = 0; i < 3; i++) {        printf("%d", size[i]);        for (int j = 0; j < size[i]; j++) {            printf(" ");            printf("%d", a[i][j]);        }        putchar('\n');    }}int main() {    int T;    int n;    unsigned long long m;    init();    scanf("%d", &T);    while (T--) {        scanf("%d%llu", &n, &m);        get_result(n, m);    }    return 0;}



原创粉丝点击