Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 河内溶液塔优于O(2^n)?_Java_Algorithm_Towers Of Hanoi - Fatal编程技术网

Java 河内溶液塔优于O(2^n)?

Java 河内溶液塔优于O(2^n)?,java,algorithm,towers-of-hanoi,Java,Algorithm,Towers Of Hanoi,对于运行时间小于O(2n)的河内塔,是否有解决方案,其中n是要移动的磁盘数?我的解需要O(2n)个时间 同样,下面的解决方案是递归的。我们能用动态规划和记忆的概念在更短的时间内解决这个问题吗 public void towersOfHanoi( int num, MyStack<Integer> from, MyStack<Integer> to, MyStack<Integer> spare

对于运行时间小于O(2n)的河内塔,是否有解决方案,其中n是要移动的磁盘数?我的解需要O(2n)个时间

同样,下面的解决方案是递归的。我们能用动态规划和记忆的概念在更短的时间内解决这个问题吗

public void towersOfHanoi(
        int num, 
        MyStack<Integer> from,
        MyStack<Integer> to, 
        MyStack<Integer> spare
) {
    if (num == 1) {
        int i = from.pop();
        to.push(i);
        System.out.println("Move "+i+" from "+from.getName()+" to " + to.getName());
        return;
    }
    towersOfHanoi(num - 1, from, spare, to);
    towersOfHanoi(1, from, to, spare);
    towersOfHanoi(num - 1, spare, to, from);
}
哈尼公共空塔(
int num,
来自,
我的目标是,
MyStack备用
) {
如果(num==1){
int i=from.pop();
推(i);
System.out.println(“将“+i+”从“+from.getName()+”移动到“+to.getName());
返回;
}
哈尼塔(数量-1,从,备用,到);
哈尼塔楼(1座,从,到,备用);
哈尼塔(数量-1,备用,至,自);
}
MyStack
是Java中
Stack
类的扩展版本,它添加了
name
字段和访问器


另外,同样的问题有什么变化吗?

考虑到解决河内塔问题总是需要2^n-1个步骤……不,你不会找到更快的算法,因为打印出这些步骤需要O(2^n),更不用说计算了。

我不会证明(像斯蒂芬那样),但我会尝试直观地解释2^n-1是最小的: 在每个状态下,磁盘只有三种可能的移动。 让我们将当前状态表示为有序的seq(1,1,…,1),这样第一个数字表示较大磁盘的位置,最后一个数字表示最小磁盘的位置。(1,1,…,1)表示所有磁盘都在位置1上。从(1,1,…1)也只有两种下降状态:(1,1,…2)和(1,1,…3)。从(1,1,…2)开始,有三种下降状态:

  • 回到(1,1,…1)
  • 后藤(1,1,…,3)
  • 后藤(1,1,…3,2)
  • 如果继续,将得到一个图,其中节点是可能的状态,边(过渡)是“磁盘移动”

    您将获得如下所示的图像(如果继续,它将看起来像三角形,并且在顶点处将是(1,1,…1),(2,2,…2),(3,3,…3))。步骤数实际上是图形中的路径

    如果沿着三角形的边行走,则步数为2^n-1。所有其他路径的长度相同或更长

    如果您使用的策略是:将除最大磁盘外的所有磁盘移动到第3位,然后将最大磁盘移动到第2位,最后将所有表格3移动到第2位,公式可按以下方式设计:

    f(n)=
    f(n-1)//将除最大值以外的所有值从1移动到3
    +1//将最大值从1移动到2
    +f(n-1)//将全部从3移动到2
    ->
    f(n)=1+2*f(n-1)


    该循环方程的解给出了该策略所需的步数(恰好是最小步数)

    河内塔的解不可避免地是2n。但是,在动态规划解决方案中,每个子问题只计算一次,然后通过组合第一个子问题解决方案、当前磁盘移动和第二个子问题解决方案来解决问题

    因此,生成每个解决方案有两个部分:为当前解决方案分配内存,然后填充该内存。内存分配与分配的内存大小大致无关,是一个昂贵的组件。内存拷贝的大小是线性的,虽然很快,但作为塔的解决方案,它在n中是指数的

    时间=c1*n+c2*2n,其中c1>>c2。也就是说,它以线性开始,以指数结束


    河内的标准塔问题涉及3个木桩

    然而,如果我们有k-peg,时间复杂度将是O(2^(n/(k-2)))


    我用4个PEG和5个PEG解决了这个问题,得到的时间复杂度分别是O(2^(n/2))和O(2^(n/3))

    这个比递归的快7%。它将移动存储在一个列表中,以便您可以使用它,否则,您可以根据需要打印并删除容器

    ```
    unsigned long i;  
    static const int MAXNUMBEROFDISKS = 32;
    vector<int> pow2Vec;
    uint_fast32_t mPinFrom    = 0;
    uint_fast32_t mNumDisk    = 0;
    unsigned long numDiskLong = 0;
    uint_fast32_t mOffset[MAXNUMBEROFDISKS];
    uint_fast32_t mDir[MAXNUMBEROFDISKS]          = { 0 };
    uint_fast32_t mPositionDisk[MAXNUMBEROFDISKS] = { 0 };
    const uint_fast32_t mRedirectArr[5] = { 2, 0, 1, 2, 0 };
    
    
    
    
    Algos::Algos()
    { 
      for (int i = 0; i < MAXNUMBEROFDISKS; ++i)
      {
        pow2Vec.push_back(pow(2, i));
        mOffset[i] = 1;
      }
    
      for (int i = 1; i < MAXNUMBEROFDISKS; i += 2)
      {
        mDir[i] = 2;
      }
    
      mOffset[0] = 0;
    }
    
    
    
    
    void Algos::calculListBinExperiment(vector<tuple<int, int, int>>& listeFinale, int nbDisk)
    {
      listeFinale.resize(pow2Vec[nbDisk] - 1);
      _BitScanForward(&i, nbDisk);
      for (int noCoup = 1; noCoup < pow2Vec[nbDisk] ; ++noCoup)
      {
        _BitScanForward(&numDiskLong, noCoup);
        mNumDisk = numDiskLong;
        mPinFrom = mPositionDisk[mNumDisk];
        mPositionDisk[mNumDisk] = mRedirectArr[mPositionDisk[mNumDisk] + mDir[mNumDisk + 
        mOffset[i]]];
        listeFinale[noCoup - 1] = make_tuple(mNumDisk, mPinFrom, mPositionDisk[mNumDisk]);
      }
    }
    ```
    
    ```
    无符号长i;
    静态常量int MAXNUMBEROFDISKS=32;
    向量pow2Vec;
    uint\u fast32\u t mPinFrom=0;
    uint\u fast32\u t mNumDisk=0;
    无符号长numDiskLong=0;
    uint_fast32_t mOffset[MAXNUMBEROFDISKS];
    uint_fast32_t mDir[MAXNUMBEROFDISKS]={0};
    uint\u fast32\u t复合磁盘[MAXNUMBEROFDISKS]={0};
    consuint_fast32_t mRedirectArr[5]={2,0,1,2,0};
    Algos::Algos()
    { 
    对于(int i=0;i
    “对于运行时间小于O(2^n)的河内塔,是否有解决方案,其中n是要移动的磁盘数?”-是。这被称为作弊:-)…你拿起整堆东西,一下子把它移过来。不,没有比2^n更好的遵循规则的方法。对这个主题有极好的洞察力!一开始,我并不十分方便,直到我自己从中得到灵感实现了它,然后我开始意识到示例程序和应答者都是同一个人。谢谢你,蒂姆·罗尔夫!我很幸运能在网上追踪你的踪迹。:-)您的代码不完整,但似乎
    CalcultiberExperiment
    有一个循环,其中
    NoGroup
    1
    运行到
    2^n
    ,其中
    n
    是磁盘数。那是O(2^n),不是即兴表演