How to determine if a point is in shape in C++? - c++

I am trying to determine whether a point within a shape.
I found a algorithm that does the job
https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html
I tested the algorithm out with a square shape.
total corners of a square = 4
but however it returns me a wrong result.(see my output results below) after my codes
Shape.h
#ifndef __Shape__Shape__
#define __Shape__Shape__
class Shape {
private:
int xArray[4];
int yArray[4];
int x;
int y;
public:
bool inPoly(int x,int y);
void pointInShape();
};
#endif
Shape.cpp
#include "Shape.h"
#include <iostream>
bool Shape::inPoly(int x,int y) {
xArray[0] = 1;
xArray[1] = 1;
xArray[2] = 3;
xArray[3] = 3;
yArray[0] = 1;
yArray[1] = 3;
yArray[2] = 3;
yArray[3] = 1;
int i, j, nvert = 4, c = 0;
for (i = 0, j = nvert - 1; i < nvert; j = i++) {
if ( ((yArray[i]>y) != (yArray[j]>y)) &&
(x < (xArray[j]-xArray[i]) * (y-yArray[i]) / (yArray[j]-yArray[i]) + xArray[i]) )
c = !c;
}
return c;
}
void Shape::pointInShape() {
std::cout << "results" << std::endl;
std::cout << inPoly(1,1) << std::endl;
std::cout << inPoly(1,2) << std::endl;
std::cout << inPoly(1,3) << std::endl;
std::cout << inPoly(2,1) << std::endl;
std::cout << inPoly(2,2) << std::endl;
std::cout << inPoly(2,3) << std::endl;
std::cout << inPoly(3,1) << std::endl;
std::cout << inPoly(3,2) << std::endl;
std::cout << inPoly(3,3) << std::endl;
}
main.cpp
#include "Shape.h"
#include <iostream>
int main() {
Shape shape;
shape.pointInShape();
}
it returns me this output
results
1 <-- (means that 1,1 is is within polygon)
1 <-- (means that 1,2 is is within polygon)
0 <-- (means that 1,3 is is not within polygon)
1 <-- (means that 2,1 is is within polygon)
1 <-- (means that 2,2 is is within polygon)
0 <-- (means that 2,3 is is not within polygon)
0 <-- (means that 3,1 is is not within polygon)
0 <-- (means that 3,2 is is not within polygon)
0 <-- (means that 3,3 is is not within polygon)
by right the correct output should only return 2,2 as true
correct output
results
0 <-- (means that 1,1 is not within polygon)
0 <-- (means that 1,2 is not within polygon)
0 <-- (means that 1,3 is not within polygon)
0 <-- (means that 2,1 is not within polygon)
1 <-- (2,2 is is within polygon)
0 <-- (means that 2,3 is is not within polygon)
0 <-- (means that 3,1 is is not within polygon)
0 <-- (means that 3,2 is is not within polygon)
0 <-- (means that 3,3 is is not within polygon)
Any advice/suggestions?

the PNPOLY code as written is really meant for floats not ints. If you defined your arrays and vertices as floats it would give you the expected results.
1.0f and 2.0f are not adjacent in float math, but 1 and 2 are in int math.
what should tip you off is the function prototype
int pnpoly(int nvert, float *vertx, float *verty, float testx, float testy)
furthermore the line:
(testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) )
is going to truncate your ints to the nearest int after those divides.
If you really want to use ints you would have to define your shapes with a more room, say 100x100 instead of 2x2.

According to your link and this one: http://www.faqs.org/faqs/graphics/algorithms-faq/ (see section 2.03) the algorithm you've used will only work for points in the inside/outside of the polygon. Points on the border may return a 1 or a 0
If you want to know when a point is exactly on the boundary, you need another program. This is only one of many functions that PNPOLY lacks; it also doesn't predict tomorrow's weather. You are free to extend PNPOLY's source code.

Related

Creating a "#" border outside my 2d array

Hi I'm currently trying to create a border for my dynamic 2D array, I managed to create the left and right side border of my 2d array grid. But I currently have trouble figuring out on how to do it for the top and bottom side of the 2d array grid.
Is the method I'm currently trying a good way to achieve this? Any help or suggestion would be greatly appreciated thanks!
void displayCity(int minX, int maxX, int minY, int maxY)
{
//Allocate the array.
int** twod = new int* [maxX];
for (int i = 0; i < maxX; i++)
{
twod[i] = new int[maxY];
}
for (int i = 0; i< maxX; ++i)
{
cout << '#';
for (int j = 0; j < maxY; ++j)
{
twod[i][j] = 0;
cout << twod[i][j] << ' ';
}
cout << setw(1) << '#';
cout << endl;
}
//Deallocate the array.
for (int i = 0; i < maxX; ++i)
{
delete[] twod[i];
}
delete[] twod;
}
This is my current output.
#0 0 0 0 0 0 0 0 #
#0 0 0 0 0 0 0 0 #
#0 0 0 0 0 0 0 0 #
#0 0 0 0 0 0 0 0 #
#0 0 0 0 0 0 0 0 #
#0 0 0 0 0 0 0 0 #
#0 0 0 0 0 0 0 0 #
#0 0 0 0 0 0 0 0 #
Don't use "new/delete" unless you really need to. (C++ core guidelines).
Instead rely on datastructures from stl, like std::vector (for dynamically allocated arrays). For example like this :
#include <vector>
#include <iostream>
#include <string>
// City class to hold city data (but not to render it).
class City
{
public:
City(std::size_t width, std::size_t height) :
m_width{ width },
m_height{ height },
m_city_blocks(height,std::vector<int>(width))
{
}
const auto& city_blocks() const noexcept
{
return m_city_blocks;
}
const auto width() const noexcept
{
return m_width;
}
const auto height() const noexcept
{
return m_height;
}
private:
std::size_t m_width;
std::size_t m_height;
// dynamically allocated arrays are best handled by vector
// not by using new (new/delete are no longer recommended)
// use STL containers or std::make_unique
std::vector<std::vector<int>> m_city_blocks;
};
// Seperate class for rendering cities
class Renderer
{
public:
void ShowCity(const City& city)
{
// make a string with enougn '#' to draw bottom and top line
std::string border(2ul * city.width() + 3ul, '#');
// output to screen
std::cout << border << "\n";
// loop over all rows in the city's blocks using a range based for loop
// use const since rendering should not modify the state of the city blocks
// only show them.
for (const auto& row : city.city_blocks())
{
std::cout << "# ";
// loop over all values and display them
for (const auto& value : row)
{
std::cout << value << " ";
}
std::cout << "#\n";
}
std::cout << border << "\n";
}
};
int main()
{
// make a 5*5 city
City city{ 5ul,5ul };
// create a renderer to display the city
Renderer renderer;
renderer.ShowCity(city);
return 0;
}
Your way of drawing the border is rather inflexible because you mix the data, and formatting and output of the data with formatting and output of the border.
Also your borders are not straight lines when the numbers have different number of digits.
I suggest you to first gather all the output to be printed inside borders, then inspect it to see how many lines there are and how long the lines are. Then you know where to print the border:
#include <sstream>
#include <iomanip>
#include <vector>
#include <iostream>
void print_with_border(std::stringstream& str,char border='#') {
std::vector<std::string> output;
size_t max_len = 0;
std::string line;
while(std::getline(str,line)) {
output.push_back(line);
max_len = std::max(max_len,line.size());
}
std::cout << std::string(max_len+4,border) << "\n";
for (const auto& l : output) {
std::cout << border << " " << std::setw(max_len) << std::left << l << " " << border << "\n";
}
std::cout << std::string(max_len+4,border) << "\n";
}
int main() {
std::stringstream ss;
ss <<"hello \n world";
print_with_border(ss);
}
Output:
##########
# hello #
# world #
##########
To print contents of a 2d array you just have to pipe the contents of the array with desired formatting into a stringstream.

How to print a triangle whose sides are not equal?

I'm playing around with C++ and decided to try printing geometric shapes to the console. After printing an equilateral triangle, I decided I should try printing a triangle with varying side lengths, so that one is longer / shorter than the other.
I've tried searching the internet for this, but couldn't find any good explanations for it. After failing to do it on my own, I'd appreciate some help. Below is my code for an equilateral triangle:
unsigned size{ 5 };
for (int x{ 0 }; x < size; x++) {
for (int y{ 0 }; y <= x; y++) {
std::cout << "*";
}
std::cout << std::endl;
}
Which works and prints:
*
**
***
****
*****
Issue is, it can't handle the lower side being longer than the left one, for example. How do I go about doing that, so that I can end up with something like...
*
***
****
******
********
...where the left side and the lower side are not equal?
This could be a start:
void paint_triangle(size_t x, size_t y) {
size_t Y=1;
while(Y<=y) std::cout << std::string(x*Y++/y, '*') << "\n";
}

Point in Polygon C++ Algorithm implementation

I have tried two algorithms that were answers in other StackOverflow questions:
Check point within polygon
Point in Polygon Algorithm
Both were showing some points in as out or out as in while other points were correct. This test cast assumes that there are always only 4 vertices (rectangle)
bool PointInPolygon(Coordinate point, vector<Coordinate> points) {
cout << "x,y" << point.getX() << "," << point.getY() << endl;
cout << "TEST COOR ARRAY" << endl;
for (int i=0; i<4; i++) {
cout << points[i].getX() << "," << points[i].getY() << endl;
}
int i, j, nvert = points.size();
bool c = false;
for(i = 0, j = nvert - 1; i < nvert; j = i++) {
if( ( (points[i].getY() > point.getY() ) != (points[j].getY() > point.getY()) ) &&
(point.getX() < (points[j].getX() - points[i].getX()) * (point.getY() - points[i].getY()) / (points[j].getY() - points[i].getY()) + points[i].getX())
)
c = !c;
}
cout << c << "======================" << endl;
return c;
}
And the output was wrong where (2,3) and (1,1) shouldn't be in.
Lines on the perimeter are not considered to be in.
But even so, then 2,3 should always be in.
x,y1,1
TEST COOR ARRAY
1,1
1,3
4,3
4,1
1======================
IN
x,y2,2
TEST COOR ARRAY
1,1
1,3
4,3
4,1
1======================
IN
x,y2,3
TEST COOR ARRAY
1,1
1,3
4,3
4,1
0======================
OUT
x,y3,2
TEST COOR ARRAY
1,1
1,3
4,3
4,1
1======================
IN
x,y3,3
TEST COOR ARRAY
1,1
1,3
4,3
4,1
0======================
OUT
I have similar issues in using the other algorithms I found as well. If anyone could point me in the right direction, I'd appreciate it a lot thanks!
The Algorithm is based on the concept:
For any closed polygon, any straight line should intersect it's edges Even number of times (not taking line on line situation into account)...
think of it as (Enter, Exit, Enter, Exit, ...).
so, If you draw a Line from your Test-Point to basically infinity, depending on where it started, it should intersect Even times if the point was outside, and Odd if it was in!
As i see, by the test cases, and the "4 vertices" note: you are seeking
PointInRectangle(Coord c, Rect r) which is much simpler, faster and seems fit.
For your test case where (2,3) in (1,1)-(1,3)-(3,4)-(4,1) = TRUE
it is parallel on your bottom line, and probobally is "Disregarded",
but most likely, the intersections with your verticals are there because of Floating Point Inaccuracy.
you should split the Expression in parts, or Debug it as is to see what actual values are calculated There.

Action selection with softmax?

I know this might be a pretty stupid question to ask, but what the hell..
I at the moment trying to implement soft max action selector, which uses the boltzmann distribution.
Formula
What I am bit unsure about, is how how do known if you want to use a specific action?
I mean the function provides me with a probability?, but how do I use that to select which action I want to perform?
For some machine learning applications, there is a point where a set of raw outputs (like from a neural network) needs to be mapped to a set of probabilities, normalized to sum to 1.
In reenforcement learning, a set of available actions' weights might need to be mapped to a set of associated probabilities, which will then by used to randomly select the next action taken.
The Softmax function is commonly used to map output weights to a set of corresponding probabilities. A "temperature" parameter allows the selection policy to be tuned, interpolating between pure exploitation (a "greedy" policy, where the highest-weighted action is always chosen) and pure exploration (where each action has an equal probability of being chosen).
This is a simple example of using the Softmax function. Each "action" corresponds to one indexed entry in the vector<double> objects passed around in this code.
#include <iostream>
#include <iomanip>
#include <vector>
#include <random>
#include <cmath>
using std::vector;
// The temperature parameter here might be 1/temperature seen elsewhere.
// Here, lower temperatures move the highest-weighted output
// toward a probability of 1.0.
// And higer temperatures tend to even out all the probabilities,
// toward 1/<entry count>.
// temperature's range is between 0 and +Infinity (excluding these
// two extremes).
vector<double> Softmax(const vector<double>& weights, double temperature) {
vector<double> probs;
double sum = 0;
for(auto weight : weights) {
double pr = std::exp(weight/temperature);
sum += pr;
probs.push_back(pr);
}
for(auto& pr : probs) {
pr /= sum;
}
return probs;
}
// Rng class encapsulates random number generation
// of double values uniformly distributed between 0 and 1,
// in case you need to replace std's <random> with something else.
struct Rng {
std::mt19937 engine;
std::uniform_real_distribution<double> distribution;
Rng() : distribution(0,1) {
std::random_device rd;
engine.seed(rd());
}
double operator ()() {
return distribution(engine);
}
};
// Selects one index out of a vector of probabilities, "probs"
// The sum of all elements in "probs" must be 1.
vector<double>::size_type StochasticSelection(const vector<double>& probs) {
// The unit interval is divided into sub-intervals, one for each
// entry in "probs". Each sub-interval's size is proportional
// to its corresponding probability.
// You can imagine a roulette wheel divided into differently-sized
// slots for each entry. An entry's slot size is proportional to
// its probability and all the entries' slots combine to fill
// the entire roulette wheel.
// The roulette "ball"'s final location on the wheel is determined
// by generating a (pseudo)random value between 0 and 1.
// Then a linear search finds the entry whose sub-interval contains
// this value. Finally, the selected entry's index is returned.
static Rng rng;
const double point = rng();
double cur_cutoff = 0;
for(vector<double>::size_type i=0; i<probs.size()-1; ++i) {
cur_cutoff += probs[i];
if(point < cur_cutoff) return i;
}
return probs.size()-1;
}
void DumpSelections(const vector<double>& probs, int sample_count) {
for(int i=0; i<sample_count; ++i) {
auto selection = StochasticSelection(probs);
std::cout << " " << selection;
}
std::cout << '\n';
}
void DumpDist(const vector<double>& probs) {
auto flags = std::cout.flags();
std::cout.precision(2);
for(vector<double>::size_type i=0; i<probs.size(); ++i) {
if(i) std::cout << " ";
std::cout << std::setw(2) << i << ':' << std::setw(8) << probs[i];
}
std::cout.flags(flags);
std::cout << '\n';
}
int main() {
vector<double> weights = {1.0, 2, 6, -2.5, 0};
std::cout << "Original weights:\n";
for(vector<double>::size_type i=0; i<weights.size(); ++i) {
std::cout << " " << i << ':' << weights[i];
}
std::cout << "\n\nSoftmax mappings for different temperatures:\n";
auto softmax_thalf = Softmax(weights, 0.5);
auto softmax_t1 = Softmax(weights, 1);
auto softmax_t2 = Softmax(weights, 2);
auto softmax_t10 = Softmax(weights, 10);
std::cout << "[Temp 1/2] ";
DumpDist(softmax_thalf);
std::cout << "[Temp 1] ";
DumpDist(softmax_t1);
std::cout << "[Temp 2] ";
DumpDist(softmax_t2);
std::cout << "[Temp 10] ";
DumpDist(softmax_t10);
std::cout << "\nSelections from softmax_t1:\n";
DumpSelections(softmax_t1, 20);
std::cout << "\nSelections from softmax_t2:\n";
DumpSelections(softmax_t2, 20);
std::cout << "\nSelections from softmax_t10:\n";
DumpSelections(softmax_t10, 20);
}
Here is an example of the output:
Original weights:
0:1 1:2 2:6 3:-2.5 4:0
Softmax mappings for different temperatures:
[Temp 1/2] 0: 4.5e-05 1: 0.00034 2: 1 3: 4.1e-08 4: 6.1e-06
[Temp 1] 0: 0.0066 1: 0.018 2: 0.97 3: 0.0002 4: 0.0024
[Temp 2] 0: 0.064 1: 0.11 2: 0.78 3: 0.011 4: 0.039
[Temp 10] 0: 0.19 1: 0.21 2: 0.31 3: 0.13 4: 0.17
Selections from softmax_t1:
2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1
Selections from softmax_t2:
2 2 2 2 2 2 1 2 2 1 2 2 2 1 2 2 2 2 2 1
Selections from softmax_t10:
0 0 4 1 2 2 2 0 0 1 3 4 2 2 4 3 2 1 0 1

Shortest path in a grid between two points. With a catch

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.
You're overthinking it. :) Run a Breadth-First Search. The solution space is a binary tree, where each node branches into "right" or "down". From current point, generate the down point and right point, stuff their coordinates into a queue, repeat until at finish.
Without checking, something like this:
queue = [{ x: 0, y: 0, path: [] }] # seed queue with starting point
p = nil
do
raise NoSolutionException if p.empty? # solution space exhausted
p = queue.pop # get next state from the back of the queue
break if p.x == MAX_X - 1 && p.y == MAX_Y - 1 # we found final state
l = grid[p.x][p.y] # leap length
# add right state to the front of the queue
queue.unshift({x: p.x + l, y: p.y, path: p.path + [p] }) if p.x + l <= MAX_X
# add down state to the front of the queue
queue.unshift({x: p.x, y: p.y + l, path: p.path + [p] }) if p.y + l <= MAX_Y
end
puts p.path
Uglifying into C++ left as exercise for the reader :p
Build an unweighted directed graph:
There are NxM vertices. In what follows, vertex v corresponds to grid square v.
There is an arc from vertex u to v iff you can jump from grid square u to square v in a single move.
Now apply a shortest path algorithm from the top-right vertex to the bottom-left.
Finally, observe that you don't actually need to build the graph. You can simply implement the shortest path algoritm in terms of the original grid.
Start off with a brute force approach to get it to work, then optimize from there. The brute force is straight-forward: run it recursively. Take your two moves, recurse on those, and so on. Collect all the valid answers and retain the minimum. If the run time is too long, then you can optimize by a variety of means. For instance, some of the moves may be invalid (because they exceed a dimension of the grid) and can be eliminated, and so on. Keep optimizing until a worst case input runs at the desired speed.
Having said that, the performance requirements only make sense if you are using the same system and inputs, and even then there are some caveats. Big O notation is a much better way of analyzing the performance, plus it can point you to an algorithm and eliminate the need for profiling.