Memoization Approach for Gold Mine Problem on GFG - c++

I am trying to solve the Gold Mine problem on GFG using a memoization based approach of dynamic programming. Here is the code I have written.
int dp[50][50];
int traverse(int x,int y,int n,int m, vector<vector<int>> M){
if((x<n and x>=0) and (y<m and y>=0))
{
if(dp[x][y]!=-1)
return dp[x][y];
else{
int right=M[x][y]+traverse(x,y+1,n,m,M);
int right_up=M[x][y]+traverse(x-1,y+1,n,m,M);
int right_down=M[x][y]+traverse(x+1,y+1,n,m,M);
return dp[x][y]=max(max(right,right_up),right_down);}
}
return 0;
}
int maxGold(int n, int m, vector<vector<int>> M)
{
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
dp[i][j]=-1;
}
}
int ans=0;
for(int i=0;i<n;i++){
ans=max(ans,traverse(i,0,n,m,M));
}
return ans;
}
The question says that we can start from any cell in the first column.
As the specific cell is not specified, I have tried finding out the maximum of all possible answers with each cell of the first column as the starting point. But this is giving a TLE, which is expected because the above code would take o(n^2*m) time.
Can anyone help me out with how to get around this problem of optimally figuring out which cell to start from so that the memoization based approach works under the time constraints provided?

Use call by const reference for the STL container. You performed thousands of copies of the full, read-only input.
int dp[55][55];
int traverse(int x,int y,int n,int m, const vector<vector<int>>&M){
. . .
}
int maxGold(int n, int m, const vector<vector<int>>&M)`
{
...
}

here is my solution:
class Solution{
public:
int maxGold(int n, int m, vector<vector<int>> M)
{
vector<vector<int>> f(n + 10, vector<int>(m + 10, 0));
for(int i = 0; i < n; i++){
f[i][0] = M[i][0];
}
for(int j = 1; j < m; j++){
for(int i = 0; i < n; i++){
if(i == 0){
f[i][j] = max(f[i][j-1], f[i+1][j-1]) + M[i][j];
}else if(i == n-1){
f[i][j] = max(f[i][j-1], f[i-1][j-1]) + M[i][j];
}else{
f[i][j] = max({f[i][j-1], f[i-1][j-1], f[i+1][j-1]}) + M[i][j];
}
}
}
int res = 0;
for(int i = 0; i < n; i++){
res = max(res, f[i][m-1]);
}
return res;
}
};

Related

generate a list of all possible combinations and randomly select a combination from the list

I found this code online on tutorials point. link https://www.tutorialspoint.com/cplusplus-program-to-generate-all-possible-combinations-out-of-a-b-c-d-e.
I tried to think of how to modify it so that it would randomly a single combination from the generated list, but I'm haven't figured it out yet.
#include<iostream>
using namespace std;
void Combi(char a[], int reqLen, int s, int currLen, bool check[], int l)
{
if(currLen > reqLen)
return;
else if (currLen == reqLen) {
cout<<"\t";
for (int i = 0; i < l; i++) {
if (check[i] == true) {
cout<<a[i]<<" ";
}
}
cout<<"\n";
return;
}
if (s == l) {
return;
}
check[s] = true;
Combi(a, reqLen, s + 1, currLen + 1, check, l);
check[s] = false;
Combi(a, reqLen, s + 1, currLen, check, l);
}
int main() {
int i,n;
bool check[n];
cout<<"Enter the number of element array have: ";
cin>>n;
char a[n];
cout<<"\n";
for(i = 0; i < n; i++) {
cout<<"Enter "<<i+1<<" element: ";
cin>>a[i];
check[i] = false;
}
for(i = 1; i <= n; i++) {
cout<<"\nThe all possible combination of length "<<i<<" for the given array set:\n";
Combi(a, i, 0, 0, check, n);
}
return 0;
}
im not a c++ specialist, but i think you should add a random number from -ArrayLenght to ArrayLenght, at least this works in python(which is written in c++)
i hope i understood your question right

N-Queen Problem: Cannot figure out why my solution is not working

I was having a go at the standard N-Queens problem for an upcoming interview.
I have tried to dry run my code and it seems to work fine. I can't spot the error in my code.
I am traversing it column by column, and using backtracking to recur back from an incorrect path.
Can anyone help me with why this doesn't give me the desired output (details below)?
Here's the problem statement
#include<bits/stdc++.h>
using namespace std;
void solve(vector<vector<int>> &ans, vector<int> &curr, int col, int n){
if(col==n){
ans.push_back(curr);
return;
}
bool flag=false;
for(int row=0; row<n; row++){
if(col==0){
curr.push_back(row);
solve(ans, curr, col+1, n);
curr.pop_back();
}
else{
for(int i=0; i<curr.size(); i++){
if((curr[i] == row) || (abs(row-curr[i]) == (col-i))){
flag=true;
break;
}
}
if(flag)
continue;
curr.push_back(row);
solve(ans, curr, col+1, n);
curr.pop_back();
}
}
}
int main()
{
int t;
cin>>t;
while(t--){
int n;
cin>>n;
vector<vector<int>> ans;
vector<int> curr;
solve(ans, curr, 0, n);
for (int i = 0; i < ans.size(); i++) {
cout << "[";
for (int j = 0; j < ans[i].size(); j++)
cout << ans[i][j]+1 << " ";
cout << "]";
}
cout << endl;
}
return 0;
}
A sample input would look like:
2
1
4
and the corresponding output would be:
[1 ]
[2 4 1 3 ] [3 1 4 2 ]
The compiler gives me an output (for my code):
[1 ]
The bool flag variable (used to check if placing a queen at (row, col) would intersect with any existing queens in curr) is currently being re-used across rows.
So, if you place the line bool flag=false; just above for(int i=0; i<curr.size(); i++){, it should produce the correct output for your test case.
Other notes:
It might be easier to create a separate function bool does_intersect(const vector<int>& cur, int row, int col) to check the queen intersection condition so that the bool flag variable isn't needed.
The if(col==0){ condition can be removed since it doesn't do anything that the else part cannot already handle.
This solution passes LeetCode's online judge for N Queens problem, and uses three flags to solve the problem:
#include <string>
#include <vector>
class Solution {
public:
std::vector<std::vector<std::string>> solveNQueens(int n) {
std::vector<std::vector<std::string>> possibilities;
std::vector<std::string> n_queens(n, std::string(n, '.'));
std::vector<int> flag_col(n, 1);
std::vector<int> flag_diag_a(2 * n - 1, 1);
std::vector<int> flag_diag_b(2 * n - 1, 1);
solveNQueens(possibilities, n_queens, flag_col, flag_diag_a, flag_diag_b, 0, n);
return possibilities;
}
private:
void solveNQueens(std::vector<std::vector<std::string>>& possibilities,
std::vector<std::string>& n_queens,
std::vector<int>& flag_col, std::vector<int>& flag_diag_a, std::vector<int>& flag_diag_b,
int row, int& n) {
if (row == n) {
possibilities.push_back(n_queens);
return;
}
for (int col = 0; col != n; col++) {
if (flag_col[col] && flag_diag_a[row + col] && flag_diag_b[n - 1 + col - row]) {
flag_col[col] = flag_diag_a[row + col] = flag_diag_b[n - 1 + col - row] = 0;
n_queens[row][col] = 'Q';
solveNQueens(possibilities, n_queens, flag_col, flag_diag_a, flag_diag_b, row + 1, n);
n_queens[row][col] = '.';
flag_col[col] = flag_diag_a[row + col] = flag_diag_b[n - 1 + col - row] = 1;
}
}
}
};
For interview, you should not probably use:
#include<bits/stdc++.h>
using namespace std;
and make sure to write clean codes.
N Queens is a low frequency interview question. There are much better questions to be asked in the interviews (such as Number of Islands), probably you would not get N Queens. But, it's good to practice.
This is a pretty simple way to solve the problem of the N-Queens using backtracking:
#include <bits/stdc++.h>
using namespace std;
int m[20][20];
bool ended = false;
void print(int n){
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
cout<<(m[i][j] == -1? "O" : "-")<<" ";
}
cout<<endl;
}
}
void fill(int val, int row, int col, int n){
int d = 1;
for(int i = col + 1; i < n; i++, d++){
m[row][i] += val;
if(row - d >= 0) m[row - d][i] += val;
if(row + d < n) m[row + d][i] += val;
}
}
void solve(int n, int col = 0){
if(ended) return;
if(col == n){ print(n); ended = true; return; }
for(int i = 0; i < n; i++){
if(m[i][col] == 0){
m[i][col] = -1;
fill(1, i, col, n);
solve(n, col + 1);
m[i][col] = 0;
fill(-1, i, col, n);
}
}
}
int main(){
memset(m, 0, sizeof(m));
solve(8); //dimension of board
return 0;
}
The idea is to always look forward. Place a queen in a slot that is 0 in the matrix. After that, add 1 in all slots where she can move to. When you return from the backtracking, subtract 1 from the same slots you just added and continue trying.

Segmentation Fault: 11 on small input for array/vector

There are several questions related to this error on stackoverflow, and I understand that its related to excess memory usage by the array, or when using pointers (I tried this with vectors aswell) but using a small array, it still shows this error. The same code earlier was running fine (for merge sorting an array).
My input was as follows:
5
9 8 1 2 4
Output:
Segmentation fault: 11
#include<iostream>
#include<vector>
using namespace std;
void merge(vector <int> ar, int l, int m, int r){
int n1 = m-l+1;
int n2 = r-m;
int L[n1];
int R[n2];
for (int i = 0; i < n1; ++i)
{
L[i]=ar[l+i];
}
for (int j = 0; j < n2; ++j)
{
R[j]=ar[m+j+1];
}
int i,j;
i = j = 0;
int k = i;
while(i<n1 && j<n2){
if (L[i]<R[j])
{
ar[k]=L[i];
i++;
}
else if (R[j]<L[i])
{
ar[k]=R[j];
j++;
}
k++;
}
while(i<n1){
ar[k]=L[i];
i++;
k++;
}
while(j<n2){
ar[k]=R[j];
j++;
k++;
}
}
void mergesort(vector <int> ar, int l, int r){
int m;
m=r+(l-r)/2;
if (l<r)
{
mergesort(ar, l, m);
mergesort(ar, m+1, r);
merge(ar, l, m, r);
}
}
void print(vector <int> ar, int size){
for (int i = 0; i < size; ++i)
{
cout<<ar[i]<< " ";
}
}
int main()
{
int n;
cin>>n;
vector <int> ar;
for (int i = 0; i < n; ++i)
{
cin>>ar[i];
}
print(ar,n);
mergesort(ar, 0, n-1);
print(ar, n);
return 0;
}
The problem is in part with m=r+(l-r)/2. When l is 0 and r is 1, (l-r)/2 is 0. This makes m equal to 1, l equal to 0, and r equal to 1 and the mergesort(ar, l, m); call identical to the one it just worked through. The stack grows unbounded until you have a segmentation fault. One way to fix this which will also make your code more efficient is to merge the lists when the difference between l and r is below some threshold. Or, you can just swap the two elements when you get to the point where l and r differ by one, like so:
if (l - r <= 1) {
int temp = ar[l];
ar[l] = ar[r];
ar[r] = temp;
return;
}

Matrix determinant algorithm C++

I'm new to programming and I was looking for a way to find the determinant of a matrix. I found this code online, but I have trouble understanding the algorithm in place here. I have no problems for the base of the recursion , but the continue and main loop I have trouble understanding. Big thanks to anyone who can explain to me the algorithm.
int determ(int a[MAX][MAX],int n) {
int det=0, p, h, k, i, j, temp[MAX][MAX];
if(n==1) {
return a[0][0];
} else if(n==2) {
det=(a[0][0]*a[1][1]-a[0][1]*a[1][0]);
return det;
} else {
for(p=0;p<n;p++) {
h = 0;
k = 0;
for(i=1;i<n;i++) {
for( j=0;j<n;j++) {
if(j==p) {
continue;
}
temp[h][k] = a[i][j];
k++;
if(k==n-1) {
h++;
k = 0;
}
}
}
det=det+a[0][p]*pow(-1,p)*determ(temp,n-1);
}
return det;
}
}
This algorithm uses a divide-conquer approach for solving the problem (finding the determinant of an N*N Matrix).
The algorithm uses a recursive pattern which is one of divide and conquer approaches. You can find out this by noticing the algorithm is calling itself in the third condition statement.
Every recursive algorithm have an exit condition which is the first if-statement in your code. and they also contain a section which is the solution to the most convenient problem or an atomic problem of the main big problem which is hard to solve in the first place. The atomic problem or the most-divided problem can be solved easily as you can see the the second if-statement of your code. In your case it is actually solving the determinant of a 2*2 Matrix.
The most important part of your code to understand which is challenging a little bit too is the part you do the dividing (which is recursive too!).
This part has the key to conquering either. By doing a little back trace and numerical examples you can find it out:
det = det + a[0][p] * pow(-1,p) * determ(temp,n-1);
For the final suggestion try a 3*3 Matrix which only needs one dividing.
Good luck with that.
This book is a great one to start studying and understanding algorithms
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
int **submatrix(int **matrix, unsigned int n, unsigned int x, unsigned int y) {
int **submatrix = new int *[n - 1];
int subi = 0;
for (int i = 0; i < n; i++) {
submatrix[subi] = new int[n - 1];
int subj = 0;
if (i == y) {
continue;
}
for (int j = 0; j < n; j++) {
if (j == x) {
continue;
}
submatrix[subi][subj] = matrix[i][j];
subj++;
}
subi++;
}
return submatrix;
}
int determinant(int **matrix, unsigned int n) {
int det = 0;
if (n == 2) {
return matrix[0][0] * matrix[1][1] - matrix[1][0] * matrix[0][1];
}
for (int x = 0; x < n; ++x) {
det += ((x % 2 == 0 ? 1 : -1) * matrix[0][x] * determinant(submatrix(matrix, n, x, 0), n - 1));
}
return det;
}
int main() {
int n;
cin >> n;
int **matrix = new int *[n];
for (int i = 0; i < n; ++i) {
matrix[i] = new int[n];
for (int j = 0; j < n; ++j) {
cin >> matrix[i][j];
}
}
cout << determinant(matrix, n);
return 0;
}

Find all possible arrays of size n constructed with all possible combinations of elements from another array in all possible orders?

For an array A of arbitrary length n, I'd like to fill in a n x m array B with all combination of elements from A that includes all possible orders of those elements. For example, if A = {1, 2, 3} and m = 2, I'd like to get B as:
11
12
13
21
22
23
31
32
33
What is an efficient way to do this in C/C++? Thanks!
EDIT: Here is what I figured out to work (data is within the class combs which is basically a matrix class with some added tricks):
void combs::setCombs (int arr[], int n, int m) {
int z, tmp, repeat;
int max = (int (pow(double (n), double( m ))));
for (int i = 0; i < m; i++) {
z = 0;
repeat = int (pow( double (n), double (i)));
for (int j = 0; j < repeat; j++) {
for (int k = 0; k < n; k ++) {
for (int p = 0; p < max/(n*repeat); p ++) {
cout << arr[k] << endl;
data[z*ROWS + i] = arr[k];
z++;
}
}
}
}
}
As mentioned by #Joachim Pileborg your question lacks a lot in the way of parameters.But lets say you could guarantee that you were passing me a vector of SORTED UNIQUE ints. Then this brute force would be possible:
std::vector< std::string > Combo( const std::vector< char >& source, int m )
{
std::vector< std::vector< char >::const_iterator > digits( length, source.cbegin() );
std::vector< std::string > result( source.size() * m );
for( int i = 0; i < result.size(); i++ )
{
for( int j = 0; j < m; j++ )
{
result[i] += *(digits[j]);
}
for( int j = digits.size() - 1; j >= 0; j-- )
{
++digits[j];
if( digits[j] == source.cend() )
{
digits[j] = source.cbegin();
}
else
{
break;
}
}
}
return result;
}
What you are describing sounds like partial permutations, not combinations.
If you are using c++, then it is recommended to use vectors, because vectors can tell you their size, and they free their own memory. An implementation with vectors would be as follows:
vector<vector<int> > partialPermutations(vector<int> &A,int m){
int i,i2,t,n=A.size(),total=1;
for(i=0;i<m;i++) total*=n;
vector<vector<int> > result;
for(i=0;i<total;i++){
result.push_back(vector<int>());
t=i;
for(i2=0;i2<m;i2++){
result[i].push_back(A[t%n]);
t/=n;
}
}
return result;
}
int main() {
vector<int> A;
int total,i,i2;
for(i=1;i<=4;i++) A.push_back(i);
vector<vector<int> > re=partialPermutations(A,2);
for(i=0;i<re.size();i++){
for(i2=0;i2<2;i2++)
cout<<re[i][i2]<<" ";
cout<<endl;
}
return 0;
}
If you still want to use arrays, then the code would be as follows:
int** partialPermutations(int*A,int n,int m,int &total){
int i,i2,t;
total=1;
for(i=0;i<m;i++) total*=n;
int **result=new int*[total];
for(i=0;i<total;i++){
t=i;
result[i]=new int[m];
for(i2=0;i2<m;i2++){
result[i][i2]=A[t%n];
t/=n;
}
}
return result;
}
int main() {
int A[]={1,2,3,4};
int total,i,i2;
int **re=partialPermutations(A,4,2,total);
for(i=0;i<total;i++){
for(i2=0;i2<2;i2++)
cout<<re[i][i2]<<" ";
cout<<endl;
}
//Cleanup
for(i=0;i<total;i++) delete[] re[i];
delete[] re;
return 0;
}
Notice that by using arrays, we have to recover the size of the resulting array (passing total by reference), and we have to free the memory afterwards. None of this is needed with vectors.
#include<iostream>
using namespace std;
void printStrRec(string s,string ans,int k,int i)
{
if(i==k)
{
cout<<"\nAnswer : "<<ans<<endl;
}
else
{
for(int x=0;x<s.size();++x)
{
ans[i]=s[x];
printStrRec(s,ans,k,i+1);
}
}
}
void printStrings(string s,int k)
{
string ans;
for(int p=0;p<k;++p)
{
ans+="x";
}
printStrRec(s,ans,k,0);
}
int main()
{
int k;
string s;
cout<<"Enter the set : ";
cin>>s;
cout<<"\nEnter k : ";
cin>>k;
printStrings(s,k);
return 0;
}
Hope that helps.