赢得Snake Ladder的最低步骤

时间:2013-08-19 16:34:46

标签: arrays algorithm

给定一个蛇和梯子游戏,编写一个函数,返回最小跳跃数量,以获取顶部或目标位置。 你可以假设你抛出的结果总是对你有利

**

  

这是我的解决方案,但不确定它是否正确。

     

这个问题类似于数组中的青蛙跳跃。但在此之前我们   必须以该格式对问题进行建模。

     

创建一个大小为100的数组,如果存在则为每个位置存储6创建   没有蛇或梯子。店铺跳数。如果梯子出现在那里   点。如果存在蛇,则存储-ve在该位置跳转。

     

现在我们必须解决我们可以达到的最小步数。   在O(n ^ 2)时间内使用动态编程可以解决主要问题   复杂性和O(n)空间。

8 个答案:

答案 0 :(得分:5)

查看this博客文章,它使用蒙特卡罗模拟和马尔可夫链对滑槽和梯子进行全面的数学分析。他确实展示了一种计算获胜步数的方法(基本上构建一个转换矩阵,看看你必须将起始矢量乘以多少次才能得到一个非零最终位置的解)。这可能不是最有效的方式,但这篇文章非常值得一读。

这是python中使用sets的快速解决方案。我从博客文章中获得了跳转表中的数字。在每一步,它只是计算从上一步可以到达的所有位置,并继续这样做,直到最终位置在可到达的位置之中:

jumps = {1: 38, 4: 14, 9: 31, 21: 42, 28: 84, 36: 44, 51: 67, 71: 91, 80: 100,
  98: 78, 95: 75, 93: 73, 87: 24, 64: 60, 62: 19, 56: 53, 49: 11, 48: 26, 16: 6}
final_pos = 100
positions = {0} #initial position off the board
nsteps = 0

while final_pos not in positions:
    nsteps += 1
    old_positions = positions
    positions = set()
    for pos in old_positions:
        for dice in range(1, 7):
            new_pos = pos + dice
            positions.add(jumps.get(new_pos, new_pos))

print 'Reached finish in %i steps' % nsteps            

执行时间可以忽略不计,并且会发出7的正确答案(见博客)。

答案 1 :(得分:3)

这是Python中一个简单的广度优先搜索解决方案:

# the target square and the positions of the snakes and ladders:
top = 100
jump = { 1: 38,  4: 14,  9: 31, 16:  6, 21: 42, 28: 84, 36: 44,
        48: 26, 49: 11, 51: 67, 56: 53, 62: 19, 64: 60, 71: 91,
        80:100, 87: 24, 93: 73, 95: 75, 98: 78}

# start from square 0 (= outside the board) after 0 rolls
open = {0}
path = {0: ()}

while len(open) > 0:
    i = open.pop()
    p = path[i] + (i,)
    for j in xrange(i+1, i+7):
        if j > top: break
        if j in jump: j = jump[j]
        if j not in path or len(path[j]) > len(p):
            open.add(j)
            path[j] = p

for i in path:
    print "Square", i, "can be reached in", len(path[i]), "rolls via", path[i]

电路板布局(即jump字典)取自他在blog post中由Bas Swinckels链接的answer。 此代码将打印(其中一条)最短路径到板上每个可到达的方块,结束于:

Square 100 can be reached in 7 rolls via (0, 38, 41, 45, 67, 68, 74)

如果您想要完整输出,请参阅this demo on ideone.com

答案 2 :(得分:1)

我在C#中实现了这一点。你可以查看我的要点here。我还会粘贴下面的代码。

在我的实施中,我考虑了以下几点:

  • 避免循环:当蛇穿过梯子时会发生这种情况。例如,当梯子的末端是蛇的头部并且蛇的尾部是同一梯子的开始时。这是一个简单的例子,但可能会有更复杂的循环。
  • 抓好蛇:我注意到你不需要避开所有的蛇。有时你需要拿蛇,因为它可以帮助你更快地到达目标。我称之为“好蛇”。例如3> 60然后 61> 50 然后51> 100(目标)。如果你拿蛇,最小骰子数将是3而没有蛇8。
  • 可选和强制跳转:当可选跳转设置为false时,算法必须在到达时跳转。
  • 最短路识别:当算法到达目标时,它将注册最短路径,在计算过程中,它将丢弃比当前找到的解决方案更长的搜索。这使得在复杂情况下该过程更快。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    namespace SnakeAndLaddersSolution
    {
      public class SnakeAndLadder
      {
        private struct Jump
       {
         public int Start;
         public int End;
       }
    
       private const int TOP = 100;
       private const int STEP_SIZE = 6;
       private int _minDiceCount = int.MaxValue;
       private readonly List<Jump> _jumps = new List<Jump>();
    
       public bool OptionalJump { get; set; }
    
       public void AddJump(int start, int end)
       {
           _jumps.Add(new Jump { Start = start, End = end });
       }
    
       public int Solve()
       {
           var path = new Stack<int>();
           path.Push(1); //start from square 1
           return FindMinimumDice(path, 0);
       }
    
       private int FindMinimumDice(Stack<int> path, int diceCount)
       {
           if (diceCount >= _minDiceCount)
           {
               //too long. we've already found a shortest path.
               //drop going deeper
               return -1;
           }
           var currentSquare = path.Peek();
           var diceCounts = new List<int>();
           int newDiceCount;
    
           var ignoreNormalJump = false;
    
        for (var i = 0; i <= STEP_SIZE; i++)
        {
            var newSquare = currentSquare + i;
            if (newSquare == TOP)
            {
                //got there
                var totalDiceCount = diceCount + (i == 0 ? 0 : 1);
                _minDiceCount = Math.Min(_minDiceCount, totalDiceCount); //register the shortest path
                return totalDiceCount;
            }
    
    
            if (_jumps.All(j => j.Start != newSquare)) continue; //only process jumps
    
            var jump = _jumps.First(j => j.Start == newSquare);
            if (path.Contains(jump.End))
                continue; //already been here
            path.Push(jump.Start);
            path.Push(jump.End);
            newDiceCount = FindMinimumDice(path, diceCount + (i == 0 ? 0 : 1));
            path.Pop();
            path.Pop();
            if (newDiceCount != -1)
                diceCounts.Add(newDiceCount);
            if (i == 0 && !OptionalJump) //the current squre is a jump that should be taken
            {
                ignoreNormalJump = true;
                break;
            }
        }
        if (!ignoreNormalJump)
        {
            var longestJump = 0;
            for (var i = STEP_SIZE; i > 0; i--)
            {
                if (_jumps.All(j => j.Start != currentSquare + i))
                {
                    longestJump = currentSquare + i;
                    break;
                }
            }
            if (longestJump != 0)
            {
                path.Push(longestJump);
                newDiceCount = FindMinimumDice(path, diceCount + 1);
                path.Pop();
                if (newDiceCount != -1)
                    diceCounts.Add(newDiceCount);
            }
        }
        return !diceCounts.Any() ? -1 : diceCounts.Min();
       }
      }
    
      class Program
      {
    
       static void Main(string[] args)
       {
           var sal = new SnakeAndLadder();
           //set OptionalJump to true if the jump is optional
           //sal.OptionalJump = true;
           sal.AddJump(10,60);
           sal.AddJump(51,100);
           Console.WriteLine(sal.Solve());
           Console.ReadLine();
       }
      }
      }
    

答案 3 :(得分:0)

广度优先搜索(BFS)或动态编程解决方案将使用O(N)空间在O(N)时间内工作。

初始化:保留辅助阵列以保持梯子和蛇。假设从第x个到第y个单元格有一个梯子。所以auxi [x] = y。如果有从单元格x到y的蛇,x>y则保留auxi[x]=-1。如果当前单元格中没有梯形图或蛇形图,请保持auxi [x] = x;

动态编程解决方案:

res[top]=0;
for(int i  = top-1; i>=0; i--) {

    res[i] = INF;
    for(int j=1; j<=6; j++){

        if(i-j<0)break;

        if(auxi[i+j]>-1)     // if i+jth cell is start of a snake, we'll always skip it
        res[i]=min( res[i] , res[auxi[i+j]]+1 );
    }

}

我们总是跳过一个蛇开始的细胞,因为我们假设,在x的细胞上,蛇开始,它在第y个细胞上结束,在那里,y

答案 4 :(得分:0)

o(n)中C#中的解决方案。

构建一个帮助矩阵来检查每个步骤,看看到达那里的最小方法是什么,并添加一个。

const int BoardSize = 100;
const int MaxStep = 6;
static void Main()
{

    // - means a ledder ending at the pos
    // + means a snake (taking you back n steps)
    int[] arr = new int[] {     
                            -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1, 
                            -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
                            -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1, 
                            -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1, 
                            -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1, 
                            -1,     -1,     -1,     -1,      8,     -1,     -1,     -1,     -1,     -1, 
                            -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1, 
                            -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1, 
                            -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1, 
                            -1,     -1,     -1,     -1,     -1,     -1,     -1,     -71,    -1,     -1      };

    Console.WriteLine("Steps needed: " + solve(arr));
}

public static int solve(int[] inArr)
{
    int[] arr = new int[BoardSize];

    arr[0] = 1;

    for (int i = 0; i < BoardSize; ++i)
    {
        // steps here is the minimum of all the positions in all the previos 6 cells +1
        if (i < MaxStep)
            arr[i] = 1;
        else
        {
            int extraOption = int.MaxValue;
            if (inArr[i] < -1 || inArr[i] > 0)
                extraOption = arr[i + inArr[i]];
            else if (inArr[i] > 0)
                extraOption = arr[i + inArr[i]];
            arr[i] = min(arr[i - 1], arr[i - 2], arr[i - 3], arr[i - 4], arr[i - 5], arr[i - 6], extraOption) + 1;
        }
    }

    for (int i = 0; i < BoardSize; ++i)
    {
        Console.Write(arr[i] + "\t");
        if ((i + 1) % 10 == 0)
            Console.WriteLine("");
    }

    return arr[arr.Length-1];
}

public static int min(int a, int b, int c, int d, int e, int f, int g)
{
    int ab = Math.Min(a,b);
    int cd = Math.Min(c,d);
    int ef = Math.Min(e,f);
    return Math.Min(Math.Min(ab, cd), Math.Min(ef,g));
}

答案 5 :(得分:0)

这个程序可以模拟实际场景......如果符合预期,请告诉我。

import java.util.HashMap;
import java.util.Map;

public class SnakeLadder {

    private Map<Integer,Integer> snakeLadderMapping=new HashMap<Integer,Integer>();


    private int winPosition=100;
    private int currentPosition=1;

    public SnakeLadder(){
        snakeLadderMapping.put(9, 19);
        snakeLadderMapping.put(17, 5);
        snakeLadderMapping.put(12, 40);
        snakeLadderMapping.put(24, 60);
        snakeLadderMapping.put(68, 89);
        snakeLadderMapping.put(50, 12);
        snakeLadderMapping.put(84, 98);
        snakeLadderMapping.put(75, 24);
        snakeLadderMapping.put(72, 16);
    }

    public int startGame(){
        int count=0;
        while(currentPosition!=winPosition){
            count++;
            getNextPosition(rollDice());
        }
        System.out.println("Game Won!!!!!!");
        return count;
    }

    public int rollDice(){
        return 1+ (int)(Math.random()*5);
    }

    public void getNextPosition(int diceValue){
        int temp=currentPosition+diceValue;
        if(snakeLadderMapping.containsKey(temp)){
            currentPosition=snakeLadderMapping.get(temp);
        }else{
            if(temp<=winPosition){
                currentPosition=temp;
            }
        }
    }
    /**
     * @param args
     */
    public static void main(String[] args) {
        SnakeLadder l=new SnakeLadder();
        System.out.println("No of Steps to win:"+l.startGame());

    }

}

答案 6 :(得分:0)

  1. 将每个视为有向图中的顶点。 2.从单元格1,您可以转到单元格2,3,4,5,6,7,因此顶点1将指向边缘朝向顶点2,顶点3 ... .vertex 7.同样考虑其余的单元格。
  2. 用蛇连接从蛇顶点到蛇顶点尾部的有向边。
  3. 用于梯形连接从梯形顶点底部到梯形顶点顶部的有向边。
    1. 现在问题被简化为短路径问题。因此,通过广度优先搜索(使用队列),我们可以解决问题。
  4. 请在此处查看完整的代码解决方案 - https://algorithms.tutorialhorizon.com/snake-and-ladder-problem/

答案 7 :(得分:0)

此Snake and Ladder游戏代码使用 Python编程语言构建。

简单的代码就能赢得蛇梯游戏。

****************蛇和梯子游戏代码*************************

$ virtualenv -p python3 venv
$ source venv/bin/activate
(venv)$ pip install git+https://github.com/Supervisor/supervisor.git
(venv)$ pip freeze