Can't find path in Minimum Cost Path using Dynamic Programming - c++

The algorithm is supposed to find the minimum cost path in NxN matrix given as an input. The starting cell is always left bottom and the destination is right top.
Each cell of the matrix represents a cost to traverse through that cell.
You can only move up and right.
I have managed to find the cost, however, I still struggle to backtrack the path.
I tried to start from top right cell and use the greedy algorithm to find my "way back", but the output was either completely wrong or skipping random columns/rows. I also tried to keep track of decisions I was making by creating an additional matrix, but I always end up stuck in the loop.
So how do I find the path?
Here's the code that works well (counts the cost and that's it):
#include <iostream>
using namespace std;
int main()
{
int tab[101][101], N, cost[101][101], backtrack[101][101];
cout << "N (size of NxN matrix) :" << endl;
cin >> N;
for(int i = 0; i < N; i++)
{
for(int j = 0; j < N; j++)
{
cin >> tab[i][j];
cost[i][j] = 0;
backtrack[i][j] = 0;
}
}
cost[N-1][0] = tab[N-1][0];
int a = N-1;
for(int i = N-2; i >= 0; i--) // column 0 can be chosen only in 1 way
{
cost[i][0] = cost[i+1][0] + tab[i][0];
backtrack[i][0] = 4; // came from down
}
for(int j = 1; j < N; j++) // row N-1 can be chosen only in 1 way
{
cost[a][j] = cost[a][j-1] + tab[a][j];
backtrack[a][j] = 3; // came from right
}
for(int i = N-2; i >= 0; i--)
{
for(int j = 1; j < N; j++)
{
if(cost[i][j-1] <= cost[i+1][j])
{
cost[i][j] = tab[i][j] + cost[i][j-1];
backtrack[i][j] = 3;
}
else
{
cost[i][j] = tab[i][j]+cost[i+1][j];
backtrack[i][j] = 4;
}
}
}
cout << "Cost: " << cost[0][a] << endl;
return 0;
}
Now, here's the function with flawed additional matrix that's supposed to give me the path, but ends up in an infinite loop:
(matrix backtrack from previous code was given as track here)
void path(int track[101][101], int N)
{
int help[101][101];
for(int i = 0; i < N; i++)
{
for(int j = 0; j < N; j++)
help[i][j] = 0;
}
int w = 0, k = N-1;
help[w][k] = 1; // top right argument is included in the output
while(w < N || k >= 0)
{
if(track[w][k] == 3)
{
help[w][k-1] = 1; // 3 means I came from the previous column k-1
k--;
}
else if(track[w][k] == 4)
{
help[w+1][k] = 1; //4 means I came from the previous row w+1
w++;
}
}
for(int i = 0; i < N; i++)
{
for(int j = 0; j < N; j++)
{
if(help[i][j] != 0)
cout << i << " " << j << endl;
}
}
}
Example input:
5
2 3 4 2 5
5 2 1 2 2
2 4 2 2 3
1 2 2 4 3
3 2 1 2 3
Expected output:
Cost: 20
4 0
4 1
4 2
3 2
2 2
1 2
1 3
0 3
0 4
Actual output
Cost: 20
And no path at all since it ends up in an infinite loop.

You have written the while loop in path() incorrectly:
while(w < N || k >= 0)
...
You intend this loop to continue until w = N-1 and k=0, which it does, but the loop doesn't terminate there, it just runs in place. (You could see this yourself by adding cout << w << " " << k << endl; to the loop.) The conditional I think you want is:
while(w < N-1 || k > 0)

Related

Checking how many times a number has been entered

I'm trying to solve one of the questions on a task sheet I've received, to help me further in my understanding of C++ code from my class.
It kept showing 100000 in output after I entered the values. Where is that 1 coming from?
I know there are better ways to write code for this but I just want to know were is my problem.
The question is
(and I quote):
Write a program that:
Asks the user to enter 10 numbers between 1 and 5 into an array and displays the array on screen.
Creates a second array of size 5 and fills it with zeros.
Counts how many 1s, 2s, , … 5s have been entered into the first array and stores this number in the second array.
Displays the second array as shown in the example below.
Code:
int A1[10];
int A2[5] = { 0,0,0,0,0 };
int count = 10;
for (int i = 0; i < count; i++)
{
here:
cout << endl << i + 1 << "- enter a number between 1 and 5 for value : ";
cin >> A1[i];
if (A1[i] < 1 || A1[i]>5)
{
cout << "eror! enter a number between 1 and 5!";
goto here;
}
}
for (int i = 0; i < 10; i++)
{
for (int j = 1; j < 6; j++)
{
if (A1[i] = j)
{
A2[j - 1]++;
break;
}
}
}
for (int i = 0; i < 5; i++)
cout << A2[i];
The error is on the row 21 or 22, you are using a single = which is the assignment sign, inside the if statement, so you are overwriting the value of A[i] to the value of j, but want to check if the element of A[i] is equal to j... So you have to add a = in the if statement.
I don't recommend that you use goto:, it creates spaghetti code. you can put an i-- in your error clause, like so:
int temp;
for (int i = 0; i < count; i++){
cout << i + 1 << "- enter a number between 1 and 5 for value : " << endl;
cin >> temp;
if (temp >= 1 && temp <=5)
A1[i] = temp;
else
i--;
}
Also, if you want to compare 2 values, you should use the == operator. that is what's causing the problem in your second loop
like so:
for(int i = 0; i < count; i++){
for(int j = 1; j < 6; j++)
if(A1[i] == j)
A2[j-1]++;
}
This should work.

(C++) How can I access the 2 other diagonals above and below the first diagonal?

Specification: first diagonal = diagonal that goes from the very top left corner to the very bottom right corner.
Take a matrix where:
(1) is the diagonal that goes from the top left corner to the bottom right corner,
(2) are the elements under(and above) the diagonal (therefore being the other 2 diagonals surrounding the first diagonal)
(0) every other element from the matrix
So the matrix would end up like this:
1 2 3 3
2 1 2 3
3 2 1 2
3 3 2 1
My question is, how can I access the elements marked with (2) from the matrix?
For the diagonal "below" you can do something like
for (int i = 1; i < colums; ++i){
std::cout << matrix[i][i-1] << std::endl;
}
and for the one "above"
for (int i = 0; i < colums - 1; ++i){
std::cout << matrix[i][i+1] << std::endl;
}
please note that this will only work for square matrices, if you don't have a square matrix the number of columns and rows is not the same so you need to set up a different loop that accounts for this case.
You could do something along these lines, even if I don't really like having for loops with more than one variable and i think it's hard to understand at first glance.
You sdould clean it up a bit and make it more error resistant before using it but it illustrates the idea
for (int i = 0, j = 0; i < columns && j < rows; ++i, ++j){
std::cout << matrix[i][j] << std::endl;
}
Having i and j start from 0 will give you the "main diagonal", having i start from 1 and j from 0 will give you the one "below" and having i start from 0 and j from 1 will give you the one "above"
This will work for any type of matrix assuming the main diagonal as elements with (i == j).
#include <iostream>
#define size [10][10] // assuming the max size of matrix to be 10 * 10
int main() {
int m = 0, n = 0;
std::cin >> m >> n; // reading number of rows in m and cols in n
int arr[m][n] = {0};
// to accept matrix elements
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j) std::cin >> arr[i][j];
// to print diagonal above the main diagonal
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
if (i == j && j != n - 1) std::cout << arr[i][j + 1] << '\n';
// to print diagonal below the main diagonal
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
if (i == j && i != 0) std::cout << arr[i][j - 1] << '\n';
return 0;
}

How to check if 3 elements of array have the same value

I am trying to write a program which checks if 3 (or more) elements of an array are the same.
I have written a code which works almost perfectly, but it gets stuck when there are 3 pairs of equal elements and I'm not sure how to fix it.
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int n, a[10],skirt=0;
cin >> n;
for(int i = 0; i < n; i++)
{
cin >> a[i];
}
for(int i = 0; i < n; i++)
{
for(int j = i + 1; j < n; j++)
{
if(a[i] == a[j])
{
skirt++;
}
}
}
cout<<skirt<<endl;
if(skirt>=3)
{
cout << "TAIP" << endl;
}
else
{
cout << "NE" << endl;
}
}
When I input
6
3 3 2 2 1 1 i
get "TAIP" but I need to get "NE".
You can use the following algorithm: first sort the array. Then iterate each adjacent pair. If they are equal, then increment counter, if not then reset counter to 1. If counter is 3, return true. If loop does not return true, then return false.
Add the following condition in the outer for loop
for(int i = 0; i < n - 2 && skirt != 3; i++)
^^^^^^^^^^^^^^^^^^^^^^^
{
skirt = 1;
^^^^^^^^^
for(int j = i + 1; j < n; j++)
{
if(a[i] == a[j])
{
skirt++;
}
}
}
Of course before the loop you should check whether n is not less than 3. For example
if ( not ( n < 3 ) )
{
for(int i = 0; i < n - 2 && skirt != 3; i++)
{
skirt = 1;
for(int j = i + 1; j < n; j++)
{
if(a[i] == a[j])
{
skirt++;
}
}
}
}
Here is a demonstrative program
#include <iostream>
using namespace std;
int main()
{
int a[] = { 6, 3, 3, 2, 2, 1, 1 };
int n = 7;
int skirt = 0;
if ( not ( n < 3 ) )
{
for(int i = 0; i < n - 2 && skirt != 3; i++)
{
skirt = 1;
for(int j = i + 1; j < n; j++)
{
if ( a[i] == a[j] )
{
skirt++;
}
}
}
}
cout << skirt << endl;
if ( skirt == 3 )
{
cout << "TAIP" << endl;
}
else
{
cout << "NE" << endl;
}
return 0;
}
Its output is
1
NE
because the array does not have 3 equal elements.
Reset skirt to 0 every time you increase i if it is less than 3, or break out the loop otherwise.
Another way to do this is using a std::map, which keeps a count of the number of times a given value occurs in your array. You would stop looking as soon as you have a number that has three occurrences.
Here's a 'minimalist' code version:
#include <iostream>
#include <map>
using std::cin; // Many folks (especially here on SO) don't like using the all-embracing
using std::cout; // ... statement, "using namespace std;". So, these 3 lines only 'use'
using std::endl; // ... what you actually need to!
int main() {
int n, a[10], skirt = 0;
std::map<int, int> gots;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
for (int i = 0; i < n && skirt < 3; i++) {
skirt = 1;
if (gots.find(a[i]) != gots.end()) skirt = gots[a[i]] + 1;
gots.insert_or_assign(a[i], skirt);
}
cout << (skirt >= 3 ? "TAIP" : "NE") << endl;
return 0;
}
I'm not saying this is any better (or worse) than the other answers - just another way of approaching the problem, and making use of what the Standard Library has to offer. Also, with this approach, you could easily modify the code to count how many numbers occur three or more times, or any number of time.
Feel free to ask for further clarification and/or explanation.

How to convert List of Edges to Adjacency Matrix in C++ with the number of edges connected to a vertex instead of ones?

I am struggling to convert a list of Edges to Adjacency Matrix in a certain required way.
Problem:
The Adjacency matrix should have number of edges connected to a vertex, so it should not have only 1s where two vertexes are connected. For better explanation here is sample input.
Input
4 7
1 2
2 3
3 2
2 4
4 1
4 2
3 2
Where 4 is number of vertexes and 7 is the number of edges and each line represents edges.
Output:
4
0 1 0 1
1 0 3 2
0 3 0 0
1 2 0 0
Where 4 is number of vertexes and each line represents how many times a vertex is connected.
In my code I only managed to convert to normal Adjacency matrix with 1s, but I cannot understand if I can solve this task only with arrays and how?
Here is my code:
#include <iostream>
using namespace std;
int main()
{
int adjMatrix[100][100] = { };
int edgeList[100][100];
int row, col;
int N, M;
cin >> N;
cin >> M;
for (int i = 0; i < 100; i++)
{
for (int j = 0; j < 100; j++)
{
adjMatrix[i][j] = 0;
}
}
for (int i = 1; i < 8; i++)
{
for (int j = 1; j <= 2; j++)
{
cin >> row;
cin >> col;
adjMatrix[row][col] = 1;
adjMatrix[col][row] = 1;
}
}
for (int i = 1; i < 8; i++)
{
for (int j = 1; j <= 2; j++)
{
if (adjMatrix[i][j] == adjMatrix[j][i])
{
adjMatrix[i][j]++;
}
}
}
cout << N << endl;
for (int i = 1; i <= N; i++)
{
for (int j = 1; j <= N; j++)
{
cout << adjMatrix[i][j] << " ";
}
cout << endl;
}
return 0;
}
Problem: Want count of connections, not simply that connection exists.
Solution: Use ++
adjMatrix[row][col]++;
adjMatrix[col][row]++;
It is worth noting that
This loop
for (int i = 0; i < 100; i++)
{
for (int j = 0; j < 100; j++)
{
adjMatrix[i][j] = 0;
}
}
Is rendered redundant by
int adjMatrix[100][100] = { };
because the = {} default initializes the array, setting all elements to 0.
In addition, what if N is greater than the 100 used to define the array dimensions? adjMatrix needs to be dynamic. Read up on and use a std::vector
The following loop conditions are incorrect
for (int i = 1; i < 8; i++)
{
for (int j = 1; j <= 2; j++)
{
cin >> row;
cin >> col;
adjMatrix[row][col] = 1;
adjMatrix[col][row] = 1;
}
}
14 lines will ALWAYS be read from the file regardless of the size of the file. The outer loop will always run 7 times (1..7) and the inner loop always twice (1..2).
M defines the number of rows in the file. Use that to control your loop.
This fixed number of lines is particularly bad if there are less than 14 lines in the file because the cin >> are not being tested for validity. The code could be loading the matrix with garbage and you would never know. Instead use something like
if (cin >> row >> col)
{
do stuff
}
else
{
handle error
}
A program must validate all input because you can't trust those slimy users. One minute they're making typos and the next trying to hack into the Pentagon.
This loop accomplishes nothing useful, but you knew that already. No thought went into this at all. It is exceptionally hard to write code without thinking. This is why I held off on answering the question so long. Not thinking is also a disincentive to others offering assistance.
for (int i = 1; i < 8; i++)
{
for (int j = 1; j <= 2; j++)
{
if (adjMatrix[i][j] == adjMatrix[j][i])
{
adjMatrix[i][j]++;
}
}
}

Swapping 2d array minimum row value with reverse diagonal

I am trying to swap minimum row value with reverse diagonal. I managed to print out every row minimum value, but my swap fails. Maybe you could give me some hints.
for (int i = 0; i < n; i++)
{
int min = mas[i][0];
for (int j = 1; j < m; j++)
{
if (mas[i][j] < min)
{
min = mas[i][j];
}
for(int k=n-1;k>0;k--){
for(int h = m-1; h>0;h--){
min = mas[i][j];
mas[i][j]=mas[k][h];
mas[k][h]=min;
}
cout << "New Matrix\n";
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
cout << mas[i][j] << " ";
}
}
}
}
system("pause");
return EXIT_SUCCESS;
}
This is my for for a minimum value and later I am adding another for to swap values.
My result:
I go printed out 3 matrices and none of them are correctly swapping value. I guess it's because of for in for cycle?
My file with with 2d array:
1 2 5 // row min 1, reverse diagonal 5
2 8 9 // row min 2, reverse diagonal 8
5 9 10 // row min 5, revese diagonal 5
What output I expect:
5 2 1 // 5 diagonal swap with min = 1
8 2 9 // 8 diagonal swap with min = 2
5 9 10 // 5 diagonal no swap because 5 is row minimum
If I understand correctly then the "reverse diagonal" can be present only in a square matrix. So there is no sense to enter two values n and m to deal with a square matrix.
If to consider the example of a 3 x 3 matrix shown in your question and to use loops instead of for example standard functions std::max_element and std::swap then the code that converts the matrix can look the following way as it is shown in the demonstrative program
#include <iostream>
#include <iomanip>
int main()
{
const size_t N = 3;
int a[N][N] =
{
{ 1, 2, 5 },
{ 2, 8, 9 },
{ 5, 9, 10 }
};
for (size_t i = 0; i < N; i++)
{
for (size_t j = 0; j < N; j++)
{
std::cout << std::setw(2) << a[i][j] << ' ';
}
std::cout << '\n';
}
std::cout << std::endl;
for (size_t i = 0; i < N; i++)
{
size_t min = 0;
for (size_t j = 1; j < N; j++)
{
if (a[i][j] < a[i][min]) min = j;
}
if ( min != N - i - 1 )
{
int tmp = a[i][min];
a[i][min] = a[i][N - i - 1];
a[i][N - i - 1] = tmp;
}
}
for (size_t i = 0; i < N; i++)
{
for (size_t j = 0; j < N; j++)
{
std::cout << std::setw(2) << a[i][j] << ' ';
}
std::cout << '\n';
}
std::cout << std::endl;
}
The program output is
1 2 5
2 8 9
5 9 10
5 2 1
8 2 9
5 9 10