加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

POJ PKU 3601 Hanoi

(2010-04-15 21:20:02)
标签:

poj

pku

3601

it

分类: 杂题

题目描述:Hanoi塔问题,只不过有一些盘子的大小是一样的,问你最少的步骤数目。

解题报告:

假设有n种盘子,x[i]为第i种盘子的数目, 0 <= i <= n - 1.

我们先计算出相同的盘子不考虑顺寻的情况,记作a[i],表示有i种盘子所需的步骤数目(不考虑第i种顺序)。

容易知道,a[0] = x[0],只有一种时,直接把这种的所有盘子移动到目标轴上。

a[i] = 2 * a[i - 1] x[i].

说明:如果从A到C轴,借助B轴,i种盘子,要先把i - 1种移动到 B, 需要a[i - 1],然后把第i种移动到C,需要x[i],然后再把i - 1种从B移动到C,需要a[i - 1]

所以得到a[i] = 2 * a[i - 1] x[i].

 

但是题目是需要考虑相同盘子的顺序的,这里记作b[i],为移动i种盘子考虑顺序需要的步骤。

b[0] = 2 * (x[0] - 1) 1.

说明:把x[0] - 1个移动到辅助轴,这时这x[0] - 1个盘子的顺序颠倒了,然后把第x[0]中最后一个移动到目标轴,然后把辅助轴上的移动回来,再次颠倒,恢复顺序,得到b[0] = 2 * (x[0] - 1) 1。

对于b[i],

如果x[i] == 1,那么第i种就不需要考虑顺序(只有一种),所以b[i] = a[i]

否则,第i种要调动2次,保证顺序不变。

还是从A到C轴,借助B轴,i种盘子

把i - 1种不考虑顺序移到C,需要a[i - 1].

把第i种从A移动到B,需要x[i](颠倒顺序),

把i - 1种不考虑顺序移到A(腾出C),需要a[i - 1].

把第i种从B移动到C,需要x[i](顺序恢复)

把i - 1种考虑顺序移到C,需要b[i - 1].

所以有b[i] = 2 * a[i - 1] 2 * x[i] b[i - 1]

最后答案是b[n - 1].

代码:

#include<iostream>
using namespace std;
int n, m, x[100], num, a[100], b[100];
int main()
{
    while(scanf("%d%d", &n, &m) != EOF)
    {
        for(int i = 0; i < n; i )
            scanf("%d", &x[i]);
        a[0] = x[0];
        for(int i = 1; i < n; i )
            a[i] = (a[i - 1] * 2 x[i]) % m;
        b[0] = 2 * x[0] - 1;
        for(int i = 1; i < n; i )
            if (x[i] == 1)
                b[i] = a[i];
            else
                b[i] = (2 * a[i - 1] 2 * x[i] b[i - 1]) % m;
        printf("%d\n", b[n - 1]);
    }
    return 0;
}

 

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有