Skip to content

Added DP problems #204

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions Competitive Coding/Dynamic Programming/cutRod/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Given a rod of length n inches and an array of prices that contains prices of all pieces of size smaller than n. Determine the maximum value obtainable by cutting up the rod and selling the pieces. For example, if length of the rod is 8 and the values of different pieces are given as following, then the maximum obtainable value is 22 (by cutting in two pieces of lengths 2 and 6)

length | 1 2 3 4 5 6 7 8
--------------------------------------------
price | 1 5 8 9 10 17 17 20

1) Optimal Substructure:
We can get the best price by making a cut at different positions and comparing the values obtained after a cut. We can recursively call the same function for a piece obtained after a cut.

Let cutRoad(n) be the required (best possible price) value for a rod of lenght n. cutRod(n) can be written as following.

cutRod(n) = max(price[i] + cutRod(n-i-1)) for all i in {0, 1 .. n-1}

2) Overlapping Subproblems
Like other typical Dynamic Programming(DP) problems, recomputations of same subproblems can be avoided by constructing a temporary array val[] in bottom up manner.
44 changes: 44 additions & 0 deletions Competitive Coding/Dynamic Programming/cutRod/cutRod.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include<stdio.h>
#include<limits.h>

// A utility function to get the maximum of two integers
int max(int a, int b)
{
return (a > b)? a : b;
}


/* Returns the best obtainable price for a rod of length n and
price[] as prices of different pieces */
int DPcutRod(int price[], int n)
{
int val[n+1];
val[0] = 0;
int i, j;
for (i = 1; i<=n; i++)
{
int max_val = INT_MIN;
// Recursively cut the rod in different pieces and compare different
// configurations
for (j = 0; j < i; j++)
max_val = max(max_val, price[j] + val[i-j-1]);
val[i] = max_val;
}
return val[n];
}

int main()
{
int n;
printf("Enter rod length\n");
scanf("%d",&n);
int arr[n],i;
printf("Enter prices for lengths 1 to n\n");
for(i=0;i<n;i++)
{
scanf("%d",&arr[i]);
}
printf("Maximum Obtainable Value is %d\n", DPcutRod(arr, n));
getchar();
return 0;
}
20 changes: 20 additions & 0 deletions Competitive Coding/Dynamic Programming/minCostPath/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Given a cost matrix cost[][] and a position (m, n) in cost[][], write a function that returns cost of minimum cost path to reach (m, n) from (0, 0). Each cell of the matrix represents a cost to traverse through that cell. Total cost of a path to reach (m, n) is sum of all the costs on that path (including both source and destination). You can only traverse down, right and diagonally lower cells from a given cell, i.e., from a given cell (i, j), cells (i+1, j), (i, j+1) and (i+1, j+1) can be traversed.

1) Optimal Substructure
The path to reach (m, n) must be through one of the 3 cells: (m-1, n-1) or (m-1, n) or (m, n-1). So minimum cost to reach (m, n) can be written as “minimum of the 3 cells plus cost[m][n]”.

minCost(m, n) = min (minCost(m-1, n-1), minCost(m-1, n), minCost(m, n-1)) + cost[m][n]

2) Overlapping Subproblems
Like other typical Dynamic Programming(DP) problems, recomputations of same subproblems can be
avoided by constructing a temporary array tc[][] in bottom up manner.


Example:
3 3
1 2 3
4 8 2
1 5 3

Ouptut:
8
55 changes: 55 additions & 0 deletions Competitive Coding/Dynamic Programming/minCostPath/minCostPath.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#include <iostream>
#include <algorithm>

using namespace std;

int main(){
std::ios::sync_with_stdio(false);
/*
We can easily observe that the optimum solution of the minimum
cost at any row i is only dependent on the cost at row i-1 and
the current row elements. Thus if we only store these two arrays
of length c, We have reduced space from n*m to 2*m.
*/

int i, j, r, c;
printf("Enter no of rows and no of cols\n");
cin>>r>>c; //take input of the rows and columns from user.
int cost[c], dp[c];
int x;
/*
Since for the first row the minimum cost is the only cost possible
required to get there, we directly calculate it.
*/
printf("Enter a R X C array\n");

for(i=0; i<c; i++){
cin>>cost[i];
if(i>0) cost[i] = cost[i] + cost[i-1];
}
/*
For the subsequent rows, the optimised cost for each cell in the
previous row has been stored in the array cost[] and the optimised
cost for the present row is stored in the array dp[].
*/
for(i=1; i<r; i++){
for(j=0; j<c; j++){
cin>>x;
if(j==0)
dp[j] = cost[j] + x;
else{
dp[j] = x + min(dp[j-1], min(cost[j-1], cost[j]));
}
}
/*
After dp[] has been found entirely, we copy its elements to
cost[] and continue the iteration.
*/
for(j=0; (j<c && i!=c-1); j++){
cost[j] = dp[j];
}
}
printf("The min cost path from 1,1 to r,c is\n");
cout<<dp[c-1]<<"\n";
return 0;
}
21 changes: 21 additions & 0 deletions Competitive Coding/Dynamic Programming/subsetSum/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Given a set of non-negative integers, and a value sum, determine if there is a subset of the given set with sum equal to given sum.

Examples: set[] = {3, 34, 4, 12, 5, 2}, sum = 9
Output: True //There is a subset (4, 5) with sum 9.

Let isSubSetSum(int set[], int n, int sum) be the function to find whether there is a subset of set[] with sum equal to sum. n is the number of elements in set[].

The isSubsetSum problem can be divided into two subproblems
…a) Include the last element, recur for n = n-1, sum = sum – set[n-1]
…b) Exclude the last element, recur for n = n-1.
If any of the above the above subproblems return true, then return true.

Following is the recursive formula for isSubsetSum() problem.

isSubsetSum(set, n, sum) = isSubsetSum(set, n-1, sum) ||
isSubsetSum(set, n-1, sum-set[n-1])
Base Cases:
isSubsetSum(set, n, sum) = false, if sum > 0 and n == 0
isSubsetSum(set, n, sum) = true, if sum == 0

We can solve the problem in Pseudo-polynomial time using Dynamic programming. We create a boolean 2D table subset[][] and fill it in bottom up manner. The value of subset[i][j] will be true if there is a subset of set[0..j-1] with sum equal to i., otherwise false. Finally, we return subset[sum][n]
45 changes: 45 additions & 0 deletions Competitive Coding/Dynamic Programming/subsetSum/subsetSum.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include <stdio.h>

// Returns true if there is a subset of a[] with sun equal to given sum
bool DP(int set[], int n, int sum)
{
// The value of subset[i][j] will be true if there is a
// subset of set[0..j-1] with sum equal to i
bool subset[n+1][sum+1];
// If sum is 0, then answer is true
for (int i = 0; i <= n; i++)
subset[i][0] = true;
// If sum is not 0 and set is empty, then answer is false
for (int i = 1; i <= sum; i++)
subset[0][i] = false;
// Fill the subset table in botton up manner
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= sum; j++)
{
if(j<set[i-1])
subset[i][j] = subset[i-1][j];
if (j >= set[i-1])
subset[i][j] = subset[i-1][j] ||
subset[i - 1][j-set[i-1]];
}
}
return subset[n][sum];
}

int main()
{
int n;
int sum;
printf("Enter no of elements of array and desired sum\n");
scanf("%d%d",&n,&sum);
int i,a[n];
printf("Enter the array\n");
for(i=0;i<n;i++)
scanf("%d",&a[i]);
if (DP(a, n+1, sum) == true)
printf("Found a subset with given sum\n");
else
printf("No subset with given sum\n");
return 0;
}
24 changes: 24 additions & 0 deletions Competitive Coding/Dynamic Programming/uglyNumbers/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Ugly numbers are numbers whose only prime factors are 2, 3 or 5. The sequence 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, … shows the first 11 ugly numbers. By convention, 1 is included.

Given a number n, the task is to find n’th Ugly number.

Input : n = 7
Output : 8

Input : n = 10
Output : 12

Input : n = 15
Output : 24

Input : n = 150
Output : 5832

DP method:
Here is a time efficient solution with O(n) extra space. The ugly-number sequence is 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, …
because every number can only be divided by 2, 3, 5, one way to look at the sequence is to split the sequence to three groups as below:
(1) 1×2, 2×2, 3×2, 4×2, 5×2, …
(2) 1×3, 2×3, 3×3, 4×3, 5×3, …
(3) 1×5, 2×5, 3×5, 4×5, 5×5, …

We can find that every subsequence is the ugly-sequence itself (1, 2, 3, 4, 5, …) multiply 2, 3, 5. Then we use similar merge method as merge sort, to get every ugly number from the three subsequence. Every step we choose the smallest one, and move one step after.
24 changes: 24 additions & 0 deletions Competitive Coding/Dynamic Programming/uglyNumbers/uglyNumbers.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include<bits/stdc++.h>
using namespace std;
int main()
{
printf("Enter no of test cases\n");
int t; cin >> t;
int i2, i3, i5;
i2 = i3 = i5 = 0;
int ugly[500];// To store ugly numbers
ugly[0] = 1;
for (int i = 1; i < 500; ++i) {
ugly[i] = min(ugly[i2]*2, min(ugly[i3]*3, ugly[i5]*5));//get minimum of possible solutions
ugly[i] != ugly[i2]*2 ? : i2++; // next_mulitple_of_2 = ugly[i2]*2;
ugly[i] != ugly[i3]*3? : i3++; // next_mulitple_of_3 = ugly[i3]*3
ugly[i] != ugly[i5]*5 ? : i5++; // next_mulitple_of_5 = ugly[i5]*5;
}
int n;
while(t--) {
printf("Enter 'n' for the nth ugly number\n");
cin >> n;
cout << ugly[n-1] << endl;
}
return 0;
}