最短路径中的两点之间的网格。使用catch [英] Shortest path in a grid between two points. With a catch

查看:177
本文介绍了最短路径中的两点之间的网格。使用catch的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个问题,我必须要找到从A点(始终左上)的N×M个网格的最短路径只向右移动或向下到点B(总右下)。听起来很简单,是吗?那么这里的渔获:我只能继续前进的瓷砖我此刻坐在上显示的号码。让我举例说明:

  2 5 1 2
9 2 5 3
3 3 1 1
4 8 2 7
 

在此4x4网格的最短路径将采取3个步骤,从顶部行走左节点2至3,并从那里3节点权1,然后1节点下到目标

  [2] 5 1 2
 9 2 5 3
[3] 3 1 [1]
 4 8 2 [7]
 

如果不是最短路径,我也可以走这条路线:

  [2] 5 [1] [2]
 9 2 5 3
 3 3 1 [1]
 4 8 2 [7]
 

这将不幸需要的高达4步,因此,是不是我的兴趣。 这应该清楚的事情了一下。 现在有关输入。


用户输入格如下:

  5 4 //高度和宽度
2 5 2 2 //
2 2 7 3 //的
3 1 2 2 //格
4 8 2 7 //
1 1 1 1 //
 


作业

我想到这通过,但不能得出一个更好的解决方案,而不是简化输入电网到unweighed(或负重量)图,并在其上​​运行像Dijkstra算法或A *(或类似的规定)。嗯...这是一部分,我迷路了。我实现的东西开始(或东西扔鞭打马上)。它有没有关系Dijkstra算法或A *或任何东西;只是直接的广度优先搜索。


的code

 的#include<的iostream>
#包括<载体>

结构点;

类型定义的std ::矢量< INT> vector_1D;
类型定义的std ::矢量<的std ::矢量< INT> > vector_2D;
类型定义的std ::矢量<点和GT; vector_point;

结构点{
    INT Y,X;
    vector_point父母;
    点(中间体yPos = 0,诠释XPOS = 0)为:y(yPos)中,x(XPOS){}

    void运算符<< (常量点和放大器;点){这 - > Parents.push_back(点); }
};

结构grid_t {
    INT高度,宽度;
    vector_2D砖;

    grid_t()//构造格
    {
        给std :: cin>>高度>>宽度; //输入电网的高度和放大器;宽度

        tiles.resize(高度,vector_1D(宽度,0)); //初始化格砖

        的for(int i = 0; I<高度;我++)//
            为(诠释J = 0; J&所述;宽度; J ++)//输入每一瓦片一次一个
                给std :: cin>>瓷砖[I] [J]。 //通过Grid循环
    }
};

无效go_find_it(grid_t&安培;电网)
{
    vector_point openList,closedList;
    点previous_node; //点​​被初始化为(Y = 0,X = 0)如果没有告知,否则
    openList.push_back(previous_node); //(0,0)当然是我们想咨询的第一点,

    做
    {
        closedList.push_back(openList.back()); //我们是在瓷砖是好的,检查。它标记左右。
        openList.pop_back(); //我们不需要这个家伙没有更多

        INT Y = closedList.back()Y。 //现在,我们将实际
        INT X = closedList.back()×。 //移动到新点

        INT跳= grid.tiles [Y] [X] //'跳'是对我们站在瓦片显示的数字。

        如果(Y +跳< grid.height)//如果我们不打算出界
        {
            openList.push_back(点(Y +跳跃,X)); //
            openList.back()&其中;&其中;点(Y,X); //推入我们在现在的点,因为它的父节点
        }
        如果(X +跳< grid.width)//如果我们不打算出界
        {
            openList.push_back(点(Y,X +跳跃)); //推入新的有希望的点
            openList.back()&其中;&其中;点(Y,X); //推入我们在现在的点,因为它的父节点
        }
    }
    而(openList.size()大于0); //当没有新的瓦片,检查,打破了与回报
}

诠释的main()
{
    grid_t网格; //初始化网格

    go_find_it(网格); //基本上蛮力得到它所有算法

    返回0;
}
 

我应该大概还要指出,运行时间不能超过1秒,且最大网格的高度和宽度为1000。所有的瓦片也号码从1至1000。

感谢。


编辑code

 的#include<的iostream>
#包括<载体>

结构点;

类型定义的std ::矢量< INT> vector_1D;
类型定义的std ::矢量<的std ::矢量< INT> > vector_2D;
类型定义的std ::矢量<点和GT; vector_point;

结构点{
    INT Y,X,深度;
    vector_point父母;
    点(中间体yPos = 0,诠释XPOS = 0,诠释dDepth = 0)为:y(yPos)中,x(XPOS),深度(dDepth){}

    void运算符<< (常量点和放大器;点){这 - > Parents.push_back(点); }
};

结构grid_t {
    INT高度,宽度;
    vector_2D砖;

    grid_t()//构造格
    {
        给std :: cin>>高度>>宽度; //输入电网的高度和放大器;宽度

        tiles.resize(高度,vector_1D(宽度,0)); //初始化格砖

        的for(int i = 0; I<高度;我++)//
            为(诠释J = 0; J&所述;宽度; J ++)//输入每一瓦片一次一个
                给std :: cin>>瓷砖[I] [J]。 //通过Grid循环
    }
};

INT go_find_it(grid_t&安培;电网)
{
    vector_point openList,closedList;
    点previous_node(0,0,0); //点​​被初始化为(γ= 0,X = 0,深度= 0),如果没有被告知,否则
    openList.push_back(previous_node); //(0,0)当然是我们想咨询的第一点,

    INT min_path = 1000000;

    做
    {
        closedList.push_back(openList [0]); //我们是在瓷砖是好的,检查。它标记左右。
        openList.erase(openList.begin()); //我们不需要这个家伙没有更多

        INT Y = closedList.back()Y。 //现在我们要实际移动到新点
        INT X = closedList.back()×。 //
        。INT深度= closedList.back()的深度; //新的深度

        如果(Y == grid.height-1和;&放大器,X == grid.width-1)的回报深度; //第一路径是最短的一个。返回它

        INT跳= grid.tiles [Y] [X] //'跳'是对我们站在瓦片显示的数字。

        如果(Y +跳< grid.height)//如果我们不打算出界
        {
            openList.push_back(点(Y +跳跃中,x,深度+ 1)); //
            openList.back()&其中;&其中;点(Y,X); //推入我们在现在的点,因为它的父节点
        }
        如果(X +跳< grid.width)//如果我们不打算出界
        {
            openList.push_back(点(Y,X +跳跃,深度+ 1)); //推入新的有希望的点
            openList.back()&其中;&其中;点(Y,X); //推入我们在现在的点,因为它的父节点
        }
    }
    而(openList.size()大于0); //当没有新的瓦片,检查,打破并返回false

    返回0;
}

诠释的main()
{
    grid_t网格; //初始化网格

    INT min_path = go_find_it(网格); //基本上蛮力得到它所有算法

    性病::法院<< min_path<<的std :: ENDL;
    //系统(暂停);
    返回0;
}
 

该计划现在打印正确的答案。现在,我必须优化(运行时间是太大了)。就这一个任何提示?优化是一件事,我吮吸。


答案

在最终解决方案出现了由小code。越少越好,因为我喜欢它。由于德扬·约万诺维奇的美丽解决方案

 的#include<的iostream>
#包括<载体>
#包括<算法>

结构grid_t {
    INT高度,宽度;
    的std ::矢量<的std ::矢量< INT> >瓷砖;
    的std ::矢量<的std ::矢量< INT> >距离;

    grid_t()//构造格
    {
        给std :: cin>>高度>>宽度; //输入电网的高度和放大器;宽度

        tiles.resize(身高,标准::矢量< INT>(宽度,0)); //初始化格砖
        distance.resize(身高,标准::矢量< INT>(宽,1000000)); //初始化格砖

        的for(int i = 0; I<高度;我++)//
            为(诠释J = 0; J&所述;宽度; J ++)//输入每一瓦片一次一个
                给std :: cin>>瓷砖[I] [J]。 //通过Grid循环
    }
};

诠释的main()
{
    grid_t网格; //初始化网格

    grid.distance [0] [0] = 0;
    的for(int i = 0; I< grid.height;我++){
        对于(INT J = 0; J< grid.width; J ++){
            如果(grid.distance [I] [J] LT; 1000000){
                INT D = grid.tiles [I] [J]。
                如果第(i + D&所述; grid.height){
                    grid.distance [I + D] [J] =标准::分(grid.distance [I] [J] + 1,grid.distance [I + D] [J]);
                }
                如果(J + D< grid.width){
                    grid.distance [I] [J + D] =标准::分(grid.distance [I] [J] + 1,grid.distance [I] [J + D]);
                }
            }
        }
    }
    如果(grid.distance [grid.height-1] [grid.width-1] == 1000000)grid.distance [grid.height-1] [grid.width-1] = 0;
    性病::法院<< grid.distance [grid.height-1] [grid.width-1];&其中;的std :: ENDL;
    //系统(暂停);
    返回0;
}
 

解决方案

有需要构造图,这可以很容易地解决了使用一个扫描整个矩阵动态规划。

您可以在一开始设定的距离矩阵D [I,J]为+ INF,与D [0,0] = 0,同时穿越你只是做矩阵

 如果(D [I,J] 1 + INF){
  INT D = A [I,J]。
  如果第(i + D&其中M){
    D [我+ D,J] = MIN(D [I,J] + 1,D [我+ D,J]);
  }
  如果第(j + D&其中N){
    D [I,J + D] =分钟(D [I,J] + 1,D [I,J + D]);
  }
}
 

最终的最小距离是在D [M-1,N-1]。如果你想重建的路径,你可以保持一个独立的矩阵标志着那里的最短路径来了。

I have this problem where I have to find the shortest path in an NxM grid from point A (always top left) to point B (always bottom right) by only moving right or down. Sounds easy, eh? Well here's the catch: I can only move the number shown on the tile I'm sitting on at the moment. Let me illustrate:

2 5 1 2
9 2 5 3
3 3 1 1
4 8 2 7

In this 4x4 grid the shortest path would take 3 steps, walking from top left 2 nodes down to 3, and from there 3 nodes right to 1, and then 1 node down to the goal.

[2] 5  1  2
 9  2  5  3
[3] 3  1 [1]
 4  8  2 [7]

If not for the shortest path, I could also be taking this route:

[2] 5 [1][2]
 9  2  5  3
 3  3  1 [1]
 4  8  2 [7]

That would unfortunately take a whopping 4 steps, and thus, is not in my interest. That should clear things out a bit. Now about the input.


The user inputs the grid as follows:

5 4      // height and width
2 5 2 2  //
2 2 7 3  // the
3 1 2 2  // grid
4 8 2 7  //
1 1 1 1  //


Homework

I have thought this through, but cannot come to a better solution than to simplify the inputted grid into an unweighed (or negative-weight) graph and run something like dijkstra or A* (or something along those lines) on it. Well... this is the part where I get lost. I implemented something to begin with (or something to throw to thrash right away). It's got nothing to do with dijkstra or A* or anything; just straight-forward breadth-first search.


The Code

#include <iostream>
#include <vector>

struct Point;

typedef std::vector<int> vector_1D;
typedef std::vector< std::vector<int> > vector_2D;
typedef std::vector<Point> vector_point;

struct Point {
    int y, x;
    vector_point Parents;
    Point(int yPos = 0, int xPos = 0) : y(yPos), x(xPos) { }

    void operator << (const Point& point) { this->Parents.push_back(point); }
};

struct grid_t {
    int height, width;
    vector_2D tiles;

    grid_t() // construct the grid
    { 
        std::cin >> height >> width; // input grid height & width

        tiles.resize(height, vector_1D(width, 0)); // initialize grid tiles

        for(int i = 0; i < height; i++)     //
            for(int j = 0; j < width; j++)  // input each tile one at a time
                std::cin >> tiles[i][j];    // by looping through the grid
    }
};

void go_find_it(grid_t &grid)
{
    vector_point openList, closedList;
    Point previous_node; // the point is initialized as (y = 0, x = 0) if not told otherwise
    openList.push_back(previous_node); // (0, 0) is the first point we want to consult, of course

    do
    {
        closedList.push_back(openList.back()); // the tile we are at is good and checked. mark it so.
        openList.pop_back(); // we don't need this guy no more

        int y = closedList.back().y; // now we'll actually
        int x = closedList.back().x; // move to the new point

        int jump = grid.tiles[y][x]; // 'jump' is the number shown on the tile we're standing on.

        if(y + jump < grid.height) // if we're not going out of bounds
        { 
            openList.push_back(Point(y+jump, x)); // 
            openList.back() << Point(y, x); // push in the point we're at right now, since it's the parent node
        }
        if(x + jump < grid.width) // if we're not going out of bounds
        { 
            openList.push_back(Point(y, x+jump)); // push in the new promising point
            openList.back() << Point(y, x); // push in the point we're at right now, since it's the parent node
        }
    }
    while(openList.size() > 0); // when there are no new tiles to check, break out and return
}

int main()
{
    grid_t grid; // initialize grid

    go_find_it(grid); // basically a brute-force get-it-all-algorithm

    return 0;
}

I should probably also point out that the running time cannot exceed 1 second, and the maximum grid height and width is 1000. All of the tiles are also numbers from 1 to 1000.

Thanks.


Edited Code

#include <iostream>
#include <vector>

struct Point;

typedef std::vector<int> vector_1D;
typedef std::vector< std::vector<int> > vector_2D;
typedef std::vector<Point> vector_point;

struct Point {
    int y, x, depth;
    vector_point Parents;
    Point(int yPos = 0, int xPos = 0, int dDepth = 0) : y(yPos), x(xPos), depth(dDepth) { }

    void operator << (const Point& point) { this->Parents.push_back(point); }
};

struct grid_t {
    int height, width;
    vector_2D tiles;

    grid_t() // construct the grid
    { 
        std::cin >> height >> width; // input grid height & width

        tiles.resize(height, vector_1D(width, 0)); // initialize grid tiles

        for(int i = 0; i < height; i++)     //
            for(int j = 0; j < width; j++)  // input each tile one at a time
                std::cin >> tiles[i][j];    // by looping through the grid
    }
};

int go_find_it(grid_t &grid)
{
    vector_point openList, closedList;
    Point previous_node(0, 0, 0); // the point is initialized as (y = 0, x = 0, depth = 0) if not told otherwise
    openList.push_back(previous_node); // (0, 0) is the first point we want to consult, of course

    int min_path = 1000000;

    do
    {
        closedList.push_back(openList[0]); // the tile we are at is good and checked. mark it so.
        openList.erase(openList.begin()); // we don't need this guy no more

        int y = closedList.back().y; // now we'll actually move to the new point
        int x = closedList.back().x; //
        int depth = closedList.back().depth; // the new depth

        if(y == grid.height-1 && x == grid.width-1) return depth; // the first path is the shortest one. return it

        int jump = grid.tiles[y][x]; // 'jump' is the number shown on the tile we're standing on.

        if(y + jump < grid.height) // if we're not going out of bounds
        { 
            openList.push_back(Point(y+jump, x, depth+1)); // 
            openList.back() << Point(y, x); // push in the point we're at right now, since it's the parent node
        }
        if(x + jump < grid.width) // if we're not going out of bounds
        { 
            openList.push_back(Point(y, x+jump, depth+1)); // push in the new promising point
            openList.back() << Point(y, x); // push in the point we're at right now, since it's the parent node
        }
    }
    while(openList.size() > 0); // when there are no new tiles to check, break out and return false

    return 0;
}

int main()
{
    grid_t grid; // initialize grid

    int min_path = go_find_it(grid); // basically a brute-force get-it-all-algorithm

    std::cout << min_path << std::endl;
    //system("pause");
    return 0;
}

The program now prints the correct answer. Now I have to optimize (run time is way too big). Any hints on this one? Optimizing is the one thing I suck at.


The Answer

In the end the solution appeared to consist of little code. The less the better, as I like it. Thanks to Dejan Jovanović for the beautiful solution

#include <iostream>
#include <vector>
#include <algorithm>

struct grid_t {
    int height, width;
    std::vector< std::vector<int> > tiles;
    std::vector< std::vector<int> > distance;

    grid_t() // construct the grid
    { 
        std::cin >> height >> width; // input grid height & width

        tiles.resize(height, std::vector<int>(width, 0)); // initialize grid tiles
        distance.resize(height, std::vector<int>(width, 1000000)); // initialize grid tiles

        for(int i = 0; i < height; i++)     //
            for(int j = 0; j < width; j++)  // input each tile one at a time
                std::cin >> tiles[i][j];    // by looping through the grid
    }
};

int main()
{
    grid_t grid; // initialize grid

    grid.distance[0][0] = 0;
    for(int i = 0; i < grid.height; i++) {
        for(int j = 0; j < grid.width; j++) {
            if(grid.distance[i][j] < 1000000) {
                int d = grid.tiles[i][j];
                if (i + d < grid.height) {
                    grid.distance[i+d][j] = std::min(grid.distance[i][j] + 1, grid.distance[i+d][j]);
                }
                if (j + d < grid.width) {
                    grid.distance[i][j+d] = std::min(grid.distance[i][j] + 1, grid.distance[i][j+d]);
                }
            }
        }
    }
    if(grid.distance[grid.height-1][grid.width-1] == 1000000) grid.distance[grid.height-1][grid.width-1] = 0;
    std::cout << grid.distance[grid.height-1][grid.width-1] << std::endl;
    //system("pause");
    return 0;
}

解决方案

There is need to construct the graph, this can easily be solved with dynamic programming using one scan over the matrix.

You can set the distance matrix D[i,j] to +inf at the start, with D[0,0] = 0. While traversing the matrix you just do

if (D[i,j] < +inf) {
  int d = a[i, j];
  if (i + d < M) {
    D[i + d, j] = min(D[i,j] + 1, D[i + d, j]);
  }
  if (j + d < N) {
    D[i, j + d] = min(D[i,j] + 1, D[i, j + d]);
  }
}

The final minimal distance is in D[M -1, N-1]. If you wish to reconstruct the path you can keep a separate matrix that marks where the shortest path came from.

这篇关于最短路径中的两点之间的网格。使用catch的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆