Maximize The Cut Segments using top down approach? - c++

Given an integer N denoting the Length of a line segment. You need to cut the line segment in such a way that the cut length of a line segment each time is either x , y or z. Here x, y, and z are integers.
After performing all the cut operations, your total number of cut segments must be maximum.
Example 1
Input:
N = 4
x = 2, y = 1, z = 1
Output: 4
Explanation:Total length is 4, and the cut
lengths are 2, 1 and 1. We can make
maximum 4 segments each of length 1.
Example 2
Input:
N = 5
x = 5, y = 3, z = 2
Output: 2
Explanation: Here total length is 5, and
the cut lengths are 5, 3 and 2. We can
make two segments of lengths 3 and 2.
This is my solution
int max_seg(int M[], int n, int x, int y, int z)
{
if( (n<=0) && (M[0] != -1) )
return M[0];
else if( (n>0) && M[n] != -1)
return M[n];
int q;
if(n <= 0)
{
q = 0;
M[0] = q;
return M[0];
}
else
{
q = max({1 + max_seg(M, n-x, x, y, z), 1 + max_seg(M, n-y, x, y, z), 1 + max_seg(M, n-y, x, y, z) });
M[n] = q;
return M[n];
}
}
int maximizeTheCuts(int n, int x, int y, int z)
{
//Your code here
int M[n+1] = {0}; // compiler does permit this
for(int i=0; i<=n; i++)
M[i] = -1;
return max_seg(M, n, x, y, z);
}
What is wrong with my code. Any help appreciated.
It failed for the test case below
N= 4000
x=3 y=4 z=5
returned 1334 instead of 1333

You'd need to ensure that max_seg is never called with a negative n, or else that, if called with negative n, it returns a value that won't be taken as the best solution. – #IgorTandetnik
fix
int max_seg(int M[], int n, int x, int y, int z)
{
if( (n<0) )
return INT_MIN;
else if( (n>=0) && M[n] != -1)
return M[n];
int q;
if(n <= 0)
{
q = 0;
M[0] = q;
return M[0];
}
else
{
q = max({1 + max_seg(M, n-x, x, y, z), 1 + max_seg(M, n-y, x, y, z), 1 + max_seg(M, n-y, x, y, z) });
M[n] = q;
return M[n];
}
}
int maximizeTheCuts(int n, int x, int y, int z)
{
//Your code here
int M[n+1] = {0}; // compiler does permit this
for(int i=0; i<=n; i++)
M[i] = -1;
return max_seg(M, n, x, y, z);
}

Related

Dynamic programming - Gold mine grid optimization TLE

I'm trying to solve Gold Mine problem from https://practice.geeksforgeeks.org/problems/gold-mine-problem2608/1/#. I am receiving TLE for the following code. I have looked at the solution also yet dont understand what minor mistake I made that the code received TLE and the solution code.
class Solution{
public:
int helper(int a , int b, int n , int m , vector<vector<int>> M, vector<vector<int>> &N){
if(a<0 || b<0 || a>=n){
return INT_MIN ;
}
if(N[a][b]!=-1){
return N[a][b];
}
if(b==m){
N[a][b] = 0;
return 0;
}
else{
N[a][b] = M[a][b] + max( (helper(a+1,b+1,n,m,M,N)) , max(helper(a-1,b+1,n,m,M,N),helper(a,b+1,n,m,M,N)));
return N[a][b] ;
}
// return N[a][b];
}
int maxGold(int n, int m, vector<vector<int>> M)
{
// code here
vector<vector<int>> N(n,vector<int>(m+1,-1) );
int ans = 0 ;
for(int i=0; i<n; i++){
// int ans2 = helper(i,0,n,m,M,N);
// if(ans2>ans){
// ans = ans2;
// }
ans = max(ans,helper(i,0,n,m,M,N));
}
return ans;
// just one extra in right to store 0s
// position a,b to a,b
// n,m to n-1,m-1
}
};
The solution given on the site :
// C++ program to solve Gold Mine problem
#include<bits/stdc++.h>
using namespace std;
int collectGold(vector<vector<int>> gold, int x, int y, int n, int m, vector<vector<int>> &dp) {
// Base condition.
if ((x < 0) || (x == n) || (y == m)) {
return 0;
}
if(dp[x][y] != -1){
return dp[x][y] ;
}
// Right upper diagonal
int rightUpperDiagonal = collectGold(gold, x - 1, y + 1, n, m, dp);
// right
int right = collectGold(gold, x, y + 1, n, m, dp);
// Lower right diagonal
int rightLowerDiagonal = collectGold(gold, x + 1, y + 1, n, m, dp);
// Return the maximum and store the value
return dp[x][y] = gold[x][y] + max(max(rightUpperDiagonal, rightLowerDiagonal), right);
}
int getMaxGold(vector<vector<int>> gold, int n, int m)
{
int maxGold = 0;
// Initialize the dp vector
vector<vector<int>> dp(n, vector<int>(m, -1)) ;
for (int i = 0; i < n; i++) {
// Recursive function call for ith row.
int goldCollected = collectGold(gold, i, 0, n, m, dp);
maxGold = max(maxGold, goldCollected);
}
return maxGold;
}
I suppose that calculating all 3 directions differently and then taking max seems to make the actual solution faster, but would like to understand the reason for the same to improve myself.
EDIT1 - Nope, still received TLE after calculating differently for all 3 directions, although it did manage to do more test cases which I dont understand why.

How can I get the common digits of two int in C++? Example: (1234, 41567) --> 1 4

Given two int I want to get all the common digits and print out them separated by spaces.
So for example, if int x=1234; int y=41567; then I want to print out: 1 4.
This is my code. It does not work properly. When I run it, it prints 0 1 2 3 4 5 then stops.
I don't want to use vector nor arrays.
void problema3() {
int x, y, kX=0, kY=0;
cout << "x="; cin >> x;
cout << "y="; cin >> y;
int cx = x;
int cy = y;
for (int i = 0; i < 10; i++) {
kX = 0;
kY = 0;
x = cx;
y = cx;
while (x != 0 || kX==0) {
if (x % 10 == i) kX=1;
x /= 10;
}
while (y != 0 || kY == 0) {
if (y % 10 == i) kY=1;
y /= 10;
}
if (kX == 1 && kY == 1) cout << i << ' ';
}
}
int main()
{
problema3();
return 0;
}
If you're allowed to use std::set then you can do what you want as follows:
#include <iostream>
#include <set>
void print(int x, int y)
{
int individual_number1 = 0, individual_number2 = 0;
std::set<int> myset;
int savey = y;//this will be used to reset y when the 2nd do while loop finishes
do
{
individual_number1 = x % 10;
do
{
individual_number2 = y % 10;
if(individual_number1 == individual_number2)
{
myset.insert(individual_number1);
break;
}
y = y / 10;
}while( y > 0);
y = savey;
x = x / 10;
} while (x > 0);
//print out the element of the set
for(int i: myset)
{
std::cout<<i<<" ";
}
}
int main()
{
int x = 1234, y = 41567;
print(x, y);
return 0;
}
The output of the above program is as follows:
1 4
which can be seen here.
Your main bug is when assigning copies of cy.
//...
for (int i = 0; i < 10; i++) {
//...
x = cx;
y = cx; // <-- BUG! should read y = cy;
But that's not the only bug in your program.
Your digit detection logic is wrong. In particular, zero is not handled correctly, and since you did not put that reusable code in a function, your program is way more complex than it needs.
Here's the corrected logic for digit detection.
// checks if base 10 representation of a positive integer contains a certain digit (0-9)
bool hasDigit(int x, int d)
{
do
{
if (x % 10 == d)
return true;
x /= 10;
} while (x != 0);
return false;
}
Your main loop then becomes:
// assuming int x, y as inputs.
// ...
for (int i = 0; i < 10; ++i)
{
if (hasDigit(x, i) && hasDigit(y, i))
std::cout << i << ' ';
}
Which leaves very little room for bugs.
You can play with the code here: https://godbolt.org/z/5c5brEcEq

From recursive algorithm to an iterative one

I have to convert this recursive algorithm into an iterative one:
int alg(int A[], int x, int y, int k){
int val = 0;
if (x <= y){
int z = (x+y)/2;
if(A[z] == k){
val = 1;
}
int a = alg(A,x,z-1,k);
int b;
if(a > val){
b = alg(A,z+1,y,k);
}else{
b = a + val;
}
val += a + b;
}
return val;
}
I tried with a while loop, but I can't figure out how I can calculate "a" and "b" variables, so I did this:
int algIterative(int A[], int x, int y, int k){
int val = 0;
while(x <= y){
int z = (x+y)/2;
if(A[z] == k){
val = 1;
}
y = z-1;
}
}
But actually I couldn't figure out what this algorithm does.
My questions are:
What does this algorithm do?
How can I convert it to iterative?
Do I need to use stacks?
Any help will be appreciated.
I am not sure that alg computes anything useful.
It processes the part of the array A between the indexes x and y, and computes a kind of counter.
If the interval is empty, the returned value (val) is 0. Otherwise, if the middle element of this subarray equals k, val is set to 1. Then the values for the left and right subarrays are added and the total is returned. So in a way, it counts the number of k's in the array.
But, if the count on the left side is found to be not larger than val, i.e. 0 if val = 0 or 0 or 1 if val = 1, the value on the right is evaluated as the value on the left + val.
Derecursivation might be possible without a stack. If you look at the sequence of subintervals that are traversed, you can reconstruct it from the binary representation of N. Then the result of the function is the accumulation of partials results collected along a postorder process.
If the postorder can be turned to inorder, this will reduce to a single linear pass over A. This is a little technical.
A simple way could be smt like this with the aid of a two dimensional array:
int n = A.length;
int[][]dp = new int[n][n];
for(int i = n - 1;i >= 0; i--){
for(int j = i; j < n; j++){
// This part is almost similar to the recursive part.
int z = (i+j)/2;
int val = 0;
if(A[z] == k){
val = 1;
}
int a = z > i ? dp[i][z - 1] : 0;
int b;
if(a > val){
b = (z + 1 <= j) ? dp[z + 1][j] : 0;
}else{
b = a + val;
}
val += a + b;
dp[i][j] = val;
}
}
return dp[0][n - 1];
Explanation:
Notice that for i, it is decreasing, and j, it is increasing, so, when calculate dp[x][y], you need dp[x][z - 1] (with z - 1 < j) and dp[z + 1][j] (with z >= i), and those values should already be populated.

Print Sum of int > 0

Given a number S ( int > 0 ) and n (int > 0), print all the different subsets of len n which sum to S.
For S = 7 and n = 3, the output is the following, the output must be descending order:
5 + 1 + 1
4 + 2 + 1
3 + 3 + 1
3 + 2 + 2
Here is what I've tried so far:
vector<vector<int> > partitions(int X, int Y)
{
vector<vector<int> > v;
if (X <= 1 && X <= X - Y + 1)
{
v.resize(1);
v[0].push_back(X);
return v;
}
for (int y = min(X - 1, Y); y >= 1; y--)
{
vector<vector<int> > w = partitions(X - y, y);
for (int i = 0; i<w.size(); i++)
{
w[i].push_back(y);
v.push_back(w[i]);
}
}
return v;
}
int main()
{
vector<vector<int> > v = partitions(7, 3);
int i;
for (i = 0; i<v.size(); i++)
{
int x;
for (x = 0; x<v[i].size(); x++)
printf("%d ", v[i][x]);
printf("\n");
}
}
the first element in the matrix is s- n + 1 and full of 1 till the sum is reached, or if the s-n+1 is equal to s, then n is 1, so only s will be the solution.
p.s.: I don t know if this problem has a particular name
This may not be the best solution for your problem, since it's not a dynamic programming based solution. In this case, I'm using recursion to fill an array until I reduce the desired number to 0. In this solution, every combination will be stored in the increasing order of the elements so we prevent permutations of a already calculated solution.
#include <iostream>
void findCombinationGivenSize(int numbersArray[], int index, int num, int reducedNum, int maxNum){
if (reducedNum < 0)
return; // this is our base case
if (reducedNum == 0 && index == maxNum){ // both criteria were attended:
//the sum is up to num, and the subset contain maxNum numbers
for (int i = index - 1; i>=0; i--)
std::cout<< numbersArray[i] << " + ";
// here we will have a problem with an extra '+' on the end, but you can figure out easily how to remove it :)
std::cout<<std::endl;
return;
}
// Find the previous number stored in arrayNumber[]
int prev;
if(index == 0)
prev = 1;
else
prev = numbersArray[index-1];
for (int k = prev; k <= num; k++){
// next element of array is k
numbersArray[index] = k;
// call recursively with reduced number
findCombinationGivenSize(numbersArray, index + 1, num,reducedNum - k, maxNum);
}
}
void findCombinations(int number, int maxSubset){
int arrayNumbers[number];
findCombinationGivenSize(arrayNumbers, 0, number, number, maxSubset);
}
int main(){
int number = 7;
int maxPartitions = 3;
findCombinations(number, maxPartitions);
return 0;
}

to detect path in bfs

i am doing a standard problem to calculate min moves to reach target by a knight but i also want to keep track of path but its showing error.it dispalys
prog.cpp: In function
'int minStepToReachTarget(int*, int*, int)':
prog.cpp:76:42: error: no match for 'operator[]' (operand types are
'std::vector<cell>' and 'cell')
{q.push(cell(x, y, t.dis + 1));parent[cell(x, y, t.dis + 1)]=t;}
I have commented down the line 76 in my code.
struct cell {
int x, y;
int dis;
cell() {}
cell(int x, int y, int dis): x(x), y(y), dis(dis) {}
};
//cell parent[10000];
typedef cell c;
vector<c> parent(10000);
bool isInside(int x, int y, int N) {
if (x >= 1 && x <= N && y >= 1 && y <= N)
return true;
return false;
}
int minStepToReachTarget(int knightPos[], int targetPos[], int N) {
// x and y direction, where a knight can move
int dx[] = {-2, -1, 1, 2, -2, -1, 1, 2};
int dy[] = {-1, -2, -2, -1, 1, 2, 2, 1};
// queue for storing states of knight in board
queue<cell> q;
// push starting position of knight with 0 distance
q.push(cell(knightPos[0], knightPos[1], 0));
cell t;
int x, y;
bool visit[N + 1][N + 1];
// make all cell unvisited
for (int i = 1; i <= N; i++)
for (int j = 1; j <= N; j++)
visit[i][j] = false;
visit[knightPos[0]][knightPos[1]] = true;
// parent[cell(knightPos[0], knightPos[1], 0)]=t;
// loop untill we have one element in queue
while (!q.empty()) {
t = q.front();
//parent[t]=t;
q.pop();
visit[t.x][t.y] = true;
// if current cell is equal to target cell,
// return its distance
if (t.x == targetPos[0] && t.y == targetPos[1])
return t.dis;
// loop for all reahable states
for (int i = 0; i < 8; i++) {
x = t.x + dx[i];
y = t.y + dy[i];
// If rechable state is not yet visited and
// inside board, push that state into queue
if (isInside(x, y, N) && !visit[x][y]) {
q.push(cell(x, y, t.dis + 1));
//76 ERROR: parent[cell(x, y, t.dis + 1)]=t;}
}
}
}
int main() {
// size of square board
int N = 6;
int knightPos[] = {4, 5};
int targetPos[] = {1, 1};
int m= minStepToReachTarget(knightPos, targetPos, N);
cout<<m<<endl;
return 0;
}
#Code
int dx[8] = {-1,-2, 1 ,2 ,-1, -2, 1, 2};
int dy[8] = {-2,-1, -2,-1, 2, 1, 2, 1};
q.push(ppi(pi(kx, ky), 0));
while(!q.empty()){
pi cur = q.front().first; int d = q.front().second; q.pop();
int x = cur.first;
int y = cur.second;
// printf("%d %d %d\n", x,y, visited[x][y]);
if(visited[x][y]) continue;
visited[x][y] = true;
if (x == tx && y == ty){
printf("%d", d);
return 0;
}
for(int i = 0; i<8; i++){
int nx = x+dx[i];
int ny = y+dy[i];
if(nx <= 0 || nx > n || ny <= 0 || ny > n) continue;
q.push(ppi(pi(nx, ny), d+1));
}
}
printf("-1");
Explanation
Here, this is the bfs which I implemented. I am storing the grid as a boolean value, I can keep track of which squares I have traveled too. If I am unable to reach the square, I output -1. I would also recommend not using function calls unless really necessary, as this is a simple BFS question.
Extension
Just in case you want to find out more, I took the following chunk from my code for a harder problem, where there exists a grid with forbidden squares where the knight cannot travel. In that case, forbidden squares are initially marked as 'true' instead of 'false' to signify that is traveled so I will not go on it.
I hope my above solution helps.