Backtrack through coin collection matrix to determine the optimal path? - c++

I've been assigned the, from what I've seen, fairly common problem when learning dynamic programming of having a nxm matrix of coins with a robot starting at the top left of the matrix [0,0] and trying to reach the bottom right of the matrix while picking up as many coins as possible. The robot is only allowed to move right and down. I have successfully been able to count the maximum number of coins that can be collected from the matrix, my code is below:
#include <iostream>
using namespace std;
int CoinCollection(int coinGrid[5][6])
{
int F[5][6] = {0};
F[0][0] = coinGrid[0][0];
for(int j = 1; j<6; j++)
{
F[0][j] = F[0][j-1]+coinGrid[0][j];
}
for(int i=1; i<5; i++)
{
F[i][0] = F[i-1][0] + coinGrid[i][0];
for(int j = 1; j<6; j++)
{
F[i][j] = max(F[i-1][j], F[i][j-1])+coinGrid[i][j];
}
}
return F[4][5];
}
string RobotPath(int coinGrid[5][6])
{
return "";
}
int main()
{
int grid[5][6] = {
{0,0,0,0,1,0},
{0,1,0,1,0,0},
{0,0,0,1,0,1},
{0,0,1,0,0,1},
{1,0,0,0,1,0} };
cout << "Max amount of coins collected is " << CoinCollection(grid);
cout << "\n\nRobot's path is" << RobotPath(grid);
}
The instructions I have say to hardcode the grid being used, so I don't have to change what I have to be flexible with inputs. The second part of the problem instructs to output the path that the robot should follow to reach the max number of coins (where the RobotPath method is). From the help I've received from my professor, I need to backtrack from the final solution to the beginning for this, but I'm at a loss for how to do this.

Related

use array to change every digit in a 3-digit number

#include<iostream>
using namespace std;
int main(){
int n,d1,d2,d3;
cout<<"Enter a 3-digit positive integer"<<endl;
cin>>n;
d1=n/100;
d2=n%100/10;
d3=n%10;
int a[3]{d1,d2,d3};
for (int i = 0; i < 3; ++i) {
if(a[i]!=0){
a[i]=10-a[i];
}
cout<<"The new number is :"<<a[i]<<endl;
}
}
This code takes a 3-digit integer as input and returns a new number in which all non-zero digits in the original are replaced by the distance between the digit and 10, for example, if one of the digits is 2 so the new digit will be 10-2=8. But the problem is with the output.
I want the program to print (The new number is :(here the new digits in the same line)), instead of repeating the message and printing each digit in a separate line. How can I do that??
Thanks in advance.
This for loop,
for (int i = 0; i < 3; ++i) {
if(a[i]!=0){
a[i]=10-a[i];
}
cout<<"The new number is :"<<a[i]<<endl;
}
Is the issue for your problem. This means that your printing The new number is : on every iteration. What we need to do is, print it once and print all the integers after it. Its very simple, just change the position of the std::cout to be before the for loop and we can put in a little optimization; we dont need to store the 10 - a[i], we can directly print it.
cout << "The new number is : ";
for (int i = 0; i < 3; ++i) {
if(a[i] != 0) {
std::cout << (10 - a[i]);
}
}
Bonus: Try not to use using namespace std; as its a bad practice. Basically what it does is, it takes the whole std namespace and dumps it into the global namespace. If its for competitive programming and time is limited, then it would be okay but for general programming, avoid it.
u can print the information out from the for loop or u can do for loop like this
for (int i = 0; i < 3; ++i) {
if(a[i]!=0){
a[i]=10-a[i];
}
if(i == 0)
cout<<"The new number is :";
cout <<a[i];
}
cout << endl

Issues with checking an array moving both forwards and backwards simultaneously and issue printing values stored in a pointer array

Preface: Currently reteaching myself C++ so please excuse some of my ignorance.
The challenge I was given was to write a program to search through a static array with a function and return the indices of the number you were searching for. This only required 1 function and minimal effort so I decided to make it more "complicated" to practice more of the things I have learned thus far. I succeeded for the most part, but I'm having issues with my if statements within my for loop. I want them to check 2 separate spots within the array passed to it, but it is checking the same indices for both of them. I also cannot seem to get the indices as an output. I can get the correct number of memory locations, but not the correct values. My code is somewhat cluttered and I understand there are more efficient ways to do this. I would love to be shown these ways as well, but I would also like to understand where my error is and how to fix it. Also, I know 5 won't always be present within the array since I'm using a pseudo random number generator.
Thank you in advance.
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
// This is supposed to walk throught the array both backwards and forwards checking for the value entered and
// incrementing the count so you know the size of the array you need to create in the next function.
int test(int A[], int size, int number) {
int count = 0;
for (int i = 0; i <= size; i++, size--)
{
if (A[i] == number)
count++;
// Does not walk backwards through the array. Why?
if (A[size] == number)
count++;
}
cout << "Count is: " << count << endl;
return (count);
}
// This is a linear search that creates a pointer array from the previous "count" variable in function test.
// It should store the indices of the value you are searching for in this newly created array.
int * search(int A[], int size, int number, int arr_size){
int *p = new int[arr_size];
int count =0;
for(int i = 0; i < size; i++){
if(A[i]==number) {
p[count] = i;
}
count++;
}
return p;
}
int main(){
// Initializing the array to zero just to be safe
int arr[99]={0},x;
srand(time(0));
// Populating the array with random numbers in between 1-100
for (int i = 0; i < 100; i++)
arr[i]= (rand()%100 + 1);
// Was using this to check if the variable was actually in the array.
// for(int x : arr)
// cout << x << " ";
// Selecting the number you wish to search for.
// cout << "Enter the number you wish to search for between 1 and 100: ";
// cin >> x;
// Just using 5 as a test case.
x = 5;
// This returns the number of instances it finds the number you're looking for
int count = test(arr, (sizeof(arr)/4), x);
// If your count returns 0 that means the number wasn't found so no need to continue.
if(count == 0){
cout << "Your number was not found " << endl;
return 0;
}
// This should return the address array created in the function "search"
int *index = search(arr, (sizeof(arr)/4), x, count);
// This should increment through the array which address you assigned to index.
for(int i=0; i < count; i++) {
// I can get the correct number of addresses based on count, just not the indices themselves.
cout << &index[i] << " " << endl;
}
return 0;
}
I deeply appreciate your help and patience as well as I want to thank you again for your help.

Calculate the sum of a selected row

I have made a program, which prints out numbers in a form of a shape.
I want to be able to calculate the sum of a selected row, e.g. I display a shape of 3 rows
1
1 2
1 2 3
1 2
1
If I wanted to calculate the sum of row 2, it will add 1 and 2 together to show the result.
How would I achieve this?
This is my code so far
#include <iostream>
using namespace std;
int main()
{
int i,k=0,n;
int space = n-1;
cout << "Enter amount of rows: ";
cin >> n;
while(k <= n)
{
for(i = 1; i <= k; i++)
cout<<i;
cout<<endl;
k++;
}
k=n;
while (k)
{
k--;
for (i = 1; i <= k; i++)
cout<<i;
cout<<endl;
}
return 0;
}
Since the numbers in each row begin with 1 and you know the total number of rows from the input n, the sum of numbers in each row can be easily calculated.
You can add the following code after the second while loop:
int rowNo; //For which the sum has to be calculated
cout << "Enter the row for which the sum has to be calculated" << endl;
cin >> rowNo;
int sum = 0;
int totalRows = n * 2 - 1;
if(rowNo <= totalRows)
{
if(rowNo > n)
rowNo = n - rowNo%n;
for (int i = 1; i <= rowNo; i++)
{
sum = sum + i;
}
cout << "Sum is " << sum << endl;
}
else
{
cout << "rowNo: "<< rowNo << " is greater than the total no of rows: " << totalRows << endl;
}
Once you printed all lines, there's no simple way to go back and calculate the sum of the numbers on a specific line.
The simplest way is to calculate the sums of the numbers of all lines (as you print them) and store in e.g. a vector. Then when you need to get the sum of a specific line just get the pre-calculated sum from the vector.
I'm not going to answer your homework for you but I'd like to give you a few ideas on how to improve your code and how to build a solution that is able to calculate the sum of the desired rows.
Don't simply print your shape when the user entered a number, rather build an object that contains the row information and can be printed.
class Shape {
...
private:
std::vector<Row> rows;
public:
Shape( int numberOfRows );
void Print();
...
}
A Row on the other hand could contain only the information about a single rows content
class Row {
...
private:
std::vector<int> content;
public:
void Print();
...
}
All you then need is to find implement a way of requesting a single Row from the Shape and calculate it's sum. The good thing about this way is, that you can easily repeat the 2. step and ask for different rows over and over again.
In your main you would then need to perform the following steps
Ask for the the number of rows
Create a Shape and print it to the screen
Ask a user for a row to calculate the sum of (maybe repetitively)
Calculate the sum and display it to the user (go back to 3. or exit)
EDIT:
I just read that you only had a few basics, so you probably haven't heard about classes yet. So your best bet IMO would be to store the shape in an array ( or an array of arrays ), btw. a std::vector<int> is somewhat similar to a C-Style array (int[]). Then you can still access the data after you have printed it and calculate the sum of a single row.

How to input an matrix style txt file instead of defining my own int 2D array for C++

So I'm pretty new to C++ but i think im gettting the hang of it a bit.
As part of an excersize, I have to take an input text file and apply this in a "shortest distance algorithm" where ultimatly I want to output all the shortest distances and routes but i haven't gotten that far yet. I have used the Floyd Warshall algorithm.
For now my question is, how do i replace a self written int array by a text input. the input array is just numbers but actually represents distances between nodes. The test array that im using now only has 3 nodes, but i want to be able to expand it to a much larger node amout, say 100.
example test matrix:
0 1234567 100
1234567 0 400
100 400 0
Should be read as:
node1 node2 node3
node 1 0 999999 100
node 2 999999 0 400
node 3 100 400 0
The large numbers: 999999 represents a distance that is too large too count as a edge.
As of now my code looks something like this:
#include<stdio.h>
// Number of vertices
#define V 3
// Define 999999 as a distance that is too large to represent a edge connection
#define TooLarge 999999
// The print function
void printSolution(int dist[][V]);
// Distance algorithm
void Distance (int distgraph[][V])
{
// output matrix that will have the shortest distance for every vertice
int dist[V][V], i, j, k;
// initial values for shortest distance are based on shortest paths.
for (i = 0; i < V; i++)
for (j = 0; j < V; j++)
dist[i][j] = distgraph[i][j];
// Add all vertices to the set of intermediate vertices.
for (k = 0; k < V; k++)
{
// use all vertices as seperate source
for (i = 0; i < V; i++)
{
// use all vertices as destination for the earlier determined source
for (j = 0; j < V; j++)
{
// If vertex k is on the shortest path from i to j, then update the value of dist[i][j]
if (dist[i][k] + dist[k][j] < dist[i][j])
dist[i][j] = dist[i][k] + dist[k][j];
}
}
}
// Print the shortest distance matrix
printSolution(dist);
}
// The print function
void printSolution(int dist[][V])
{
printf ("Shortest distance matrix \n");
for (int i = 0; i < V; i++)
{
for (int j = 0; j < V; j++)
{
if (dist[i][j] == 999999)
printf("%7s", "TooLarge");
else
printf ("%7d", dist[i][j]);
}
printf("\n");
}
}
// driver program to test above function
int main()
{
int distgraph[V][V] = { {0, 1234567, 100},
{1234567, 0, 400},
{100, 400, 0,},
};
// Print the solution
Distance(distgraph);
return 0;
}
Hopefully someone can help me, I have the feeling im just forgetting something stupid. I have tried to inport the textfile using this type of code:
using namespace std;
double distances [3][3];
int main () {
int x, y;
ifstream in("citytest.txt");
if (!in) {
cout << "Cannot open file.\n";
return 0;
}
for (y = 0; y < 3; y++) {
for (x = 0; x < 3; x++) {
in >> distances[x][y];
}
}
cout << distances[3][3] << " " << endl;
in.close();
Which i know works, but only inports a predetermind part of the matrix whereas i want to input the entire array. (the cout function is just there to test if the correct distances were given as an input)
You cannot efficiently allocate the container unless you know big the workload in your external data file is.
Thus:
tokenize the first line of your file and take the dimension N from that
allocate your container accordingly
then consume the rest of the file and put the data into the container; maybe throw if a row's length doesn't match N, or if there are not N rows.
You may consider that
representing a graph by a full adjacency matrix is a debatable concept; it's space-inefficient and time-inefficient for sparse graphs
a 2D c-array is not the only possible representation of a matrix; you may consider a flat std container and implement a slice-style access on it
last not least you may want to have a look at boost::graph

How can i find bicomponents in graph ? called block

Here my tryings, and copypastings. But what i must write to find biconnectedcomponent (called block)?
#include <fstream>
#include <vector>
using namespace std;
ifstream cin ("test3.txt");
ofstream cout ("output.txt");
const int l = 6;
int G[l][l];
int MAXN;
int used[l];
int number[l], low[l], counter = 1, kids = 0;
vector <int> block[l];
void BiComp(int curr, int prev) {
int kids = 0;
low[curr] = number[curr] = counter++;
used[curr] = 1;
for(int i = 0; i < MAXN; i++) {
if(G[curr][i] == 1) {
if (i != prev) {
if (used[i] == 0) {
kids++;
block[0].push_back(curr);
block[0].push_back(i);
BiComp(i, curr);
low[curr] = min(low[curr], low[i]);
if(low[i] >= number[curr] && (prev != -1 || kids >= 2)) {
cout << "tochka " << curr + 1 << endl;
}
} else {
block[0].push_back(i);
block[0].push_back(prev);
cout<<block<<endl;
low[curr] = min(low[curr], number[i]);
}
}
}
}
}
void main()
{
MAXN = 6;
for (int i = 0; i < MAXN; i++)
{
for (int j = 0; j < MAXN; j++)
{
cin >> G[i][j];
cout << G[i][j] << " ";
}
cout << endl;
}
//for (int i = 0; i < MAXN; i++) {
//if (number[i] == 0) {
BiComp(0, -1);
//}
//}
}
How can i find by this code, finding cutpoints at the same time blocks???
In graph theory, a biconnected component (or 2-connected component) is a maximal biconnected subgraph.
Ok what comes to my mind is a very brute-force approach that isn't going to scale well, but I also remember reading that finding biconnected components is in fact a hard problem, computationally, so let's just start with it and then see if there's optimizations to be done.
Given a set of N nodes, check for each possible subset of nodes whether they form a biconnected component. Typically, you'll want the biggest component available, so just start with the whole graph, then with all subgraphs of N-1 nodes, N-2, and so on. As soon as you find one solution, you'll know you have found one of the biggest possible size and you can quite. Still, you'll end up checking 2^N subgraphs in the worst case. So start with a loop constructing your graphs to be tested.
To find out if a given graph with K nodes is a biconnected component, loop over all K*(K-1)/2 pairs of nodes and find out if there are two independent paths between them.
In order to find out if two nodes i and j are biconnected, first find all paths between them. For each path, find out if there is an alternative connection to that path. If you find one, you're done for that pair. If not, you've found proof that the graph you're looking at is not biconnected and you can break from all loops but the outer one and test the next graph.
In order to see if there is an alternative connection between i and j, take out all edges you used in the first path, and see if you can find another one. If you can, you're fine with i and j. If you can't, continue with the next path in the initial list of paths you found. If you reach the end of your list of paths without finding one for which an alternative exists when taking out the involved edges, the two nodes are not biconnected and hence the whole graph isn't.
There is a linear run time algorithm for finding all cut points (or cut vertices or articulation points) in a given graph using Depth First Search.
Once you found all the cut points, it's easy to find all of the bicomponents.