├── .gitignore ├── Count-all-paths.C ├── README.md ├── largest-sum-longest-contiguous-sub-array.C ├── lis-pair.C ├── longest-increasing-sub-sequence.C └── minimum-cost-path.C /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.out 9 | *.so 10 | 11 | # Packages # 12 | ############ 13 | # it's better to unpack these files and commit the raw source 14 | # git has its own built in compression methods 15 | *.7z 16 | *.dmg 17 | *.gz 18 | *.iso 19 | *.jar 20 | *.rar 21 | *.tar 22 | *.zip 23 | 24 | # Logs and databases # 25 | ###################### 26 | *.log 27 | *.sql 28 | *.sqlite 29 | 30 | # OS generated files # 31 | ###################### 32 | .DS_Store 33 | .DS_Store? 34 | ._* 35 | .Spotlight-V100 36 | .Trashes 37 | ehthumbs.db 38 | Thumbs.db 39 | -------------------------------------------------------------------------------- /Count-all-paths.C: -------------------------------------------------------------------------------- 1 | /* 2 | Program to find all possible paths to reach to bottom-right cell starting from the top-left 3 | Can move only right,down or diagonally lower 4 | 5 | Enter the no of rows: 2 6 | Enter the no of columns: 2 7 | Total paths: 3 8 | 9 | j 10 | ___ 11 | i |1 1 12 | |1 3 13 | 14 | sum of all three sides, gives total path. 15 | */ 16 | 17 | 18 | #include 19 | 20 | int main() 21 | { 22 | int a[100][100],i,j,r,c; 23 | 24 | printf("Enter the no of rows: "); 25 | scanf("%d",&r); 26 | printf("Enter the no of columns: "); 27 | scanf("%d",&c); 28 | 29 | a[0][0] = 1; 30 | 31 | for(i=0;i 26 | 27 | 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. The total cost of a path to reach (m, n) is the 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. You may assume that all costs are positive integers. 28 | 29 | | 1 | 2 | 3 | 30 | |:-:|:-:|:-:| 31 | | 4 | 8 | 2 | 32 | | 1 | 5 | 3 | 33 | 34 | (forgive the highlighting of the first row it is of no special significance) 35 | 36 | **Solution:** 37 | 38 | **Me:** So how would you go on solving that?
39 | **Friend:** Oh, the properties I read talked about saving the sub-problems to make the computations easier!
40 | **Me:** What are the sub-problems here?
41 | **Friend:** Oh, it's too tough.
42 | **Me:** No, it's not we will work together.
43 | 44 | How would you normally solve it, forgetting about code for a minute?
45 | You probably eye all the cells, adding the cost along the path till you reach the destination. But you don't know if it's minimum, so you start adding again by traversing in a different direction. Then maybe after considering all paths, you come up with a cost that gives you the least.
46 | 47 | That's pretty much it.
48 | 49 | My friend interrupts,
50 | **Friend:** But the above method only solves the problem for one particular destination, what if we want to calculate the total cost for reaching a different destination.
51 | **Me:** Good point!
52 | **Friend:** That's why we store the minimum cost for reaching each cell in the array from the first cell. That way when we fill up all cells we will be left with solutions of every cell.
53 | **Friend:** I lost you there.
54 | **Me:** Haha, let me finish. 55 | 56 | So what do we know so far?
57 | - There's an array and we can move right, down and diagonally lower.
58 | - We need to print the minimum cost of traversing to the given destination.
59 | - And we start at the first cell.
60 | 61 | **Breaking down the problem:** 62 | 63 | **Me:** What is simply the cost of moving from [0,0] to [0,1]?
64 | **Friend:** It's `2 + 1 = 3`
65 | **Me:** What is the minimum cost of moving from [0,0] to [0,1]?
66 | **Friend:** Still 3, because there's no other way we could reach [0,1] since we can only move right or down or diagonally lower. We can **only** reach [0,1] from [0,0].
67 | **Me:** Excellent! So what is the minimum cost of moving from [0,1] to [0,2]?
68 | **Friend:** Oh wait, the cost of moving from **[0,0] to [0,1]** is **3**, hence **[0,1] to [0,2]** would be `3 + cost of getting to (0,2)` which is `3 + 3 = 6`.
69 | **Me:** Now shall we store this obtained cost corresponding to each cell in a different array, so that we can return them, when the cell is the destination?
70 | **Friend:** Fair enough. 71 | 72 | 73 | 74 | 75 |
Table A Min cost
76 | 77 | | 1 | 2 | 3 | 78 | |:-:|:-:|:-:| 79 | | 4 | 8 | 2 | 80 | | 1 | 5 | 3 | 81 | 82 | 83 | 84 | | 1 | 3 | 6 | 85 | |:-:|:-:|:-:| 86 | | - | - | - | 87 | | - | - | - | 88 | 89 |
90 | 91 | Why not code it up too? 92 | 93 | minarr[0][0] = a[0][0]; 94 | 95 | for(i=1;i 101 | 102 | **Friend:** Why not the columns? The cells in the first column have only one way of reaching them too, which is down from the first cell.
103 | **Me:** Yeah absolutely, that's our next step. 104 | 105 | Similarly, we calculate the cost of reaching each column by adding the cell with the previous ones in the column. 106 | 107 | 108 | 109 |
Table A Min cost
110 | 111 | | 1 | 2 | 3 | 112 | |:-:|:-:|:-:| 113 | | 4 | 8 | 2 | 114 | | 1 | 5 | 3 | 115 | 116 | 117 | 118 | | 1 | 3 | 6 | 119 | |:-:|:-:|:-:| 120 | | 5 | - | - | 121 | | 6 | - | - | 122 | 123 |
124 | 125 | We'll code that up too! 126 | 127 | for(i=1;i 134 | **Me:** We know we can only traverse left, down or diagonally lower cell. Hence we can reach cell [1,1] only from cell [0,0] or [0,1] or [1,0]. So now that our table already has the minimum values to reach [0,0], [0,1] and [1,0], simply the minimum of those three values plus the cost of reaching cell [1,1] gives us our result.
135 | 136 | So the `cost to reach cell [1,1] = a[1,1] + min(minarr[0,0], minarr[0,1], minarr[1,0])`
137 | `minarr[1,1] = 8 + min(1,3,5)`
138 | So, `minarr[1,1] = 9`
139 | 140 | Similarly, we do for all cells, starting from 1,1. 141 | 142 | Let's code it up again, 143 | 144 | for(i=1;i 150 | Table A Min cost 151 | 152 | 153 | | 1 | 2 | 3 | 154 | |:-:|:-:|:-:| 155 | | 4 | 8 | 2 | 156 | | 1 | 5 | 3 | 157 | 158 | 159 | 160 | | 1 | 3 | 6 | 161 | |:-:|:-:|:-:| 162 | | 5 | 9 | 5 | 163 | | 6 |10 | 8 | 164 | 165 | 166 | 167 | Now that our table is filled, we simply return the cell of the given destination in the minimum cost array. The full code is [given here](https://github.com/nobodyme/Dynamic-Programming/blob/master/minimum-cost-path.C). Here is a [similar problem](http://practice.geeksforgeeks.org/problems/largest-zigzag-sequence/0), try it on your own and another similar problem is added in the [repository](https://github.com/nobodyme/dynamic-programming/blob/master/Count-all-paths.C). 168 | 169 | Hence by considering the elements one by one we have built up our solution or in DP terms, we have acquired our solution in bottom-up fashion(tabulation method) from the sub-problems. There's another approach to it called memoization. The difference between both is explained in the [article over here](http://www.geeksforgeeks.org/tabulation-vs-memoizatation/). 170 | 171 | ## Longest increasing subsequence 172 | 173 | The Longest Increasing Subsequence (LIS) problem is to find the length of the longest subsequence of a given sequence such that all elements of the subsequence are sorted in increasing order. 174 | For example, the length of LIS for {10, 12, 32, 2, 22, 23, 25, 30} is 6 and LIS is {10, 12, 22, 23, 25, 30} 175 | 176 | **Solution:** 177 | 178 | How would go on solving this problem? What would you store to make the calculations easier? Okay simply, how would you solve the above problem using **brute force** just like how you would perform a [selection sort](https://en.wikipedia.org/wiki/Selection_sort)! 179 | 180 | 181 | | 10 | 12 | 32 | 2 | 22 | 23 | 25 | 30 | 182 | |:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:| 183 | | k,i | j | | | | | | | 184 | 185 | 186 | **Friend:** I would compare every element with every other element, if it's greater than the current one, I would increase the count variable and I would print the highest count, I get. Roughly I would code it something like this
187 | 188 | ***pseudo code*** (It's okay if you don't understand my friend's code)
189 | 190 | for(i=0;i a[k]) 196 | { 197 | k=j; 198 | count++; 199 | } 200 | if(count>maxi) 201 | maxi = count; 202 | } 203 | } 204 | printf("\nMax-length = %d\n",maxi); 205 | 206 | 207 | **Me:** Let's run it.
208 | **Friend:** Uh? Okay.
209 | **Me:** So what's the output?
210 | **Friend:** The program returns, `max-length = 5`, which I guess is {2, 22, 23, 24, 25}. But we know it's 6 and the LIS is {10, 12, 22, 23, 25, 30}.
211 | Why does it fail to catch the above lis?
212 | 213 | **Me:** Because while traversing {10, 12, 32, 22, 23, 25, 30} the code will run as follows,it will check,
214 | if(10>12) yes--> count is 2, then
215 | if(32>12) yes--> count is 3, then
216 | At this point **count = 3**, from there on count won't get incremented because the following elements are lesser than 32 and hence condition like (22>32) will consecutively fail.
217 | 218 | **Friend:** If only it knew that by **avoiding 32** and traversing through the rest of the array we would actually obtain the result which is `max-length = 6`.
219 | **Me:** This is exactly the information we store for our computation using DP. In brute force terms, we store the count variable for all possible alternatives of traversal in the array and then simply find the maximum of it (Note: Not that brute force cannot solve the problem, a different approach might but definitely in exponential time). 220 | 221 | **NOTE:** And my friend has set count=1 and not 0 initially because when we have a case where all numbers are the same in the array i.e {2, 2, 2, 2}. We must return count as 1 since one element { 2 } is still a subarray of the larger one. 222 | 223 | **Dp solution:** 224 | 225 | **Me:** So how would you code the same in DP, well actually it's easier.
226 | **Friend:** Since you said we store counts of all variables, we initialize an array of same size of corresponding counts?
227 | **Me:** Exactly, we first start by creating another array for storing the count for each member of the array as we discussed and initialize all of them to **1**.
228 | 229 | | array | 10 | 12 | 32 | 2 | 22 | 23 | 25 | 30 | 230 | |:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:| 231 | |count | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 232 | | | j | i | | | | | | | 233 | 234 | **Friend:** Now we check in a similar way?
235 | **Me:** Yeah but for now, lets us consider only the element **10** exists in the array.
236 | **Friend:** Why?
237 | **Me:** To make it simpler?! Why else? Listen along. So what is the longest increasing subsequence then?
238 | **Friend:** 1 of course and LIS is {10}.
239 | **Me:** So now, say, we add 12 and set its initial count to 1 240 | 241 | | array | 10 | 12 | 242 | |:-:|:-:|:-:| 243 | |count | 1 | 1 | 244 | | | j | i | 245 | 246 | **Friend:** We check **if(12>10)** so 12's count gets incremented?
247 | **Me:** Yes, now that 12>10, 12's count becomes `count of 10 + 1` since count of 10 already represents the longest increasing subsequence that can be made with the existing elements. Count of 12 now represents {10} + {12} = {10 ,12} or simply `count[i] = count[j]+1;` which is 2
248 | 249 | **Friend:** So let me clear this up, when 10 was alone LIS is 1 and now that 12 is added and we find {10, 12} could be LIS since 12>10 and so we add count of 10's to 12's count and add 1 to include the number itself.
250 | **Me:** That's right and the array becomes,
251 | 252 | | array | 10 | 12 | 253 | |:-:|:-:|:-:| 254 | |count | 1 | 2 | 255 | | | j | i | 256 | 257 | 258 | Now let us consider 32, increment `i to 32 and j to 10` i.e. j to the starting element of the array and traverse from the beginning to see **adding 32** provides a longer subsequence. 259 |
The array becomes, 260 | 261 | 262 | | array | 10 | 12 | 32 | 263 | |:-:|:-:|:-:|:-:| 264 | |count | 1 | 2 | 1 | 265 | | | j | | i | 266 | 267 |
**Friend:** Yes, it does prove longer. Since **(32>10)** therefore we increment 32's count --> count[i] = count[j]+1; 268 | 269 | **Me:** We check all numbers before 32 to see if they can be added to form a sequence with it, so increment j, continue filling in the boxes! 270 | 271 | ![animated](https://user-images.githubusercontent.com/22789194/27852855-3ce86814-6150-11e7-9a31-bcb108e1308d.gif) 272 | 273 |
**Friend**: Okay I will, So **if(32>12)** --> 32's count = 12's count + 1 = (2+1) = 3 274 | 275 | | array | 10 | 12 | 32 | 276 | |:-:|:-:|:-:|:-:| 277 | |count | 1 | 2 | 3 | 278 | | | | j | i | 279 | 280 |
Similarly, **considering element 2** the array becomes, 281 | 282 | | array | 10 | 12 | 32 | 2 | 283 | |:-:|:-:|:-:|:-:|:-:| 284 | |count | 1 | 2 | 3 | 1 | 285 | | | j | | | i | 286 | 287 |
The array stays the same since each case checking **if(2>10)** , **if(2>12)** or **if(2>32)** fails, and it's count variable remains unchanged. 288 | 289 |
Now I'm adding the next number, **22** and check for 10, 12, 32, similar to the previous one, for 10 and 12, the count of 22 is incremented to 3 and with 32 it fails and remains as 3, and j is incremented to point 2. 290 | 291 | | array | 10 | 12 | 32 | 2 | 22 | 292 | |:-:|:-:|:-:|:-:|:-:|:-:| 293 | |count | 1 | 2 | 3 | 1 | 3 | 294 | | | | | | j | i | 295 | 296 |
Now **if(22 > 2)** --> count of 22 becomes `count[j]+1` i.e. 2? 297 |
**Me:** Haha, glad you paused and asked, in short, **No**, we know that count reflects the longest subsequence. By traversing other elements in the array, we obtained 3 as the longest subsequence for 22. So why lower it to 2? Hence while adding `count[i] = count[j]+1` make sure it benefits the cause. Therefore place `count[i] = max(count[j]+1,count[i])` ie with the maximum of two numbers to avoid such cases. 298 | 299 | 300 | 301 | And similarly the rest of the array is traversed and the array becomes, 302 | 303 | | array | 10 | 12 | 32 | 2 | 22 | 23 | 25 | 30 | 304 | |:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:| 305 | |count | 1 | 2 | 3 | 1 | 3 | 4 | 5 | 6 | 306 | | | | | | | | | j | i | 307 | 308 | Since the highest is 6, which gives the longest increasing subsequence, the video of the above traversal is [linked here(different example)](https://youtu.be/Ns4LCeeOFS4). Let's have a look at the code snippet of the same below. 309 | As we have learned, 310 | - We initialize the count array to 1 311 | - Then calculate the count for every element 312 | 313 | for(i=0;i array[j]) 321 | count[i] = max(count[i],count[j]+1); 322 | } 323 | } 324 | 325 | After that, we find the maximum of the count array and print it, [full code snippet is here](https://github.com/nobodyme/Dynamic-Programming/blob/master/longest-increasing-sub-sequence.C) and a look-alike problem just with a [pair of numbers](https://github.com/nobodyme/dynamic-programming/blob/master/lis-pair.C). 326 | 327 | ## More to come 328 | 329 | - Minimum coin change 330 | 331 | ## Points to remember 332 | 333 | - Dynamic programming is just like any other kind, you get some, you don't get some, practice makes it all better. I have lot to do too. 334 | - From my experience, it is similar to brute force but instead of exploring the whole input space, you find a way to store intermediate results that arise from the input and exhaustively explore that for the required result. 335 | - Yes, it is indeed a method of trading space for time. A recursive approach may utilize a little less space but dynamic programming approach is quicker. 336 | 337 | ## Other resources 338 | - [Hackerearth article explaining more on "Why dynamic programming"](https://www.hackerearth.com/practice/notes/dynamic-programming-i-1/) 339 | - [How to approach Dynamic Programming by Paul Baltescu on Quora](https://www.quora.com/What-are-some-good-ways-to-approach-a-dynamic-programming-question/answer/Paul-Baltescu) 340 | - [Geeks for geeks tutorials](http://www.geeksforgeeks.org/fundamentals-of-algorithms/#DynamicProgramming) 341 | - [Hackerearth article for problems involving grids](https://www.hackerearth.com/practice/notes/dynamic-programming-problems-involving-grids/) 342 | 343 | 344 | ## Problems lists from various sites 345 | 346 | - [Practice problems - Geeks for Geeks](http://practice.geeksforgeeks.org/topics/Dynamic-Programming/) 347 | - [Problem list - top coder](https://apps.topcoder.com/forums/?module=Thread&start=0&threadID=674592) 348 | - [Problem sets - code forces](http://codeforces.com/problemset/tags/dp?order=BY_SOLVED_DESC) 349 | - [Dp challenges - Hackerrank](https://www.hackerrank.com/domains/algorithms/dynamic-programming) 350 | 351 | -------------------------------------------------------------------------------- /largest-sum-longest-contiguous-sub-array.C: -------------------------------------------------------------------------------- 1 | /*Program to find the largest-sum-longest-contiguous-sub-array 2 | 3 | Input: 3,1,-5,-8,0,2,2 4 | Output: Sum: 4 5 | Sub-array: 0,2,2 6 | 7 | Although [3,1] gives sum as 4 which is same as [0,2,2] the latter is the longest*/ 8 | 9 | #include 10 | 11 | int main() 12 | { 13 | int a[] = {3,1,-5,-8,0,2,2}; 14 | int i,sum,start,end,n,max_value,start_max,end_max; 15 | 16 | n = sizeof(a)/sizeof(a[0]); 17 | 18 | //max sums of all 19 | max_value = sum = a[0]; 20 | //start-point and end-point of max array 21 | start_max = 0; 22 | end_max = -1; 23 | //start and end check 24 | start = end = 0; 25 | 26 | for(i=1;i end_max - start_max) 54 | { 55 | start_max = start; 56 | end_max = end; 57 | } 58 | 59 | } 60 | 61 | //print sum and sub-array 62 | printf("Sum: %d\nSub-array: ",max_value); 63 | 64 | for(i=start_max;i<=end_max;i++) 65 | printf("%d ",a[i]); 66 | 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /lis-pair.C: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int max(int a,int b) 5 | { 6 | return a > b ? a : b; 7 | } 8 | 9 | int max_incre(int array[100][2],int n) 10 | { 11 | int count[5],i,j,maxi = 1; 12 | 13 | for(i=0;iarray[j][1]) 27 | count[i] = max(count[i],count[j]+1); 28 | 29 | if(count[i] > maxi) 30 | maxi = count[i]; 31 | } 32 | return maxi; 33 | } 34 | 35 | int main() 36 | { 37 | int i,n,array[][2]={{5,24},{39,60},{15,28},{27,40},{50,90}}; 38 | n = sizeof(array)/sizeof(array[0]); //returns no of elements in the array 39 | 40 | printf("Lis = %d\n",max_incre(array,n)); 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /longest-increasing-sub-sequence.C: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int max(int a,int b); 5 | void max_inc(int array[100],int n); 6 | 7 | // return maximum of two numbers 8 | int max(int a,int b) 9 | { 10 | return a>b ? a : b; 11 | } 12 | 13 | void max_inc(int array[100],int n) 14 | { 15 | int count[100],maxi; 16 | int i,j; 17 | 18 | //set all elements of count to 1 19 | for(i=0;i array[j]) 28 | count[i] = max(count[i],count[j]+1); 29 | } 30 | 31 | //finding the maximum no in the count array 32 | 33 | for (i = 0; i < n; i++ ) 34 | if (maxi < count[i]) 35 | { 36 | maxi = count[i]; 37 | } 38 | 39 | //print max count 40 | 41 | printf("\nMax-length = %d\n",maxi); 42 | 43 | } 44 | 45 | int main() 46 | { 47 | int n,array[] = {10, 12, 32, 22, 23, 25, 30}; 48 | n = sizeof(array)/sizeof(array[0]); // get no of elements in the array 49 | max_inc(array,n); 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /minimum-cost-path.C: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | //naive 3 variable comparison 5 | int min(int a,int b, int c) 6 | { 7 | if(a 0) && (n1 < n) && (m1 > 0) && (m1 < m)) 25 | { 26 | //setting up the base cases in the minarray 27 | minarr[0][0] = a[0][0]; 28 | 29 | for(i=1;i