Unexpected result when resizing Vector of Vector of OpenCV Mat - c++

I am on Ubuntu 16.04, GCC 5.4, latest OpenCV. Suppose I have a vector of double
std::vector<std::vector<double>> vecvecdouble;
vecvecdouble.resize(3, std::vector<double>(3, 0));
for (int j = 0; j < 3; j++){
for (int i = 0; i < 3; i++){
if (i == 0){
vecvecdouble[i][j] = 1;
vecvecdouble[i][j] = 1;
}
if (i == 1){
vecvecdouble[i][j] = 2;
vecvecdouble[i][j] = 2;
}
if (i == 1 && j == 0){
std::cout << vecvecdouble[i - 1][j] << std::endl;
std::cout << vecvecdouble[i][j] << std::endl;
std::cout << vecvecdouble[i + 1][j] << std::endl;
}
}
}
It prints
1
2
0
as expected. However, if I do the same thing with OpenCV cv::mat
std::vector<std::vector<cv::Mat>> vecvecmat;
vecvecmat.resize(
3, std::vector<cv::Mat>(3, cv::Mat(4, 4, CV_64FC1, cv::Scalar(0.0))));
for (int j = 0; j < 3; j++){
for (int i = 0; i < 3; i++){
if (i == 0){
vecvecmat[i][j].at<double>(0, 0) = 1;
vecvecmat[i][j].at<double>(0, 1) = 1;
}
if (i == 1){
vecvecmat[i][j].at<double>(0, 0) = 2;
vecvecmat[i][j].at<double>(0, 1) = 2;
}
if (i == 1 && j == 0){
std::cout << vecvecmat[i - 1][j] << std::endl;
std::cout << vecvecmat[i][j] << std::endl;
std::cout << vecvecmat[i + 1][j] << std::endl;
}
}
}
It prints
[2, 2, 0, 0;
0, 0, 0, 0;
0, 0, 0, 0;
0, 0, 0, 0]
[2, 2, 0, 0;
0, 0, 0, 0;
0, 0, 0, 0;
0, 0, 0, 0]
[2, 2, 0, 0;
0, 0, 0, 0;
0, 0, 0, 0;
0, 0, 0, 0]
which is completely unexpected because I am expecting it to print
[1, 1, 0, 0;
0, 0, 0, 0;
0, 0, 0, 0;
0, 0, 0, 0]
[2, 2, 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]
However, if I don't try to resize the vector in one single line and go through two for loops it actually returns the expected result
std::vector<std::vector<cv::Mat>> vecvecmat;
vecvecmat.resize(3);
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++){
cv::Mat mymat = cv::Mat(4, 4, CV_64FC1, cv::Scalar(0.0));
vecvecmat[i].push_back(mymat);
}
}
for (int j = 0; j < 3; j++){
for (int i = 0; i < 3; i++){
if (i == 0){
vecvecmat[i][j].at<double>(0, 0) = 1;
vecvecmat[i][j].at<double>(0, 1) = 1;
}
if (i == 1){
vecvecmat[i][j].at<double>(0, 0) = 2;
vecvecmat[i][j].at<double>(0, 1) = 2;
}
if (i == 1 && j == 0){
std::cout << vecvecmat[i - 1][j] << std::endl;
std::cout << vecvecmat[i][j] << std::endl;
std::cout << vecvecmat[i + 1][j] << std::endl;
}
}
}
What is wrong with the line?
vecvecmat.resize(3, std::vector<cv::Mat>(3, cv::Mat(4, 4, CV_64FC1, cv::Scalar(0.0))));

The documentation for the copy constructor for cv::Mat says (emphasis mine):
Parameters
m Array that (as a whole or partly) is assigned to the constructed matrix. No data is copied by these constructors. Instead, the header pointing to m data or its sub-array is constructed and associated with it. The reference counter, if any, is incremented. So, when you modify the matrix formed using such a constructor, you also modify the corresponding elements of m. If you want to have an independent copy of the sub-array, use Mat::clone().
The initial matrix that you construct in your call to std::vector::resize is being copied into each element of the vector with this copy constructor*, so they are all pointing to the same data. When you modify one matrix, you modify all of them.
* or maybe with operator=, which does the same thing (I'm not sure which, but it doesn't affect the result)
I suggest initializing your vector like this:
std::vector<std::vector<cv::Mat>> vecvecmat;
vecvecmat.resize(3, std::vector<cv::Mat>());
for(auto& v : vecvecmat)
{
for(std::size_t i = 0; i < 3; ++i)
{
v.emplace_back(4, 4, CV_64FC1, cv::Scalar(0.0));
}
}

Related

Unable to get BFS algorithm to work properly in c++

I'm creating a dungeon/rouge-like game in c++ and am trying to implement pathfinding.
The issue I am having is that when the player moves more than two times the adjacency matrix doesn't generate properly. What happens is that every place that the player has been turning to a zero which signifies that you cant go there. I am trying to regenerate the matrix every time the player moves but it doesn't seem to want to. here is the code.
#include <iostream>
#include <vector>
using namespace std;
int main ()
{
int World_Width = 10;
int World_Height = 10;
int Player_X = 1;
int Player_Y = 2;
int Enemy_X = 8;
int Enemy_Y = 1;
int X = Player_X;
int Y = Player_Y;
int Player_Health = 10;
int Enemy_Health = 5;
int Player_Damage = 1;
int Enemy_Damage = 1;
bool PlayerIsAlive = true;
bool EnemyIsAlive = true;
int World[World_Width][World_Height] =
{
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 1, 0, 4, 1},
{1, 2, 0, 0, 0, 0, 1, 0, 0, 1},
{1, 0, 0, 1, 1, 0, 1, 0, 0, 1},
{1, 0, 0, 1, 1, 0, 1, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 1, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 1, 0, 0, 1},
{1, 1, 1, 1, 0, 0, 1, 0, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
};
int NodeMap[World_Width][World_Height] =
{
{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, 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,},
};
int NeighborMap[World_Width][World_Height] =
{
{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, 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,},
};
int NodeNumber = 1;
for (int h = 0; h < World_Height; h++)
{
for (int d = 0; d < World_Width; d++)
{
NodeMap[h][d] = NodeNumber;
NodeNumber ++;
}
}
vector<int> queue {};
vector<int> visited {};
string input;
bool AddNode = true;
int QueueNumber = 0;
int Max_iterations = 1000;
int TurnCount = 0;
bool run = true;
while (run)
{
TurnCount += 1;
//Prints out the map
for (int h = 0; h < World_Height; h++)
{
for (int d = 0; d < World_Width; d++)
{
cout << World[h][d] << " ";
}
cout << "\n";
}
cout << "\n";
cout << "Player health: " << Player_Health << "\n";
cout << "Enemy health: " << Enemy_Health << "\n" << "\n";
cout << "What do you want to do; move, attack, or open a chest: ";
//Player movement
cin >> input;
if (input == "w" && World[Player_Y - 1][Player_X] == 0)
{
World[Player_Y ][Player_X] = 0;
Player_Y--;
World[Player_Y][Player_X] = 2;
}
if (input == "a" && World[Player_Y][Player_X - 1] == 0)
{
World[Player_Y][Player_X] = 0;
Player_X--;
World[Player_Y][Player_X] = 2;
}
if (input == "s" && World[Player_Y + 1][Player_X] == 0)
{
World[Player_Y][Player_X] = 0;
Player_Y++;
World[Player_Y][Player_X] = 2;
}
if (input == "d" && World[Player_Y][Player_X + 1] == 0)
{
World[Player_Y][Player_X] = 0;
Player_X++;
World[Player_Y][Player_X] = 2;
}
if (input == "e")
{
if (Player_X == Enemy_X && Player_Y - 1 == Enemy_Y)
{
Enemy_Health -= Player_Damage;
}
if (Player_X == Enemy_X - 1 && Player_Y == Enemy_Y)
{
Enemy_Health -= Player_Damage;
}
if (Player_X == Enemy_X && Player_Y + 1 == Enemy_Y)
{
Enemy_Health -= Player_Damage;
}
if (Player_X == Enemy_X + 1 && Player_Y == Enemy_Y)
{
Enemy_Health -= Player_Damage;
}
}
if ( input == "stop")
{
Player_Health = 0;
}
queue.clear();
QueueNumber = 0;
X = Player_X;
Y = Player_Y;
NeighborMap[Y][X] = 0;
//BFS - Breadth First Search: Pathfinding Algorithim
for (int iterations = 0; iterations < Max_iterations; iterations++)
{
if (World[Y - 1][X] == 0 || World[Y - 1][X] == 4)
{
AddNode = true;
for (int i = 0; i < visited.size(); i++)
{
if (visited[i] == NodeMap[Y - 1][X])
{
AddNode = false;
}
}
if (AddNode)
{
queue.push_back(NodeMap[Y - 1][X]);
NeighborMap[Y - 1][X] = NodeMap[Y][X];
}
}
if (World[Y][X - 1] == 0 || World[Y][X - 1] == 4)
{
AddNode = true;
for (int i = 0; i < visited.size(); i++)
{
if (visited[i] == NodeMap[Y][X - 1])
{
AddNode = false;
}
}
if (AddNode)
{
queue.push_back(NodeMap[Y][X - 1]);
NeighborMap[Y][X - 1] = NodeMap[Y][X];
}
}
if (World[Y + 1][X] == 0 || World[Y + 1][X] == 4)
{
AddNode = true;
for (int i = 0; i < visited.size(); i++)
{
if (visited[i] == NodeMap[Y + 1][X])
{
AddNode = false;
}
}
if (AddNode)
{
queue.push_back(NodeMap[Y + 1][X]);
NeighborMap[Y + 1][X] = NodeMap[Y][X];
}
}
if (World[Y][X + 1] == 0 || World[Y][X + 1] == 4)
{
AddNode = true;
for (int i = 0; i < visited.size(); i++)
{
if (visited[i] == NodeMap[Y][X + 1])
{
AddNode = false;
}
}
if (AddNode)
{
queue.push_back(NodeMap[Y][X + 1]);
NeighborMap[Y][X + 1] = NodeMap[Y][X];
}
}
for (int h = 0; h < World_Height; h++)
{
for (int d = 0; d < World_Width; d++)
{
if(NodeMap[h][d] == queue[QueueNumber])
{
X = d;
Y = h;
}
}
}
visited.push_back(queue[QueueNumber]);
QueueNumber++;
}
//Enemy AI
if (Enemy_Health == 0)
{
if (EnemyIsAlive)
{
World[Enemy_Y][Enemy_X] = 0;
}
EnemyIsAlive = false;
}
if (Player_Health == 0)
{
run = false;
}
}
system("clear");
for (int h = 0; h < World_Height; h++)
{
for (int d = 0; d < World_Width; d++)
{
cout << NeighborMap[h][d] << " ";
}
cout << "\n";
}
cout << "\n";
for (int h = 0; h < World_Height; h++)
{
for (int d = 0; d < World_Width; d++)
{
cout << NodeMap[h][d] << " ";
}
cout << "\n";
}
cout << "GAME OVER" << "\n" << "Thanks for Playing!";
}

adding two binary numbers(integer array)

I have done this program to add two binary numbers of the same length stored in an integer array and store the sum in a new integer array. But due to some logical error, it does not show the desired output.
#include <conio.h>
#include <iostream.h>
void main() {
clrscr();
int a[] = {1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1,
1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1};
int b[] = {1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1,
1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0};
int temp[100];
int carry = 0, p = 35;
for(int i = 34; i >= 0; i--) {
if(a[i] + b[i] + carry == 0) {
temp[p] = 0;
carry = 0;
p--;
}
if((a[i] + b[i] + carry) == 1) {
temp[p] = 1;
carry = 0;
p--;
}
if((a[i] + b[i] + carry) == 2) {
temp[p] = 0;
carry = 1;
p--;
}
if((a[i] + b[i] + carry) > 2) {
temp[p] = 1;
carry = 1;
p--;
}
}
for(int pop = 0; pop < 36; pop++) cout << temp[pop];
getch();
}
the expected output is:
110100101001100101101010110101011111
actual output is:
101100110011011101011011101011011111
if((a[i] + b[i] + carry) == 2) {
temp[p] = 0;
carry = 1;
p--;
}
if((a[i] + b[i] + carry) > 2) {
temp[p] = 1;
carry = 1;
p--;
}
Go through this with a[i] = 1, b[i] = 1, carry = 0
This will trigger the first if here as it should, which then sets carry to 1.
Then the second if will find the configuration a[i] = 1, b[i] = 1, carry = 1 which triggers it despite the original configuration not fitting, causing the bug.
For the future, please get to know how to use a debugger, or at least how to include some debugging console prints in the program. Set stop points or prints where there would be nodes in a corresponding diagram to see if the flow takes the right route.
With prints:
for(int i = 34; i >= 0; i--) {
cout << "entered loop" << endl;
if(a[i] + b[i] + carry == 0) {
temp[p] = 0;
carry = 0;
p--;
cout << "recognized case 1" << endl;
}
if((a[i] + b[i] + carry) == 1) {
temp[p] = 1;
carry = 0;
p--;
cout << "recognized case 2" << endl;
}
if((a[i] + b[i] + carry) == 2) {
temp[p] = 0;
carry = 1;
p--;
cout << "recognized case 3" << endl;
}
if((a[i] + b[i] + carry) > 2) {
temp[p] = 1;
carry = 1;
p--;
cout << "recognized case 4" << endl;
}
}
(But using the debugger is better than prints.)
The issue in your code is you have a set of separate if statements which each modify carry, if carry is changed in such a way to alter the result of the subsequent if statements then multiple if statement bodies will be executed.
The simple fix is to change your last 3 ifs to else if.
You also need to add the final carry bit to your output:
temp[0] = carry;
for(int pop = 0; pop < 36; pop++) cout << temp[pop];
However your code could be greatly simplified using a swtich statement. Simpler code is generally less buggy and easier to understand:
for(int i = 34; i >= 0; i--, p--) {
switch(a[i] + b[i] + carry) {
case 0:
temp[p] = 0;
carry = 0;
break;
case 1:
temp[p] = 1;
carry = 0;
break;
case 2:
temp[p] = 0;
carry = 1;
break;
case 3:
temp[p] = 1;
carry = 1;
break;
default:
// should never be reached with inputs of 0 or 1
throw std::invalid_argument("invalid input");
}
}
This code could be simplified even further using bit manipulations to remove all branches and set the bits directly but I'll leave that as an exercise for the reader hint.

Distance transform :

Kindly help me with the working of Distance transform and rectify the errors. I have tried Borgefors' method which has defined values for Eucledian measure. I get all zeros as output.
Below is the code which i have tried.
int _tmain(int argc, _TCHAR* argv[])
{
Mat v = imread("ref.png", 0);
imshow("input", v);
Mat forward = (Mat_<uchar>(5, 5) << 0, 11, 0, 11, 0, 11, 7, 5, 7, 11, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
Mat backward = (Mat_<uchar>(5, 5) << 0,0,0,0,0, 0,0,0,0,0, 0, 0, 0, 5, 0, 11, 7, 5, 7, 11, 0, 11, 0, 11, 0);
Mat op = cv::Mat::zeros(v.size(), CV_32FC1);
cout << forward;
cout << backward;
int r = v.rows;
int c = v.cols;
float min=100, x = 0;
int size = 3;
int lim = size / 2;
int a, b;
for (int i = lim; i <= r-1-lim; i++)
{
for (int j = lim; j <= c-1-lim; j++)
{
for (int k = -lim; k <= lim; k++)
{
for (int l = -lim; l <= lim; l++)
{
a = (v.at<uchar>(i + k, j + l));
b=(forward.at<uchar>(k + lim, l + lim));
x = a + b;
if (x>0 && min> x)
min = x;
}
}
op.at<float>(i, j) = min;
}
}
cout << min;
for (int i = (r-1-lim); i >lim; i--)
{
for (int j = (c-1-lim); j >lim; j--)
{
for (int k = -lim; k <= lim; k++)
{
for (int l = -lim; l <= lim; l++)
{
a = (v.at<uchar>(i + k, j + l));
b = (forward.at<uchar>(k + lim, l + lim));
x = a + b;
if (x >0 && min> x) min = x;
}
}
op.at<float>(i, j) = min;
}
}
cout << op;
Mat res = cv::Mat::ones(v.size(), CV_8UC1);
normalize(op, res, 0, 255, NORM_MINMAX);
imshow("output",res);
waitKey(0);
return 0;
}
Which is the best method and why it is the best way to implement Distance Transform?
Here is how to fix your code:
Apply the backward mask in the backward loop, you apply the same mask there as in the forward loop.
Use only the defined weights, the values in the mask where you wrote 0 are not part of the mask. Those pixels don't have a distance of 0!
As for your second question, it's probably out of scope for SO. But what the best method is depends very much on the goal. You have a fast and relatively accurate method here, there are other methods that are exact but more expensive.

How do you find out in which sub-grid a 2D array element is located

C++ beginner here. I'm currently trying to make a sudoku solving program, so I have to check whether a value exists in the 9x9 box it's located in.
This is my code for checking if the element follows the rules:
//constants for rows and columns of the sudoku puzzle, can be changed
const int ROWS = 9;
const int COLS = 9;
bool follows_rule(int grid[ROWS][COLS], int rowIndex, int colIndex, int value){
for (int i = 0; i < COLS; i++){
if (grid[rowIndex][i] == value) //check if there are any other values on the same column
return false;
if (grid[i][colIndex] == value) //or the same row
return false;
}
//to-do: check if another equal value exists in the 9x9 box
return true;
}
//returns true if another element has the same value as "value", false otherwise
bool exists_in_2d_array(int grid[ROWS][COLS], int value){
for (int x = 0; x < ROWS / 3; x++)
{
for (int y = 0; y < COLS / 3; y++)
{
if (grid[x][y] == value)
{
return true;
}
}
}
return false;
}
My idea was to find out which 9x9 box the coordinates of the current element lead to, then put that 9x9 grid in another 2D array and check if the element's value exists somewhere else in the grid. I don't really know how, though.
The SUDOKU rules require that the digit is used only once:
Rule 1: in each row
Rule 2: in each column
Rule 3: in each 3x3 subgrid of the 9x9 grid
Function follows_rule() checks for a given grid position, if the value would be allowed or not. For the moment it checks only rules 1 and 2. I propose you the following code for rule 3:
bool follows_rule(int grid[ROWS][COLS], int rowIndex, int colIndex, int value){
for (int i = 0; i < COLS; i++){
if (grid[rowIndex][i] == value)
return false;
if (grid[i][colIndex] == value) // ATTENTION THIS IS OK BECAUSE ROWS==COLS !!
return false;
}
// Check if another equal value exists in the 3x3 box
int sgc = (colIndex / 3) * 3; // in wich subgrid are we ?
int sgr = (rowIndex / 3) * 3;
// check all the elements of the 3x3 grid startic at sgr, sgc
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
if (grid[sgr + i][sgc + j] == value)
return false;
return true;
}
You can test the 3x3 verification with the following code:
int sudoku[ROWS][COLS] = {
{ 1, 0, 0, 0, 0, 0, 0, 8, 0 },
{ 0, 0, 2, 0, 0, 0, 0, 0, 0 },
{ 0, 3, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 1, 3, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 5, 0, 0, 0 },
{ 0, 0, 0, 0, 8, 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 }
};
if (follows_rule(sudoku, 1, 0, 1) == false
&& follows_rule(sudoku, 1, 0, 4) == true
&& follows_rule(sudoku, 5, 5, 8) == false
&& follows_rule(sudoku, 5, 5, 1) == false
&& follows_rule(sudoku, 5, 5, 7) == true)
cout << "Test ok !" << endl;
else cout << "Tests failed" << endl;
Accepted answer does not calculate the subgrids correctly , sgc and and sgr needs to be multiplied with 3 too after division to crrectly identify the subgrid vertices
public boolean isValidEntry(char[][] board, int row , int col,char val)
{
for(int i = 0 ; i < 9 ;i++){
if(board[row][i] == val)
return false;
}
for(int j = 0 ; j < 9 ;j++){
if(board[j][col] == val)
return false;
}
int sgc = col / 3; // in wich subgrid are we ?
int sgr = row / 3;
// check all the elements of the 3x3 grid startic at sgr, sgc
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++)
if (board[(3*sgr) + i][(3*sgc) + j] == val)
return false;
}
return true;
}

Dijkstra's Shortest Path Algorithm issue

So I'm trying to code Dijkstra's shortest path algorithm in C++. For some reason, it's not adding up the distances correctly...
Here is what I have so far for code. You can ignore the section where I am copying the path to the stack because I know it's not complete yet. Any ideas where I'm going wrong?
#include <fstream>
#include "matrix.h"
#include <list> // STL container
using namespace std;
//---------------------------------------------------------------------------
const int INFIN = 100000;
const int size = 8;
double a[] = {
0, 0, 5, 0, 0, 2, 3, 0, //length matrix ( #9, page 276)
4, 0, 6, 0, 7, 0, 5, 0,
0, 3, 0, 9, 2, 6, 0, 7,
3, 0, 2, 0, 1, 0, 7, 6,
0, 5, 0, 1, 0, 0, 4, 0,
0, 0, 2, 0, 8, 0, 9, 0,
1, 2, 3, 0, 0, 6, 0, 0,
5, 0, 8, 0, 2, 0, 9, 0
};
// Global declarations for L Matrix and begin and end node
Matrix L(size,size,a); //length matrix
int begin, end;
void path(long* D, int* P); //function prototype for shortest path algorithm
Matrix Warshall(Matrix M);
void main()
{
int i, u;
long D [size+1]; //distance functions
int P [size+1]; //prior vertices in path
cout << "\nLength Matrix: " << L;
cout << "\nPaths that exist:" << Warshall(L);
for (i=1; i <= size; i++) {
D[i] = INFIN; //initialize distance functions
P[i] = 0;
}
cout << "\nFind distance from vertex #";
cin >> begin;
cout << " to vertex #";
cin >> end;
if (begin == end) exit(1);
if (begin < 0 || end < 0) exit(1);
if (begin > size || end > size) exit(1);
path(D,P);
cout << "\nShortest distance from \nvertex #"
<< begin << " to vertex #"
<< end << " is " << D[end];
// u = end;
list<int> stack; // work path backwards
while (1) {
stack.push_front(end);
stack.push_front(begin);
break;
}
cout << "\nusing path:\n";
cout << "\t" << stack.front();
stack.pop_front();
while (stack.size()) {
cout << " -> " << stack.front();
stack.pop_front();
}
getch();
}
void path(long* D, int* P) {
int i, u, dist;
int U[size+1];
for (i=1; i <= size; i++)
U[i] = 0;
U[begin] = 1; // add first vertex;
D[begin] = 0;
u = begin;
do { // until find end vertex
for (i = 1; i <= size; i++) {
dist = L.element(u,i); // distance from u to i
if( D[u] + dist < D[i]) {
D[i] = D[u] + dist;
P[i] = u;
}
}
dist = 38000; // reset distance value to large value
int min;
for(i = 1; i <= size; i++) {
if(L.element(u,i) != 0) {
if(L.element(u,i) < dist && U[i] != 1) {
dist = L.element(u,i);
min = i;
}
}
}
u = min;
U[u] = 1;
cout << "Min is " << min << endl;
} while (u != end);
}
if( D[u] + dist < D[i]) {
D[i] = D[u] + dist;
P[i] = u;
}
should be
if( D[u] + dist < D[i] && dist != 0) {
D[i] = D[u] + dist;
P[i] = u;
}