Related
Look at this code, In my VS code or some online compilers it gives favorable output, but when I'm submitting this on HackerRank or this online compiler I'm getting wrong output but only when I provide input as: 1 1 1 100...and I'm not able to spot the Error?..I'm providing question for reference.
/*There will be two arrays of integers. Determine all integers that satisfy
the following two conditions:
The elements of the first array are all factors of the integer being
considered
The integer being considered is a factor of all elements of the second array
These numbers are referred to as being between the two arrays. Determine how
many such numbers exist.
*/
#include <iostream>
int main()
{
int count1, count2;
int num1[20], num2[20];
std::cin >> count1 >> count2;
for (int i = 0; i < count1; i++)
{
std::cin >> num1[i];
}
for (int i = 0; i < count2; i++)
{
std::cin >> num2[i];
}
int occurence_firstarray = 0, occurence_secondarray = 0, totalvalid_occurence = 0;
for (int i = num1[count1 - 1]; i < num2[1]; i++)
{
occurence_firstarray = 0;
occurence_secondarray = 0;
for (int j = 0; j < count1; j++)
{
if (i % num1[j] == 0)
{
occurence_firstarray++;
}
}
if (occurence_firstarray == count1)
{
for (int p = 0; p < count2; p++)
{
if (num2[p] % i == 0)
{
occurence_secondarray++;
}
}
}
if (occurence_secondarray == count2)
{
totalvalid_occurence++;
}
}
std::cout << totalvalid_occurence;
return (0);
}
Considering your inputs: 1 1 1 100,
What are you doing in this code is You are pointing on index beyond your second array's size limit i < num2[1], this is why you are getting wrong outputs.
Do some changes as, i <= num2[0];
Given an undirected and disconnected graph G(V, E), print its BFS traversal.
Here you need to consider that you need to print BFS path starting from vertex 0 only.
V is the number of vertices present in graph G and vertices are numbered from 0 to V-1.
E is the number of edges present in graph G.
Note : 1. Take graph input in the adjacency matrix.
2. Handle for Disconnected Graphs as well
Input Format :
Line 1: Two Integers V and E (separated by space)
Next 'E' lines, each have two space-separated integers, 'a' and 'b', denoting that there exists an edge between Vertex 'a' and Vertex 'b'.
Output Format :
BFS Traversal (separated by space)
Constraints :
2 <= V <= 1000
1 <= E <= 1000
Sample Input 1:
4 4
0 1
0 3
1 2
2 3
Sample Output 1:
0 1 3 2
Please tell what is wrong in the code.
Here is the code:
#include <iostream>
using namespace std;
#include <queue>
void print(int** edges, int V, int sv, bool* visited){
queue<int> pq;
pq.push(sv);
visited[sv] = true;
while(!pq.empty()){
int ans = pq.front();
cout << ans << " ";
pq.pop();
for(int i = 0; i < V; i++){
if(ans == i){
continue;
}
if(edges[ans][i] == 1 && !visited[i]){
pq.push(i);
visited[i] = true;
}
}
}
}
void BFS(int** edges, int V){
bool* visited = new bool[V];
for(int i = 0; i < V; i++){
visited[i] = false;
}
for(int i = 0; i < V; i++){
if(!visited[i]){
print(edges, V, i, visited);
}
}
delete [] visited;
}
int main() {
int V, E;
cin >> V >> E;
int**edges = new int*[V];
for(int i = 0; i < V; i++){
edges[i] = new int[V];
for(int j = 0; j < V; j++){
edges[i][j] = 0;
}
}
for(int i = 0; i < E; i++){
int f, s;
cin >> f >> s;
edges[f][s] == 1;
edges[s][f] == 1;
}
BFS(edges, V);
for(int i = 0; i < V; i++){
delete [] edges[i];
}
delete [] edges;
/*
Write Your Code Here
Complete the Rest of the Program
You have to take input and print the output yourself
*/
}
I think the only problem is a tiny mistake I see in the part you read params from command line. The algorithm itself looks good.
You need to use assignment operator = instead of comparison operator == when read edges:
edges[f][s] = 1;
edges[s][f] = 1;
As stated above, I am trying to get the elements of a 2D matrix using only C++
The matrix has MxN dimensions, and it may be so that N!=M, N >= M or M < N (basically the dimensions can be anything and are determined in execution time)
I have tried to go about it using 2 nested for loops but so far the code just keeps getting more & more complex & does not produce consistent results.
Visual aid:
I am trying to get the 2nd for loop to iterate through the colored cells of the matrix starting from top left - i.e. in every loop the amount/position of the cells that the 2nd loop iterates through keeps changing & I am starting to wonder whether this can be done at all given that N & M are not known on compile time.
Thanks for your time in advance.
~EDIT1:
Here is what the iteration of the elements would look like for a non square matrix (same thing applies if the rows where more than the columns)
~EDIT2:
Here is the code so far: (testable!)
#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;
void func(void);
// use these variables to specify the dimensions arbitrarily
// keep in mind I need this to work with relatively big matrices
int row = 5, col = 5;
string arr[][10]= {{"0", "0", "0", "0", "0", "0", "0", "0", "0", "0" },
{"0", "1,1", "1,2", "1,3", "1,4", "1,5", "1,6", "1,7", "1,8", "1,9" },
{"0", "2,1", "2,2", "2,3", "2,4", "2,5", "2,6", "2,7", "2,8", "2,9" },
{"0", "3,1", "3,2", "3,3", "3,4", "3,5", "3,6", "3,7", "3,8", "3,9" },
{"0", "4,1", "4,2", "4,3", "4,4", "4,5", "4,6", "4,7", "4,8", "4,9" },
{"0", "5,1", "5,2", "5,3", "5,4", "5,5", "5,6", "5,7", "5,8", "5,9" },
{"0", "6,1", "6,2", "6,3", "6,4", "6,5", "6,6", "6,7", "6,8", "6,9" },
{"0", "7,1", "7,2", "7,3", "7,4", "7,5", "7,6", "7,7", "7,8", "7,9" },
{"0", "8,1", "8,2", "8,3", "8,4", "8,5", "8,6", "8,7", "8,8", "8,9" },
{"0", "9,1", "9,2", "9,3", "9,4", "9,5", "9,6", "9,7", "9,8", "9,9" } };
bool f = false, f2 = false;
int main (void)
{
func();
return 0;
}
void func(void)
{
if(row < col)
{
//remember that row > col
f = true;
}
unsigned short m_i; //mask for the counter of the outer for loop (i) - counts how many times the
unsigned short j_end = 1; //stores the max number of iterations the inner loop should do - increments accordingly
unsigned short k = 1; //stores the starting index of the inner loop - starts incrementing once (j_end == col)
cout << "row = " << row << ", col = " << col << endl;
cout << "total \"i\" loops " << (row + col -1) << endl << endl;
for (unsigned short i=1; i<=row + col -1; i++) // row + col -1 is the total number of diagonals in any matrix
{ // and also the total number of iterations we need
if( i > row) // here I implement the row > col scenario, the rest should be similar
{
m_i = row; // the mask should never go above the max row number
}else if(i == row)
{
m_i = row;
if (f = true) f2 = true; // using f2 remember that we've reached the max number for rows
}else{
m_i = i; // (i < row) so just pass i
}
for(unsigned short j=k; j<=j_end; j++){
cout<< arr[m_i][j]<<" ";
if(m_i > 1){
m_i--;
}else{
m_i = 1;
}
}
cout<<endl<< "*************" << endl;
if(j_end == col )
{
k++; // increment starting index of inner loop
}else{
j_end++; // max number for inner loop not yet achieved so increment max number
}
if(m_i == row)
{
k++;
}
} // end outer loop
} // end func
You can use this code to test it for yourself the output should be something like this:
And you can change the row & col values to test for different dimensions.
So far I believe this code works for square matrices, but not so much when row != col
~EDIT3:
func() should take performance into consideration as I said before I expect the matrices to be quite large!
for( int manhattan_distance = 0; manhattan_distance < M + N - 1; ++manhattan_distance )
{
for( int i = 0; i <= manhattan_distance; ++i )
{
int j = manhattan_distance - i;
if( j < N && i < M )
{
...
}
}
}
Code:
#include <vector>
#include <utility>
#include <iostream>
int main() {
int n, m;
std::cin >> n >> m;
std::vector<std::pair<int, int> > result;
for (int k = 0; k < m; k++) {
int i = 0, j = k;
while (i < n && j >= 0)
{
result.push_back({ i, j });
i++;
j--;
}
}
for (int k = 1; k < n; k++) {
int i = k, j = m - 1;
while (i < n && j >= 0)
{
result.push_back({ i, j });
i++;
j--;
}
}
return 0;
}
Explanations:
If you look at the picture, you can see that diagonal is when you move i + 1 and j - 1. Until the first half, we start from the first row and try to go in direction specified. When we hit the end, we just go to the next column. Basically, every iteration we are just changing the starting point. The second part is a bit trickier, because we already traversed some of the lines, so we start from 1 (because we already traversed first row. Then applying the same direction as in the first half, we traverse the rest of the matrix.
You can do it like this:
void foo(int rows,int cols){
// first go vertically down
for (int start_row = 0;start_row<rows;start_row++){
int col = 0;
int row = start_row;
while (col < cols && row >= 0){
std::cout << row << "," << col << " ";
row--;
col++;
}
std::cout << std::endl;
}
// now horizantally
for (int start_col = 0;start_col<cols;start_col++){
int col = start_col;
int row = rows-1;
while (col < cols && row >= 0){
std::cout << row << "," << col << " ";
row--;
col++;
}
std::cout << std::endl;
}
}
It might be possible to write it more compact, but it works.
OK I got an answer for this, all thought its not refined.
It is working properly but it is not optimized.
EDIT: c#... did not see it was for c++, but the idea is the same
using System;
Random r = new Random();
int rows = r.Next(10,13); // or any range of rows
int cols = r.Next(10,20); // same applies
int[,] matrix = new int[rows,cols];
// mark upper diagonal
for(var i=0; i<= cols; i++)
markByCol(i,0,cols-i);
// mark lower diagonal
for(var i=1; i<= rows; i++)
markByCol(cols+1+i,i,cols-1);
// stringify matrix to view it properly
string line = string.Empty;
for(int i=0; i< rows; i++)
{
line = string.Empty;
for(int j=0; j< cols; j++)
{
line+= matrix[i,j]+" | ";
}
Console.WriteLine(line);
}
// the actual function
int markByCol(int marker,int row,int col){
if((row > -1 && row < rows) && (col > -1 && col < cols))
{
matrix[row,col] = marker;
return markByCol(marker,row+1,col-1);
}
else
return 0;
}
Here is a jsFiddle. just hit play. This implementation marks each diagonal with a specific integer so you can scan and categorize each cell by its value, in terms of which diagonal crosses it.
https://dotnetfiddle.net/Qy8J1O
I'm trying to solve Sudoku by recursive. The program working great. The problem is that the stack is only keep-able of 4-6K recursive. That's mean that if I'm leaving the soduku with more than 6-7 empty cells, the combination needed to solve it is:
4^7 = 16384 > 4-5K...
How can I improve my program to work with less calls? The program is working good out of this problem. The function:
void solve_soduku(int soduku[][N*N], int &row, int &col, const bool fix_v[][N*N])
is all the business.
I give you here all the numbers you need for correct soduku to not wast your time. You can some of them out and see how it's work:
0 0 1
0 1 2
0 2 3
0 3 4
1 0 4
1 1 3
1 2 2
1 3 1
2 0 3
2 1 1
2 2 4
2 3 2
3 0 2
3 1 4
3 2 1
3 3 3
-1
and the code:
#include <iostream>
using namespace std;
const int N = 2;
void zero_soduku(int soduku[][N*N]);
void zero_arr(int temp_arr[], int size);
void get_input(int soduku[][N*N], bool fixed_values[][N*N]);
void solve_soduku(int soduku[][N*N], int &row, int &col, const bool fix_v[][N*N]);
bool check_soduku(const int soduku[][N*N]);
bool check_rows(const int soduku[][N*N]);
bool check_cols(const int soduku[][N*N]);
bool check_sub_interval(const int soduku[][N*N]);
void print_soduku(const int soduku[][N*N]);
int main() {
int soduku[N*N][N*N] = { 0 }, row = 0, col = 0;
bool fixed_values[N*N][N*N] = { false };
get_input(soduku, fixed_values);
solve_soduku(soduku, row, col, fixed_values);
cout << endl;
print_soduku(soduku);
system("pause");
return EXIT_SUCCESS;
}
bool check_soduku(const int soduku[][N*N]) {
if (check_rows(soduku) && check_cols(soduku) && check_sub_interval(soduku))
return true;
return false;
}
bool check_rows(const int soduku[][N*N]) {
int temp_arr[N*N] = { 0 };
for (auto i = 0; i < N*N; i++) {
zero_arr(temp_arr, N*N);
for (auto j = 0; j < N*N; j++)
temp_arr[soduku[i][j] - 1]++;
for (auto k = 0; k < N*N; k++)
if (temp_arr[k]>1)
return false;
}
return true;
}
bool check_cols(const int soduku[][N*N]) {
int temp_arr[N*N] = { 0 };
for (auto i = 0; i < N*N; i++) {
zero_arr(temp_arr, N*N);
for (auto j = 0; j < N*N; j++)
temp_arr[soduku[j][i] - 1]++;
for (auto k = 0; k < N*N; k++)
if (temp_arr[k]>1)
return false;
}
return true;
}
bool check_sub_interval(const int soduku[][N*N]) {
int temp_arr[N*N] = { 0 };
for (auto rows_intervals = 0; rows_intervals < N; rows_intervals++)
for (auto cols_intervals = 0; cols_intervals < N; cols_intervals++)
for (auto i = rows_intervals*N; i < rows_intervals*N + N; i++)
for (auto j = cols_intervals*N; j < cols_intervals*N + N; j++) {
temp_arr[soduku[i][j] - 1]++;
//end of interval, check if !good interval
if (i == rows_intervals*N + N - 1 && j == cols_intervals*N + N - 1) {
for (auto k = 0; k < N*N; k++)
if (temp_arr[k]>1)
return false;
zero_arr(temp_arr, N*N);
}
}
return true;
}
void solve_soduku(int soduku[][N*N], int &row, int &col, const bool fix_v[][N*N]) {
static int counter = 0;
counter++;
cout << endl << counter << endl;
//Not empty cell
if (soduku[row][col] != 0)
//Not end of line
if (col < N*N - 1) {
col++;
solve_soduku(soduku, row, col, fix_v);
}
else
//Not end of rows
if (row < N*N - 1) {
row++;
col = 0;
solve_soduku(soduku, row, col, fix_v);
}
else
//end of soduku
if (check_soduku(soduku)) {
print_soduku(soduku);
return;
}
/////// Finishd soduku but answaer not good //////////////////
else
//Last cell not max
if (soduku[row][col] < N*N - 1) {
soduku[row][col]++;
print_soduku(soduku);
cout << endl;
solve_soduku(soduku, row, col, fix_v);
}
//Last cell max, going back...
else {
while (soduku[row][col] == N*N || fix_v[row][col]) {
if (!fix_v[row][col]) {
soduku[row][col] = 1;
print_soduku(soduku);
cout << endl;
}
if (col > 0) {
col--;
continue;
}
if (col == 0 && row > 0) {
col = N*N - 1;
row--;
}
}
if (!fix_v[row][col]) {
soduku[row][col]++;
print_soduku(soduku);
cout << endl;
}
solve_soduku(soduku, row, col, fix_v);
}
//////////////////////////////////////////////////////////////////////////
//Empty cell
else {
soduku[row][col]++;
print_soduku(soduku);
cout << endl;
solve_soduku(soduku, row, col, fix_v);
}
}
void zero_arr(int temp_arr[], int size) {
for (auto i = 0; i < size; i++)
temp_arr[i] = 0;
}
void zero_soduku(int soduku[][N*N]) {
for (int i = 0; i < N*N; i++)
for (int j = 0; j < N*N; j++)
soduku[i][j] = 0;
}
void get_input(int soduku[][N*N], bool fixed_values[][N*N]) {
cout << endl << "Please enter locatin and nums into soduku: ";
int row = 0, col, value;
while (row != -1) {
cin >> row;
if (row == -1)
return;
cin >> col >> value;
soduku[row][col] = value;
fixed_values[row][col] = true;
}
}
void print_soduku(const int soduku[][N*N]) {
for (auto i = 0; i < N*N; i++)
for (auto j = 0; j < N*N; j++) {
cout << soduku[i][j] << " ";
if (j == N*N - 1)
cout << endl;
}
//system("pause");
}`enter code here`
Your algorithm appears to be, roughly:
1) Try each move in turn
2) Check the entire board to see if it's valid
3) Repeat until the entire board is filled
This is obviously very inefficient. The code will be making many moves which are illegal, then only realizing this belatedly, after fact.
I would suggest that you completely get rid of this, and attempt to implement something a little bit more efficient. Try to think how carbon-based life forms solve sudoku puzzles, and implement the same algorithm. Do you also do the above approach, when you solve a sudoku puzzle? Of course not. You do something like this:
1) For each position on the board, instead of storing just the current number in that position, if any, also store additional information: namely, if there is no number in that position, also store all possible numbers which would legal moves for that position.
For a completely empty board, for example, each position on the sudoku board would contain all values 1-9. From this, we then make the next logical step:
2) When making a move and placing a value in some position, say 4, you will remove the value 4 from all other cells in its 3x3 square, and remove 4 from all other cells in the same row and column. Because that number will no longer be a valid move in those cells. Conversely, when undoing a move, and removing the 4 from the cell, this means that the value 4 is now legal in all cells in its 3x3 square, and its row and column, so you would put this value in all of those positions, as a number that's now a legal move in those positions.
3) When deciding which next move to make, scan the board first, looking for any cell that has only one possible legal number. This means, of course, that this is the only legal move for that cell, so you make it.
4) If you find any cell that has no legal values left, this means that you reached an unsolvable state, so you'll undo your last move, and then try the next valid move from that point on.
5) Otherwise, you should just pick one of the cells that has the fewest possible legal moves left, make the first move, then keep going, then if you reach an unsolvable state, and return to this move, you undo it, and try the next move.
This seems to me an approach that should be much more efficient, as it should end up making the least number of illegal moves.
It is also closely mimics how carbon-based lifeforms solve sudoku puzzles by themselves.
P.S. To initialize a new sudoku puzzle with prefilled numbers, just start with an empty sudoku board, with all cells allowing all numbers 1-9 as legal moves, then make each move, as described above, to fill in the initial numbers on the sudoku board.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Let's have a field (of given dimensions) of little squares with a value on each square. From each square, one can move only to the square directly below, or the one diagonally to the left or right. The task is to find the maximum combined value of a journey through the field.
For example for the input
1
6 5
3 1 7 4 2
2 1 3 1 1
1 2 2 1 8
2 2 1 5 3
2 1 4 4 4
5 2 7 5 1
the output should be 32, but my code outputs 20.
My approach was to exhaustively try all the possible routes through the field in the following manner:
y == last_row return value[x,y]
f(x,y)
y != last_row return value[x,y] + max(f(x-1,y+1),f(x,y+1),f(x+1,y+1))
Is there an error in my approach, in my code, or both?
The code is here:
#include <iostream>
#include <vector>
#include <limits>
using namespace std;
typedef int T;
T max(T x, T y, T z) {
if(x < y) {
if(y < z) return z;
else return y;
}
else {
if(y > z) return x;
else {
if(x > z) return x;
else return z;
}
}
}
//Finds the maximum amount of stones possibly gathered by following coordinates x,y
//The topmost left is (0,0), bottom right is (columns-1,rows-1)
T max_stones_found_following(T x, T y, vector< vector<T> > A) {
//Reached the last row?
if(y == A.size()-1) return A[x][y];
else {
T went_left, went_right, went_down;
if(x-1 >= 0) went_left = max_stones_found_following(x-1, y+1, A);
else went_left = numeric_limits<T>::min();
if(x+1 <= A[x].size()-1) went_right = max_stones_found_following(x+1, y+1, A);
else went_right = numeric_limits<T>::min();
went_down = max_stones_found_following(x, y+1, A);
return A[x][y] + max(went_left, went_right, went_down);
}
}
int main() {
//Initialization
T test_cases, rows, columns, stones_found, max_stones;
vector< vector<T> > A;
cin >> test_cases;
while(test_cases--) {
//Field input
cin >> rows >> columns;
for(int i = 0; i < rows; i++) {
vector<T> row;
for(int j = 0; j < columns; j++) {
T in;
cin >> in;
row.push_back(in);
}
A.push_back(row);
}
max_stones = 0;
stones_found = 0;
//Try starting at different positions in the first row
for(int i = 0; i < columns; i++) {
stones_found = max_stones_found_following(i, 0, A);
if(stones_found > max_stones) max_stones = stones_found;
}
//Output
cout << max_stones << endl;
}
return 0;
}
Some of your problems:
Method max is more complex that needed. You are making to many comparison to find the max. See bellow.
Your principal problem is using i and j inverted, according to the calling site i means the column where to start in the row 0 and in the method max_stones_found_following you are using as the row of the matrix of values.
Fixed Code (by the way it's a really slow solutions for big input data, and not dynamic programming):
#include <iostream>
#include <vector>
#include <limits>
using namespace std;
typedef int T;
T max(T x, T y, T z) {
return std::max(x, std::max(y, z));
}
// Finds the maximum amount of stones possibly gathered by following coordinates
// x,y
// The topmost left is (0,0), bottom right is (columns-1,rows-1)
T max_stones_found_following(T x, T y, vector<vector<T>> A) {
// Reached the last row?
if (y == A.size() - 1)
return A[y][x];
else {
T went_left, went_right, went_down;
if (x - 1 >= 0)
went_left = max_stones_found_following(x - 1, y + 1, A);
else
went_left = numeric_limits<T>::min();
if (x + 1 <= A[y].size() - 1)
went_right = max_stones_found_following(x + 1, y + 1, A);
else
went_right = numeric_limits<T>::min();
went_down = max_stones_found_following(x, y + 1, A);
return A[y][x] + max(went_left, went_right, went_down);
}
}
int main() {
// Initialization
T test_cases, rows, columns, stones_found, max_stones;
vector<vector<T>> A;
cin >> test_cases;
while (test_cases--) {
// Field input
cin >> rows >> columns;
for (int i = 0; i < rows; i++) {
vector<T> row;
for (int j = 0; j < columns; j++) {
T in;
cin >> in;
row.push_back(in);
}
A.push_back(row);
}
max_stones = 0;
stones_found = 0;
// Try starting at different positions in the first row
for (int i = 0; i < columns; i++) {
stones_found = max_stones_found_following(i, 0, A);
if (stones_found > max_stones)
max_stones = stones_found;
}
// Output
cout << max_stones << endl;
}
return 0;
}
See definition of dynamic programming. It's applicable to solve problems that:
Can be break into sub-problems.
And this sub-problems overlaps some how.
Ex: this problem can be divided into sub-problems as, what is the best path from row 0 -> row i. With this in mind the problem of the best path to row i, only depend of the best paths to row i-1 and the values of the matrix for the ith row. Using this you extend the solution to row i until reach last row.
In the last row would be the best path until every column of that row, search the max of this.
Source Code (Dynamic Programming):
#include <algorithm>
#include <iostream>
#include <vector>
typedef std::vector<int> row_t;
typedef std::vector<row_t> matrix_t;
int main() {
// Initialization
int test_cases, rows, columns;
matrix_t A;
std::cin >> test_cases;
while (test_cases--) {
std::cin >> rows >> columns;
for (int i = 0; i < rows; i++) {
row_t row(columns);
int in;
for (int j = 0; j < columns; j++) {
std::cin >> in;
row[j] = in;
}
A.push_back(row);
}
// Dynamic Programming Here
// For storage the best path until each cell
matrix_t best_A (rows, row_t(columns, 0));
std::copy(A[0].cbegin(), A[0].cend(), best_A[0].begin());
for (int i = 1; i < rows; i++) {
for (int j = 0; j < columns; j++) {
// right down
if (j > 0 && best_A[i - 1][j - 1] + A[i][j] > best_A[i][j]) {
best_A[i][j] = best_A[i - 1][j - 1] + A[i][j];
}
// left down
if (j < columns - 1 && best_A[i - 1][j + 1] + A[i][j] > best_A[i][j]) {
best_A[i][j] = best_A[i - 1][j + 1] + A[i][j];
}
// down
if (best_A[i - 1][j] + A[i][j] > best_A[i][j]) {
best_A[i][j] = best_A[i - 1][j] + A[i][j];
}
}
}
// End Dynamic Programming
auto it = std::max_element(best_A[best_A.size() - 1].cbegin(), best_A[best_A.size() - 1].cend());
// Output
std::cout << *it << std::endl;
}
return 0;
}
As commented previously you can calculate the best path to row i reading only the first i rows, you could do it on the fly (when reading, read first rows, calculate best starting positions, read second row, calculate best path until every column of second row, and so on), this is very good if the input is really, really big. You also don't need to save the best path until rows 1..i, you only need to have the last row calculated and the best paths of the actual row calculating.
Dynamic programming is a great way to approach this problem. But like anonymous commented, you aren't using it, or at least not in a clear fashion.
If you have C columns, then you have C possible starting locations, and C second locations, but there are 3*C - 2 pairs of (first, second). The way to leverage dynamic programming is to note the Markov nature, and for each cell in the second row, of all paths ending in that cell, keep only the one with the best score.
Then for each additional row, you again evaluate 3*C - 2 paths, keeping only C of them.
Repeat until you reach the bottom.
Implementation-wise, you should have a vector of C "best" paths to the current row, and build the vector of C best paths to the next row. Then the next row becomes the current row (use vector::swap). Each "path" must store at minimum the accumulated value, but storing the history of locations visited might also be nice.
In fact, you never even need to store the entire grid in memory. You can perform all processing for each row as you read it.
NOTE: Use of dynamic programming here makes the complexity R*C instead of C * 3^R
It was actually a lot of fun coming up with a real solution. Warning: pointers ahead!
#include <iostream>
#include <sstream>
#include <vector>
void solve_one_case();
int main(int argc, char** argv)
{
/* driver */
const std::string input = "6 5\n"
"3 1 7 4 2\n"
"2 1 3 1 1\n"
"1 2 2 1 8\n"
"2 2 1 5 3\n"
"2 1 4 4 4\n"
"5 2 7 5 1";
std::stringbuf inputstream(input, std::ios_base::in);
auto const oldbuf = std::cin.rdbuf();
std::cin.rdbuf(&inputstream);
solve_one_case();
std::cin.rdbuf(oldbuf);
return 0;
}
void solve_one_case()
{
/* get board size from input */
int rows = 1, columns = 1;
std::cin >> rows >> columns;
std::vector<char> route(rows * columns, '|');
/* get first row from input */
std::vector<int> current_row, prev_row;
current_row.resize(columns);
for( int& start_score : current_row )
std::cin >> start_score;
/* get all cells from input, solving */
char* pRoute = &route[columns];
for( int row = 1; row < rows; ++row ) {
prev_row = current_row;
int cell = 0;;
for( int column = 0; column < columns; ++column )
{
std::cin >> cell;
if (column > 0 && prev_row[column-1] > current_row[column]) {
current_row[column] = prev_row[column-1];
*pRoute = '\\';
}
if (column + 1 < columns && prev_row[column+1] > current_row[column]) {
current_row[column] = prev_row[column+1];
*pRoute = '/';
}
current_row[column] += cell;
++pRoute;
}
}
/* find best value in final row */
int best_score = current_row[0], best_end = 0;
for( int i = 1; i < columns; ++i ) {
if (best_score < current_row[i]) {
best_score = current_row[i];
best_end = i;
}
}
std::cout << "Best score is " << best_score << "\n";
/* backtrack along route */
int route_column = best_end;
for( int row = 0; row < rows; ++row ) {
char breadcrumb = '*';
pRoute -= columns;
std::swap(pRoute[route_column], breadcrumb);
switch (breadcrumb) {
case '/': ++route_column; break;
case '\\': --route_column; break;
}
}
/* print routes */
pRoute = &route[0];
for( int row = 0; row < rows; ++row ) {
std::cout.write(pRoute, columns);
pRoute += columns;
std::cout << '\n';
}
std::cout << std::flush;
}
Output:
Best score is 32
||*||
|/|*\
//|\*
/||*|
||*|\
|/*||