Shortest path in a grid between two points. With a catch - c++

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.

Related

How do I check on how many parts is a matrix divided in

I have a matrix made out of zeroes and ones. I need a way to see how many "zero blocks" there are. Here's a picture to better illustrate:
In this example there are 4 "zero blocks" divided by the black blocks (ones in the matrix).
As mentioned above, you can use dfs to find components in a graph. Here is a classic code example working on a grid where X means a wall and 0 means free space (black and white squares in your case):
#include <vector>
#include <string>
using Map = std::vector<std::string>;
using BoolMap = std::vector<std::vector<bool>>;
void dfs(BoolMap& visited, int x, int y)
{
if (x < 0 || y < 0 || y >= visited.size() || x >= visited[y].size())
return;
if (visited[y][x])
return;
visited[y][x] = true;
dfs(visited, x - 1, y);
dfs(visited, x + 1, y);
dfs(visited, x, y - 1);
dfs(visited, x, y + 1);
}
int main()
{
Map map;
map.emplace_back("0X00");
map.emplace_back("XXX0");
map.emplace_back("0X0X");
map.emplace_back("0X00");
BoolMap visited(map.size());
for (size_t y = 0; y < map.size(); y++)
{
visited[y].resize(map[y].size());
for (size_t x = 0; x < map[y].size(); x++)
{
// set visited to true if there is a wall
visited[y][x] = (map[y][x] == 'X');
}
}
size_t component_count = 0;
for (size_t y = 0; y < map.size(); y++)
{
for (size_t x = 0; x < map[y].size(); x++)
{
if (!visited[y][x])
{
dfs(visited, x, y);
component_count++;
}
}
}
std::cout << component_count << std::endl;
}
This code can be simplier if you know that your map is always a square one (map.size() can be used instead of map[y].size()). Also I loop through the map twice to check for a walls but if it is not too big there should not be a performance issue.
If you are already working with a boolean matrix and it is okay to change it you can just pass it as a visited parameter and the algorithm will work the same way.
I recommend taking a look at BFS & DFS for graph traversal. You can represent your matrix as a graph where every cell is connected to its neighbors in the 4 directions: North, South, East and west.
If you have a problem, let me know in the comments for more details.

How can I return all the shortest paths with tied weight using bellman-ford algorithm?

As title says, what I'm looking for is printing "all the shortest paths" that are tied by weight.
Example:
We have a graph with edges going from 0 -> 1 -> 3 that has 6 as weight, but we also have the path 0 -> 3 that has 6 as weight as well, the algorithm below only returns the first path, I would like to know if it is possible to return both or all the paths alike. Also is there a more efficient/elegant way of printing the shortest path. I took this code as example only, mine is very similar but prints only from source to last vertex.
There is a similar question answered here, but I could not understand the code since I'm familiar with c++.
#include <iostream>
#include <vector>
#include <iomanip>
#include <climits>
using namespace std;
// Data structure to store graph edges
struct Edge
{
int source, dest, weight;
};
// Recurive Function to print path of given vertex v from source vertex
void printPath(vector<int> const &parent, int v)
{
if (v < 0)
return;
printPath(parent, parent[v]);
cout << v << " ";
}
// Function to run Bellman Ford Algorithm from given source
void BellmanFord(vector<Edge> const &edges, int source, int N)
{
// count number of edges present in the graph
int E = edges.size();
// distance[] and parent[] stores shortest-path (least cost/path)
// information. Initially all vertices except source vertex have
// a weight of infinity and a no parent
vector<int> distance (N, INT_MAX);
distance[source] = 0;
vector<int> parent (N, -1);
int u, v, w, k = N;
// Relaxation step (run V-1 times)
while (--k)
{
for (int j = 0; j < E; j++)
{
// edge from u to v having weight w
u = edges[j].source, v = edges[j].dest;
w = edges[j].weight;
// if the distance to the destination v can be
// shortened by taking the edge u-> v
if (distance[u] != INT_MAX && distance[u] + w < distance[v])
{
// update distance to the new lower value
distance[v] = distance[u] + w;
// set v's parent as u
parent[v] = u;
}
}
}
// Run Relaxation step once more for Nth time to
// check for negative-weight cycles
for (int i = 0; i < E; i++)
{
// edge from u to v having weight w
u = edges[i].source, v = edges[i].dest;
w = edges[i].weight;
// if the distance to the destination u can be
// shortened by taking the edge u-> v
if (distance[u] != INT_MAX && distance[u] + w < distance[v])
{
cout << "Negative Weight Cycle Found!!";
return;
}
}
for (int i = 0; i < N; i++)
{
cout << "Distance of vertex " << i << " from the source is "
<< setw(2) << distance[i] << ". It's path is [ ";
printPath(parent, i); cout << "]" << '\n';
}
}
// main function
int main()
{
// vector of graph edges as per above diagram
vector<Edge> edges =
{
// (x, y, w) -> edge from x to y having weight w
{ 0, 1, 2 }, { 1, 3, 4 }, { 0, 3, 6 }
};
// Set maximum number of nodes in the graph
int N = 5;
// let source be vertex 0
int source = 0;
// run Bellman Ford Algorithm from given source
BellmanFord(edges, source, N);
return 0;
}
Looking at this more abstractly, you have something that can find a smallest thing, and you want to change it to also return all the other things equally small. (The same principles apply when looking for largest things. Sticking to "smallest", though, lends itself to an easier explanation.)
Many algorithms for finding an extreme thing have some part where they ask "is A more extreme than B". For example, you might see code like the following:
if ( A < B )
smallest = A;
Notice how this ignores ties (A == B) the same way it ignores worse results (A > B). Hence, you get only the first of the best results returned. So this is something to change. However, you cannot simply change A < B to A <= B, since that would replace B with A in the case of a tie, the same way it is replaced when A is a better result. (You'd get only the last of the best results returned.) The three cases (less than, equal to, and greater than) need to be dealt with separately.
Another aspect to look at is how the smallest thing is tracked. The above code snippet suggests that smallest has the same type as A; this is inadequate for tracking multiple solutions. You probably will want a container to track solutions. A vector is likely a reasonable choice.
Putting this together, the above code might become something more like the following (after changing the declaration of smallest):
if ( A < B ) {
smallest.clear();
smallest.push_back(A);
}
else if ( A == B ) {
smallest.push_back(A);
}
How can this be applied to Bellman-Ford?
Fortunately the key part of the code is relatively easy since there are comments documenting it. The harder part is changing the code to track multiple results, as there are two pieces of data updated when a shorter path is found. It looks like parent is the data that needs to be expanded. Here is a new declaration for it:
vector< vector<int> > parent (N);
This uses an empty vector instead of -1 to indicate "no parent". The check for shortest path can now become
if (distance[u] != INT_MAX) {
// if the distance to the destination v can be
// shortened by taking the edge u-> v
if (distance[u] + w < distance[v])
{
// update distance to the new lower value
distance[v] = distance[u] + w;
// forget the previous parent list.
parent[v].clear();
}
// if u-> v is a way to get the shortest
// distance to the destination v.
if (distance[u] + w == distance[v])
{
// add u as a possible parent for v
parent[v].push_back(u);
}
}
This differs a little from what the general approach in that there is no "else". It is the same logic, just arranged a bit differently. Note that when the first if clause is entered, the distance vector is updated so the second if clause is entered as well.
I think that handling the found paths is a separate (and not trivial) question, so I'll leave it to you to figure out how to update printPath(). I will, though, give a version that preserves the old output (just the first of the shortest paths) while receiving the new results. This is not a recommendation so much as an illustration relating the new data structure to the old.
// Recursive function to print the path of (just) the first given vertex from source vertex.
void printPath(vector< vector<int> > const &parent, vector<int> const &vlist)
{
if (vlist.empty())
return;
int v = vlist.front();
printPath(parent, parent[v]);
cout << v << " ";
}

How do I trace back a path using A* in C++? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I've been trying to implement A* for weeks so an enemy can chase a player in my game, and I can't get it to work. I've been working on it the entire weekend, and I even ended up scraping most of it and re writing it. I can draw a path from the starting location to the goal, but I can't trace it back, as in actually write down the path. I'm using Vector2f (ordered pair of floats) and Sprite from SFML but all the code there is pretty simple so you won't really need to understand it.
Edit: the problem is with Node.cameFrom. For some reason, it doesn't cout anything but the walls.
Here's Node.h
#ifndef NODE_H
#define NODE_H
#include <SFML/Graphics.hpp>
using namespace sf;
class Node {
public:
Vector2f pos;
// Distance traveled already to reach node
int level;
// Level + estimated dist to goal
int priority;
Node *cameFrom;
Node(Vector2f npos, int lv, Vector2f dest, Node *cf=nullptr);
bool operator == (const Node &nhs) const {
return nhs.priority == priority;
}
};
#endif // NODE_H
Node.cpp
#include "Node.h"
#include <SFML/Graphics.hpp>
#include <math.h>
#include <iostream>
using namespace std;
using namespace sf;
int estimatedDist(Vector2f pos, Vector2f dest) {
return abs(dest.x - pos.x) + abs(dest.y - pos.y);
}
Node::Node(Vector2f npos, int lv, Vector2f dest, Node *cf) {
cameFrom = cf;
level = lv;
pos = npos;
priority = level + estimatedDist(pos, dest);
}
Enemy.cpp pathfind functions
bool occupies(Vector2f pos, vector<Wall> walls) {
for (unsigned w = 0; w < walls.size(); w++) {
if (walls.at(w).collisionBox.getGlobalBounds().contains(pos.x * 32, pos.y * 32)) {
return true;
}
}
return false;
}
bool nFind(Node n, vector<Node> nodes) {
for (unsigned i = 0; i < nodes.size(); i++) {
if (nodes.at(i).pos == n.pos) {
return true;
}
}
return false;
}
void Enemy::pathFind(Vector2f dest, vector<Wall> walls) {
char fullMap[32][22];
vector<Node> openSet;
vector<Node> closedSet;
int xStart, yStart;
for (unsigned y = 0; y < 22; y++) {
for (unsigned x = 0; x < 32; x++) {
if (sprite.getGlobalBounds().top >= y * 32 && sprite.getGlobalBounds().top <= (y + 1) * 32) {
if (sprite.getGlobalBounds().left >= x * 32 && sprite.getGlobalBounds().left <= (x + 1) * 32) {
xStart = x;
yStart = y;
}
} if (occupies(Vector2f(x, y), walls)) {
fullMap[x][y] = '2';
} else {
fullMap[x][y] = ' ';
}
}
}
fullMap[int(dest.x)][int(dest.y)] = 'D';
Node *current = new Node(Vector2f(xStart, yStart), 0, dest);
fullMap[int(current->pos.x)][int(current->pos.y)] = '2';
openSet.push_back(*current);
while (openSet.size() > 0) {
sort(openSet.begin(), openSet.end(), sortByPriority());
*current = openSet.front();
if (current->pos == dest) {
cout << "We gots it ";
for (unsigned y = 0; y < 22; y++) {
for (unsigned x = 0; x < 32; x++) {
if (occupies(Vector2f(x, y), walls)) {
fullMap[x][y] = '2';
} else {
fullMap[x][y] = ' ';
}
}
}
while (current->cameFrom) {
fullMap[int(current->pos.x)][int(current->pos.y)] = 'P';
current = current->cameFrom;
for (unsigned y = 0; y < 22; y++) {
for (unsigned x = 0; x < 32; x++) {
cout << fullMap[x][y];
}
cout << endl;
}
cout << endl;
} for (unsigned y = 0; y < 22; y++) {
for (unsigned x = 0; x < 32; x++) {
cout << fullMap[x][y];
}
cout << endl;
}
cout << endl;
return;
}
openSet.erase(remove(openSet.begin(), openSet.end(), *current), openSet.end());
closedSet.push_back(*current);
fullMap[int(current->pos.x)][int(current->pos.y)] = '2';
vector<Node> neighbors;
neighbors.push_back(Node(Vector2f(current->pos.x - 1, current->pos.y - 1), current->level + 1, dest));
neighbors.push_back(Node(Vector2f(current->pos.x, current->pos.y - 1), current->level + 1, dest));
neighbors.push_back(Node(Vector2f(current->pos.x + 1, current->pos.y - 1), current->level + 1, dest));
neighbors.push_back(Node(Vector2f(current->pos.x + 1, current->pos.y), current->level + 1, dest));
neighbors.push_back(Node(Vector2f(current->pos.x + 1, current->pos.y + 1), current->level + 1, dest));
neighbors.push_back(Node(Vector2f(current->pos.x, current->pos.y + 1), current->level + 1, dest));
neighbors.push_back(Node(Vector2f(current->pos.x - 1, current->pos.y + 1), current->level + 1, dest));
neighbors.push_back(Node(Vector2f(current->pos.x - 1, current->pos.y), current->level + 1, dest));
for (unsigned i = 0; i < neighbors.size(); i++) {
if (nFind(neighbors.at(i), closedSet) ||
neighbors.at(i).pos.x > 22 ||
neighbors.at(i).pos.y > 32 ||
neighbors.at(i).pos.x < 0 ||
neighbors.at(i).pos.y < 0 ||
occupies(neighbors.at(i).pos, walls)) {
continue;
} if (!nFind(neighbors.at(i), openSet)) {
openSet.push_back(neighbors.at(i));
}
neighbors.at(i).cameFrom = current;
}
}
}
MCVE would help to try on our side (see zett42 comment).
So by just a quick look I can give you some pointers where to look during debugging, but no clear answer.
These lines looks highly suspicious:
Node *current = new Node(Vector2f(xStart, yStart), 0, dest);
// ^ no delete in source, will leak memory
*current = openSet.front();
// will overwrite the heap memory with copy constructor
// but the pointer will remain the same
// so all of your nodes will always have "cameFrom"
// pointing to this same memory.
Overall this code looks a bit complicated. Do you have the game with fixed square 32x22 tiles? Why "walls" vector then?
I would maintain only single global tile map as level (but the A* search then shouldn't damage it, rather create it's own copy for search, or rather to have new map with to-reach-costs, that would probably simplify the code a lot).
xStart, yStart can be computed directly, no need to iterate it every loop:
xStart = int(sprite.getGlobalBounds().left)>>5; // left/32
yStart = int(sprite.getGlobalBounds().top)>>5; // top/32
The bool operator == (const Node &nhs) const looks unhealthy, but it's not even used anywhere.
And to see if neighbour is in wall, you don't need to use the O(N) occupies, just test the map for == '2'? (I mean if the code is designed that way, I didn't verify it will work as expected if you change it right away in your code).
Overall I don't like that code, you can streamline that into shorter version, if you focus on what data you want to process and how, and stop moving objects back and forth through several lists. For A* IIRC you should need single sorted queue with insert_at to keep it sorted vs map field to mark which squares were already processed.
Are those Vector2f positions important, for example:
...
P#D
...
If player "P" stands in lower part of square ("#" is wall, "D" is destination), should the A* find the bottom path, or you need only "tile" accuracy and the upper path would be good too?
It's not clear to me from you question, whether you work with sub-tile accuracy or not, if not, then you can drop most of that Vector2f stuff and work only in the tile coordinates.
With sub-tile accuracy you can probably still drop most of it, but if actually tile has "32" size, and player is for example only "3" wide, so he can use the tile as some kind of "area" and move across it by different lines, avoiding in example above to go to full centre of middle tile, saving distance... Then you need to calculate those sub-tile positions somehow in to get at least roughly accurate "shortest" path.
When I was working on one game, we had linked list of nodes (classic math graph) instead of tiles, each node had it's "area radius", and after the shortest node-to-node path was found, another reiterative algorithm did few loops to move from node positions to some shadow-node position which was within the radius, but was closer to the other two shadow-nodes. After hitting max iterations, or the shadow-positions didn't change much (usually it took 3-5 iterations at most), it stopped "smoothing" the path and returned it. This way soldiers were running across desert in almost straight lines, while actually the waypoint nodes were like sparse grid with 20m area radius, so the soldier was actually going only like 2-3 nodes away and starting/ending far away from node centre going almost zig-zag in the node graph itself.
For every tile, you need its cost (cost of getting there plus heuristic), and the identify of the neighbouring tile from which you reached it.
The algorithm has a "balloon" of points round the start point, and the best point is analysed first. So if the path is simple, the balloon is very elongated. If it is convoluted, the balloon is roundish, and many paths get abandoned because hemmed in by walls and already-visited tiles.

Algorithm to divide a black-and-white chocolate bar

Problem description:
There's a chocolate bar that consists of m x n squares. Some of the squares are black, some are white. Someone breaks the chocolate bar along its vertical axis or horizontal axis. Then it is broken again along its vertical or horizontal axis and it's being broken until it can broken into a single square or it can broken into squares that are only black or only white. Using a preferably divide-and-conquer algorithm, find the number of methods a chocolate bar can be broken.
Input:
The first line tells you the m x n dimensions of the chocolate bar. In the next m lines there are n characters that tell you how does the chocolate bar look. Letter w is a white square, letter b is a black square.
for example:
3 2
bwb
wbw
Output:
the number of methods the chocolate bar can be broken:
for the example above, it's 5 (take a look at the attached picture).
I tried to solve it using an iterative approach. Unfortunately, I couldn't finish the code as I'm not yet sure how to divide the the halves (see my code below). I was told that an recursive approach is much easier than this, but I have no idea how to do it. I'm looking for another way to solve this problem than my approach or I'm looking for some help with finishing my code.
I made two 2D arrays, first for white squares, second for black squares. I'm making a matrix out of the squares and if there's a chocolate of such or such color, then I'm marking it as 1 in the corresponding array.
Then I made two arrays of the two cumulative sums of the matrices above.
Then I created a 4D array of size [n][m][n][m] and I made four loops: first two (i, j) are increasing the size of an rectangular array that is the size of the searching array (it's pretty hard to explain...) and two more loops (k, l) are increasing the position of my starting points x and y in the array. Then the algorithm checks using the cumulative sum if in the area starting at position kxl and ending at k+i x l+j there is one black and one white square. If there is, then I'm creating two more loops that will divide the area in half. If in the two new halves there are still black and white squares, then I'm increasing the corresponding 4D array element by the number of combinations of the first halve * the number of combinations of the second halve.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
int counter=0;
int n, m;
ifstream in;
in.open("in.txt");
ofstream out;
out.open("out.txt");
if(!in.good())
{
cout << "No such file";
return 0;
}
in >> n >> m;
int whitesarray[m][n];
int blacksarray[m][n];
int methodsarray[m][n][m][n];
for(int i=0; i<m; i++)
{
for(int j=0; j<n; j++)
{
whitesarray[i][j] = 0;
blacksarray[i][j] = 0;
}
}
while(in)
{
string colour;
in >> colour;
for (int i=0; i < colour.length(); i++)
{
if(colour[i] == 'c')
{
blacksarray[counter][i] = 1;
}
if(colour[i] == 'b')
{
whitesarray[counter][i] = 1;
}
}
counter++;
}
int whitessum[m][n];
int blackssum[m][n];
for (int i=0; i<m; i++)
{
for (int j=0; j<n; j++)
{
if(i-1 == -1 && j-1 == -1)
{
whitessum[i][j] = whitesarray[i][j];
blackssum[i][j] = blacksarray[i][j];
}
if(i-1 == -1 && j-1 != -1)
{
whitessum[i][j] = whitessum[i][j-1] + whitesarray[i][j];
blackssum[i][j] = blackssum[i][j-1] + blacksarray[i][j];
}
if(j-1 == -1 && i-1 != -1)
{
whitessum[i][j] = whitessum[i-1][j] + whitesarray[i][j];
blackssum[i][j] = blackssum[i-1][j] + blacksarray[i][j];
}
if(j-1 != -1 && i-1 != -1)
{
whitessum[i][j] = whitessum[i-1][j] + whitessum[i][j-1] - whitessum[i-1][j-1] + whitesarray[i][j];
blackssum[i][j] = blackssum[i-1][j] + blackssum[i][j-1] - blackssum[i-1][j-1] + blacksarray[i][j];
}
}
}
int posx=0;
int posy=0;
int tempwhitessum=0;
int tempblackssum=0;
int k=0, l=0;
for (int i=0; i<=m; i++)
{
for (int j=0; j<=n; j++) // wielkosc wierszy
{
for (posx=0; posx < m - i; posx++)
{
for(posy = 0; posy < n - j; posy++)
{
k = i+posx-1;
l = j+posy-1;
if(k >= m || l >= n)
continue;
if(posx==0 && posy==0)
{
tempwhitessum = whitessum[k][l];
tempblackssum = blackssum[k][l];
}
if(posx==0 && posy!=0)
{
tempwhitessum = whitessum[k][l] - whitessum[k][posy-1];
tempblackssum = blackssum[k][l] - blackssum[k][posy-1];
}
if(posx!=0 && posy==0)
{
tempwhitessum = whitessum[k][l] - whitessum[posx-1][l];
tempblackssum = blackssum[k][l] - blackssum[posx-1][l];
}
if(posx!=0 && posy!=0)
{
tempwhitessum = whitessum[k][l] - whitessum[posx-1][l] - whitessum[k][posy-1] + whitessum[posx-1][posy-1];
tempblackssum = blackssum[k][l] - blackssum[posx-1][l] - blackssum[k][posy-1] + blackssum[posx-1][posy-1];
}
if(tempwhitessum >0 && tempblackssum > 0)
{
for(int e=0; e<n; e++)
{
//Somehow divide the previously found area by two and check again if there are black and white squares in this area
}
for(int r=0; r<m; r++)
{
//Somehow divide the previously found area by two and check again if there are black and white squares in this area
}
}
}
}
}}
return 0;
}
I strongly recommend recursion for this. In fact, Dynamic Programming (DP) would also be very useful, especially for larger bars. Recursion first ...
Recursion
Your recursive routine takes a 2-D array of characters (b and w). It returns the number of ways this can be broken.
First, the base cases: (1) if it's possible to break the given bar into a single piece (see my comment above, asking for clarification), return 1; (2) if the array is all one colour, return 1. For each of these, there's only one way for the bar to end up -- the way it was passed in.
Now, for the more complex case, when the bar can still be broken:
total_ways = 0
for each non-edge position in each dimension:
break the bar at that spot; form the two smaller bars, A and B.
count the ways to break each smaller bar: count(A) and count(B)
total_ways += count(A) * count(B)
return total_ways
Is that clear enough for the general approach? You still have plenty of coding to do, but using recursion allows you to think of only the two basic ideas when writing your function: (1) How do I know when I'm done, and what trivial result do I return then? (2) If I'm not done, how do I reduce the problem?
Dynamic Programming
This consists of keeping a record of situations you've already solved. The first thing you do in the routine is to check your "data base" to see whether you already know this case. If so, return the known result instead of recomputing. This includes the overhead of developing and implementing said data base, probably a look-up list (dictionary) of string arrays and integer results, such as ["bwb", "wbw"] => 5.

program crashes on certain inputs

I have tried writing this code to output an odd-order magic square based on user input of an odd number. When I enter 1 or 3, it works fine. Whenever I enter anything above that such as 5, 7, 9, 11, etc the program crashes the moment I press enter. I've reviewed my code and I can't pinpoint where the problem is. I get no error messages.
Small note: if you know what a magic square is, my algorithm here (given to us by the professor in English to translate to C++) does not output the correct values since they don't all add up to the same number.
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
int n; //n = order
cout << "Enter an odd integer for the order of the Magic Square: ";
cin >> n;
cout << endl;
if(n%2 == 0) //only allows program to accept odd numbers
{
cout << "The number you have entered is not odd" << endl;
return 0;
}
int x, y; //x and y access the columns and rows of the following matrix
int magicsquare[n][n]; //creates a n by n matrix to set up magic square
int counter, square = n*n; //square is upper boundary
for(x=0; x<n; x++) //initialize all spaces in matrix with zeros
{
for(y=0; y<n; y++)
magicsquare[x][y] = 0;
}
/*Beginning of the magic square algorithm*/
x = 0, y = n/2; //initialize algorithm at the middle column of the top row
for (counter = 1; counter <= square; counter++) //magic square will contain the integers from 1 to n squared
{
magicsquare[x][y] = counter; //places current counter number at current position in the matrix or square
x--; //moves position diagonally up
y++; //and to the right
/*If a move takes you above the top row in the jth column, move to the bottom of the jth column*/
if(x<0)
x = n - 1;
/*If a move takes you outside to the right of the square in the ith row, move to the left side of the ith row*/
else if(y==n)
y = 0;
/*If a move takes you to an already filled square or if you move out of the square at the upper right
hand corner, move immediately below position of previous number*/
else if((magicsquare[x][y] != 0) || (x<0 && y==n))
{
y--; //move one space to the left back into the square
x = x+2; //move two spots down into the square and below previous number
}
}
for(x=0; x<n; x++)
{
for(y=0; y<n; y++)
cout << setw(5) << magicsquare[x][y];
cout << endl;
}
return 0;
}
I can't follow the logic in my head to know if this can ever actually happen, but in this code:
if(x<0)
x = n - 1;
/*If a move takes you outside to the right of the square in the ith row, move to the left side of the ith row*/
else if(y==n)
y = 0;
If both conditions would have been true, you won't fix up y and the next iteration you'll run off the end of the matrix.
Also note that int magicsquare[n][n]; is a compiler extension and not supported by the C++ standard, since n is not a compile time constant. You almost certainly want to use vector instead.
The following is illegal:
int magicsquare[n][n];
Did you ignore errors, or are you using a compiler that doesn't give errors at all? I suggest you to use an IDE that hints you when a mistake is made, so you can easily see your mistake. Please do not use notepad to write C++, that is horrible.
Fixed version:
int** magicsquare = new int*[n]; //creates a n by n matrix to set up magic square
for(int i = 0; i < n+1; ++i)
magicsquare[i] = new int[n];
Now, together with Mark B's hint, you will get this running up in no time.
Do not forget to cleanup magicsquare by the way using delete.
So I don't really know anything about magic squares. But I think that this is the behavior that you are trying to achieve:
for (int counter = 1, x = 0, y = (n / 2); counter <= n * n; ++counter){
magicsquare[x][y] = counter; //places current counter number at current position in the matrix or square
if (counter % n == 0){ //moves down into the square and below previous number
x = (x + 1) % n;
}
else //moves position diagonally up and to the right
{
x = (x + n - 1) % n;
y = (y + 1) % n;
}
}
Two additional points:
Until we can use the Array Extensions Technical Specification I think you should avoid declaring C99's runtime-sized arrays in your code. Even though gcc will allow it. You might look into doing something like: vector<vector<int>> magicsquare(n, vector<int>(n));
This doesn't match the behavior illustrated by Wikipedia's article but you can get there by tweaking the start values and order of indexing.