0% found this document useful (1 vote)
2K views3,020 pages

Dynamic Programming Problems Guide

The document is a table of contents that lists 38 topics related to dynamic programming. Each topic is numbered and includes the name of the dynamic programming problem addressed and the page number of its source material. The topics cover a range of classic dynamic programming problems from longest common subsequence to knapsack problems to matrix chain multiplication.

Uploaded by

Tarun Dhamor
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (1 vote)
2K views3,020 pages

Dynamic Programming Problems Guide

The document is a table of contents that lists 38 topics related to dynamic programming. Each topic is numbered and includes the name of the dynamic programming problem addressed and the page number of its source material. The topics cover a range of classic dynamic programming problems from longest common subsequence to knapsack problems to matrix chain multiplication.

Uploaded by

Tarun Dhamor
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 3020

Contents

1 DP-01 | Overlapping Subproblems Property in Dynamic Programming 27


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

2 DP-02 | Optimal Substructure Property in Dynamic Programming 36


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

3 DP-03 | Longest Increasing Subsequence 38


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

4 DP-04 | Longest Common Subsequence 47


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

5 DP-05 | Edit Distance 59


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73

6 DP-06 | Min Cost Path 74


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86

7 DP-07 | Coin Change 87


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100

8 DP-08 | Matrix Chain Multiplication 101


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112

9 DP-09 | Binomial Coefficient 113


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126

10 DP-10 | 0-1 Knapsack Problem 127


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138

11 DP-11 | Egg Dropping Puzzle 139


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

12 DP-12 | Longest Palindromic Subsequence 150


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159

13 DP-13 | Cutting a Rod 160


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169

1
Contents

14 DP-14 | Maximum Sum Increasing Subsequence 170


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176

15 DP-15 | Longest Bitonic Subsequence 177


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183

16 DP-16 | Floyd Warshall Algorithm 184


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194

17 DP-17 | Palindrome Partitioning 195


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207

18 DP-18 | Partition problem 208


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219

19 DP-19 | Word Wrap Problem 220


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229

20 DP-20 | Maximum Length Chain of Pairs 230


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235

21 DP-21 | Variations of LIS 236


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237

22 DP-22 | Box Stacking Problem 238


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245

23 DP-23 | Bellman–Ford Algorithm 246


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257

24 DP-24 | Optimal Binary Search Tree 258


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269

25 DP-25 | Subset Sum Problem 270


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281

26 DP-26 | Largest Independent Set Problem 282


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288

27 DP-27 | Maximum sum rectangle in a 2D matrix 289


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295

28 DP-28 | Minimum insertions to form a palindrome 296


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305

29 DP-29 | Longest Common Substring 306


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312

30 DP-30 | Dice Throw 313


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319

2
Contents

31 DP-31 | Optimal Strategy for a Game 320


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324

32 DP-32 | Word Break Problem 325


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332

33 DP-33 | Find if a string is interleaved of two other strings 333


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336

34 DP-34 | Assembly Line Scheduling 337


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345

35 DP-35 | Longest Arithmetic Progression 346


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352

36 DP-36 | Maximum Product Cutting 353


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362

37 DP-37 | Boolean Parenthesization Problem 363


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366

38 A Space Optimized DP solution for 0-1 Knapsack Problem 367


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 370

39 A Space Optimized Solution of LCS 371


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377

40 All ways to add parenthesis for evaluation 378


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380

41 Alternate Fibonacci Numbers 381


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381

42 Balanced expressions such that given positions have opening brackets 384
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387

43 Balanced expressions such that given positions have opening brackets |


Set 2 388
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392

44 Bell Numbers (Number of ways to Partition a Set) 393


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399

45 Bitmasking and Dynamic Programming | Set 1 (Count ways to assign


unique cap to every person) 400
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409

46 Bitmasking and Dynamic Programming | Set-2 (TSP) 410


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417

47 Check for possible path in 2D matrix 418

3
Contents

Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 424

48 Check if all people can vote on two machines 425


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427

49 Check if any valid sequence is divisible by M 428


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433

50 Check if array sum can be made K by three operations on it 434


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436

51 Check if it is possible to transform one string to another 437


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 441

52 Check if possible to cross the matrix with given power 442


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449

53 Check whether row or column swaps produce maximum size binary


sub-matrix with all 1s 450
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454

54 Choice of Area 455


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 459

55 Choose maximum weight with given weight and value ratio 460
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 464

56 Clustering/Partitioning an array such that sum of square differences is


minimum 465
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 474

57 Coin game winner where every player has three choices 475
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 481

58 Collect maximum coins before hitting a dead end 482


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 487

59 Collect maximum points in a grid using two traversals 488


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 491

60 Compute nCr % p | Set 1 (Introduction and Dynamic Programming


Solution) 492
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498

61 Compute sum of digits in all numbers from 1 to n 499


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 512

62 Construction of Longest Increasing Subsequence using Dynamic Pro-


gramming 513
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 515

4
Contents

63 Convert to Strictly increasing array with minimum changes 516


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 521

64 Count numbers from 1 to n that have 4 as a digit 522


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 522

65 Count All Palindrome Sub-Strings in a String | Set 1 531


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535

66 Count All Palindromic Subsequence in a given String 536


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 541

67 Count Balanced Binary Trees of Height h 542


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 545

68 Count Derangements (Permutation such that no element appears in its


original position) 546
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 555

69 Count Distinct Subsequences 556


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 560

70 Count Possible Decodings of a given Digit Sequence 561


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 567

71 Count all increasing subsequences 568


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 575

72 Count all possible paths from top left to bottom right of a mXn matrix 576
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 582

73 Count all possible walks from a source to a destination with exactly k


edges 583
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 593

74 Count all subsequences having product less than K 594


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 597

75 Count all triplets whose sum is equal to a perfect cube 598


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 602

76 Count binary strings with k times appearing adjacent two set bits 603
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 605

77 Count digit groupings of a number with given constraints 606


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 613

78 Count distinct occurrences as a subsequence 614


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 619

5
Contents

79 Count even length binary sequences with same sum of first and second
half bits 620
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 633

80 Count number of binary strings without consecutive 1’s 634


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 638

81 Count number of increasing subsequences of size k 639


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 643

82 Count number of paths with at-most k turns 644


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 647

83 Count number of subsets having a particular XOR value 648


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 651

84 Count number of ways to cover a distance 652


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 660

85 Count number of ways to fill a “n x 4” grid using “1 x 4” tiles 661


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 668

86 Count number of ways to jump to reach end 669


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 674

87 Count number of ways to partition a set into k subsets 675


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 680

88 Count number of ways to reach a given score in a game 681


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 688

89 Count number of ways to reach destination in a Maze 689


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 698

90 Count of AP (Arithmetic Progression) Subsequences in an array 699


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 706

91 Count of Palindromic substrings in an Index range 707


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 713

92 Count of arrays having consecutive element with different values 714


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 719

93 Count of arrays in which all adjacent elements are such that one of them
divide the another 720
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 723

94 Count of different ways to express N as the sum of 1, 3 and 4 724


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 729

95 Count of n digit numbers whose sum of digits equals to given sum 730

6
Contents

Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 742

96 Count of possible hexagonal walks 743


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 749

97 Count of strings that can be formed using a, b and c under given


constraints 750
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 758

98 Count of strings where adjacent characters are of difference one 759


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 762

99 Count of subarrays whose maximum element is greater than k 763


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 769

100 Count possible ways to construct buildings 770


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 777

101 Count the number of ways to tile the floor of size n x m using 1 x m
size tiles 778
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 784

102 Count total number of N digit numbers such that the difference be-
tween sum of even and odd digits is 1 785
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 787

103 Count ways to build street under given constraints 788


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 792

104 Count ways to divide circle using N non-intersecting chords 793


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 797

105 Count ways to increase LCS length of two strings by one 798
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 801

106 Count ways to reach the nth stair using step 1, 2 or 3 802
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 810

107 Count ways to reach the n’th stair 811


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 823

108 Counting numbers of n digits that are monotone 824


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 830

109 Counting pairs when a person can form pair with at most one 831
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 838

110 Counts paths from a point to reach Origin 839


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 847

111 Delannoy Number 848

7
Contents

Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 856

112 Different ways to sum n using numbers greater than or equal to m 857
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 861

113 Digit DP | Introduction 862


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 867

114 Dynamic Programming on Trees | Set 2 868


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 875

115 Dynamic Programming on Trees | Set-1 876


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 880

116 Dynamic Programming vs Divide-and-Conquer 881


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 891

117 Dynamic Programming | Building Bridges 892


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 895

118 Dynamic Programming | High-effort vs. Low-effort Tasks Problem 896


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 899

119 Dynamic Programming | Wildcard Pattern Matching | Linear Time


and Constant Space 900
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 906

120 Edit Distance | DP using Memoization 907


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 915

121 Edit distance and LCS (Longest Common Subsequence) 916


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 917

122 Efficient program to print all prime factors of a given number 918
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 924

123 Entringer Number 925


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 933

124 Eulerian Number 934


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 942

125 Find Jobs involved in Weighted Job Scheduling 943


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 946

126 Find Maximum dot product of two arrays with insertion of 0’s 947
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 950

127 Find all combinations of k-bit numbers with n bits set where 1 <= n
<= k in sorted order 951
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 953

8
Contents

128 Find all distinct palindromic sub-strings of a given string 954


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 960

129 Find all distinct subset (or subsequence) sums of an array 961
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 968

130 Find all distinct subset (or subsequence) sums of an array | Set-2 969
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 971

131 Find if string is K-Palindrome or not | Set 1 972


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 978

132 Find if string is K-Palindrome or not | Set 2 979


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 983

133 Find length of longest subsequence of one string which is substring of


another string 984
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 990

134 Find length of the longest consecutive path from a given starting char-
acter 991
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 999

135 Find longest bitonic sequence such that increasing and decreasing parts
are from two different arrays 1000
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1002

136 Find maximum length Snake sequence 1003


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1009

137 Find maximum possible stolen value from houses 1010


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1021

138 Find maximum sum array of length less than or equal to m 1022
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1023

139 Find minimum adjustment cost of an array 1024


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1031

140 Find minimum number of coins that make a given value 1032
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1043

141 Find minimum possible size of array with given rules for removing
elements 1044
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1047

142 Find minimum sum such that one of every three consecutive elements
is taken 1048
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1054

9
Contents

143 Find n-th element from Stern’s Diatomic Series 1055


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1061

144 Find number of endless points 1062


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1070

145 Find number of solutions of a linear equation of n variables 1071


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1081

146 Find number of times a string occurs as a subsequence in given string1082


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1090

147 Find the Longest Increasing Subsequence in Circular manner 1091


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1098

148 Find the largest area rectangular sub-matrix whose sum is equal to k 1099
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1103

149 Find the longest path in a matrix with given constraints 1104
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1108

150 Find the minimum cost to reach destination using a train 1109
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1119

151 Find the probability of reaching all points after N moves from point N1120
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1122

152 Finding the maximum square sub-matrix with all equal elements 1123
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1132

153 Friends Pairing Problem 1133


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1138

154 G-Fact 21 | Collatz Sequence 1139


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1139

155 Generate all unique partitions of an integer 1140


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1149

156 Given a large number, check if a subsequence of digits is divisible by 81150


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1161

157 Gold Mine Problem 1162


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1168

158 Golomb sequence 1169


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1177

159 Highway Billboard Problem 1178


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1182

10
Contents

160 Hosoya’s Triangle 1183


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1193

161 How to print maximum number of A’s using given four keys 1194
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1203

162 How to solve a Dynamic Programming Problem ? 1204


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1207

163 Jacobsthal and Jacobsthal-Lucas numbers 1208


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1219

164 K maximum sums of non-overlapping contiguous sub-arrays 1220


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1229

165 K maximum sums of overlapping contiguous sub-arrays 1230


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1236

166 LCS (Longest Common Subsequence) of three strings 1237


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1244

167 LCS formed by consecutive segments of at least length K 1245


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1250

168 Largest Sum Contiguous Subarray 1251


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1264

169 Largest area rectangular sub-matrix with equal number of 1’s and 0’s 1265
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1269

170 Largest divisible pairs subset 1270


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1275

171 Largest rectangular sub-matrix having sum divisible by k 1276


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1280

172 Largest rectangular sub-matrix whose sum is 0 1281


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1285

173 Largest sum Zigzag sequence in a matrix 1286


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1294

174 Largest sum subarray with at-least k numbers 1295


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1301

175 Length of Longest Balanced Subsequence 1302


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1306

176 Length of longest common subsequence containing vowels 1307


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1307

11
Contents

177 Length of the longest valid substring 1311


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1316

178 Level Ancestor Problem 1317


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1324

179 Lobb Number 1325


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1331

180 Longest Common Substring (Space optimized DP solution) 1332


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1339

181 Longest Common Increasing Subsequence (LCS + LIS) 1340


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1355

182 Longest Common Subsequence with at most k changes allowed 1356


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1358

183 Longest Common Subsequence | DP using Memoization 1359


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1363

184 Longest Decreasing Subsequence 1364


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1369

185 Longest Even Length Substring such that Sum of First and Second
Half is same 1370
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1382

186 Longest Geometric Progression 1383


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1386

187 Longest Increasing Odd Even Subsequence 1387


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1392

188 Longest Increasing Path in Matrix 1393


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1396

189 Longest Increasing Subsequence Size (N log N) 1397


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1408

190 Longest Increasing consecutive subsequence 1409


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1411

191 Longest Palindromic Substring | Set 1 1412


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1418

192 Longest Repeated Subsequence 1419


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1425

193 Longest Repeating Subsequence 1426


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1431

12
Contents

194 Longest Zig-Zag Subsequence 1432


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1439

195 Longest alternating (positive and negative) subarray starting at every


index 1440
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1445

196 Longest alternating sub-array starting from every index in a Binary


Array 1446
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1453

197 Longest alternating subsequence 1454


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1461

198 Longest palindrome subsequence with O(n) space 1462


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1470

199 Longest repeating and non-overlapping substring 1471


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1474

200 Longest subarray having maximum sum 1475


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1477

201 Longest subsequence such that difference between adjacents is one 1478
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1485

202 Lucas Numbers 1486


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1494

203 Matrix Exponentiation 1495


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1503

204 Maximize arr[j] – arr[i] + arr[l] – arr[k], such that i < j < k < l 1504
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1506

205 Maximize array elements upto given number 1507


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1524

206 Maximize the binary matrix by filpping submatrix once 1525


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1527

207 Maximize the sum of selected numbers from an array to make it empty 1528
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1530

208 Maximum Product Subarray | Added negative product case 1531


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1534

209 Maximum Subarray Sum Excluding Certain Elements 1535


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1545

210 Maximum Subarray Sum using Divide and Conquer algorithm 1546

13
Contents

Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1553

211 Maximum Sum Decreasing Subsequence 1554


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1559

212 Maximum absolute difference between sum of two contiguous sub-arrays 1560
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1571

213 Maximum and Minimum Values of an Algebraic Expression 1572


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1582

214 Maximum average sum partition of an array 1583


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1586

215 Maximum decimal value path in a binary matrix 1587


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1593

216 Maximum difference of zeros and ones in binary string 1594


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1599

217 Maximum difference of zeros and ones in binary string | Set 2 (O(n)
time) 1600
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1605

218 Maximum games played by winner 1606


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1610

219 Maximum length of segments of 0’s and 1’s 1611


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1613

220 Maximum length subsequence with difference between adjacent ele-


ments as either 0 or 1 1614
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1620

221 Maximum number of segments of lengths a, b and c 1621


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1627

222 Maximum number of trailing zeros in the product of the subsets of


size k 1628
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1632

223 Maximum path sum for each position with jumps under divisibility
condition 1633
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1639

224 Maximum path sum in a triangle. 1640


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1646

225 Maximum path sum that starting with any cell of 0-th row and ending
with any cell of (N-1)-th row 1647

14
Contents

Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1652

226 Maximum points collected by two persons allowed to meet once 1653
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1656

227 Maximum points from top left of matrix to bottom right and return
back 1657
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1662

228 Maximum product of an increasing subsequence 1663


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1667

229 Maximum profit by buying and selling a share at most k times 1668
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1681

230 Maximum profit by buying and selling a share at most twice 1682
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1691

231 Maximum profit from sale of wines 1692


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1699

232 Maximum size square sub-matrix with all 1s 1700


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1706

233 Maximum size subset with given sum 1707


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1710

234 Maximum sub-matrix area having count of 1’s one more than count of
0’s 1711
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1715

235 Maximum subarray sum in O(n) using prefix sum 1716


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1723

236 Maximum subarray sum in an array created after repeated concatenation 1724
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1730

237 Maximum subsequence sum such that no three are consecutive 1731
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1738

238 Maximum sum Bi-tonic Sub-sequence 1739


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1746

239 Maximum sum alternating subsequence 1747


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1756

240 Maximum sum bitonic subarray 1757


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1768

241 Maximum sum in a 2 x n grid such that no two elements are adjacent1769
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1772

15
Contents

242 Maximum sum in circular array such that no two elements are adjacent 1773
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1776

243 Maximum sum increasing subsequence from a prefix and a given ele-
ment after prefix is must 1777
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1782

244 Maximum sum of a path in a Right Number Triangle 1783


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1791

245 Maximum sum of pairs with specific difference 1792


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1802

246 Maximum sum path in a matrix from top to bottom 1803


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1810

247 Maximum sum subarray removing at most one element 1811


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1819

248 Maximum sum subsequence with at-least k distant elements 1820


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1825

249 Maximum sum such that no two elements are adjacent 1826
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1831

250 Maximum value with the choice of either dividing or considering as it is 1832
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1836

251 Maximum weight path ending at any element of last row in a matrix 1837
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1843

252 Maximum weight transformation of a given string 1844


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1848

253 Memoization (1D, 2D and 3D) 1849


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1861

254 Minimal moves to form a string by adding characters or appending


string itself 1862
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1863

255 Minimum Cost Path with Left, Right, Bottom and Up moves allowed 1864
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1867

256 Minimum Cost Polygon Triangulation 1868


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1873

257 Minimum Cost To Make Two Strings Identical 1874


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1879

258 Minimum Initial Points to Reach Destination 1880

16
Contents

Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1885

259 Minimum Sum Path In 3-D Array 1886


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1894

260 Minimum Sum Path in a Triangle 1895


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1901

261 Minimum and Maximum values of an expression with * and + 1902


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1905

262 Minimum cells required to reach destination with jumps equal to cell
values 1906
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1914

263 Minimum cost to fill given weight in a bag 1915


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1921

264 Minimum cost to make Longest Common Subsequence of length k 1922


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1924

265 Minimum cost to make two strings identical by deleting the digits 1925
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1930

266 Minimum cost to reach the top of the floor by climbing stairs 1931
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1941

267 Minimum cost to sort strings using reversal operations of different costs 1942
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1946

268 Minimum insertions to sort an array 1947


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1952

269 Minimum jumps to reach last building in a matrix 1953


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1961

270 Minimum number of deletions and insertions to transform one string


into another 1962
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1967

271 Minimum number of deletions to make a sorted sequence 1968


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1976

272 Minimum number of deletions to make a string palindrome 1977


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1984

273 Minimum number of deletions to make a string palindrome | Set 2 1985


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1988

274 Minimum number of elements which are not part of Increasing or


decreasing subsequence in array 1989

17
Contents

Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1992

275 Minimum number of jumps to reach end 1993


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2009

276 Minimum number of jumps to reach end | Set 2 (O(n) solution) 2010
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2017

277 Minimum number of single digit primes required whose sum is equal
to N 2018
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2026

278 Minimum number of squares whose sum equals to given number n 2027
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2038

279 Minimum removals from array to make max – min <= K 2039
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2048

280 Minimum splits in a binary string such that every substring is a power
of 4 or 6. 2049
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2054

281 Minimum steps to delete a string after repeated deletion of palindrome


substrings 2055
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2061

282 Minimum steps to minimize n as per given condition 2062


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2072

283 Minimum steps to reach a destination 2073


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2079

284 Minimum steps to reach target by a Knight | Set 2 2080


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2084

285 Minimum sum of multiplications of n numbers 2085


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2092

286 Minimum sum submatrix in a given 2D array 2093


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2096

287 Minimum sum subsequence such that at least one of every four con-
secutive elements is picked 2097
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2104

288 Minimum time to finish tasks without skipping two consecutive 2105
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2114

289 Minimum time to write characters using insert, delete and copy operation 2115
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2117

18
Contents

290 Mobile Numeric Keypad Problem 2118


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2126

291 Modify array to maximize sum of adjacent differences 2127


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2132

292 Moser-de Bruijn Sequence 2133


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2144

293 Multistage Graph (Shortest Path) 2145


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2148

294 Newman-Conway Sequence 2149


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2156

295 Newman–Shanks–Williams prime 2157


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2164

296 Non-crossing lines to connect points in a circle 2165


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2172

297 Non-decreasing subsequence of size k with minimum sum 2173


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2179

298 Number of Co-prime pairs obtained from the sum of digits of elements
in the given range 2180
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2186

299 Number of NGEs to the right 2187


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2190

300 Number of Unique BST with a given key | Dynamic Programming 2191
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2196

301 Number of arrays of size N whose elements are positive integers and
sum is K 2197
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2202

302 Number of circular tours that visit all petrol pumps 2203
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2206

303 Number of decimal numbers of length k, that are strict monotone 2207
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2212

304 Number of different cyclic paths of length N in a tetrahedron 2213


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2216

305 Number of n digit stepping numbers 2217


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2224

306 Number of n-digits non-decreasing integers 2225

19
Contents

Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2231

307 Number of non-negative integral solutions of a + b + c = n 2232


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2239

308 Number of ordered pairs such that (Ai & Aj) = 0 2240
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2247

309 Number of palindromic paths in a matrix 2248


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2251

310 Number of palindromic subsequences of length k where k <= 3 2252


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2260

311 Number of paths from source to destination in a directed acyclic graph 2261
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2264

312 Number of paths with exactly k coins 2265


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2270

313 Number of permutation with K inversions 2271


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2276

314 Number of subsequences in a string divisible by n 2277


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2280

315 Number of subsequences of the form a^i b^j c^k 2281


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2289

316 Number of subsets with sum divisible by m 2290


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2292

317 Number of substrings divisible by 8 but not by 3 2293


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2300

318 Number of ways a convex polygon of n+2 sides can split into triangles
by connecting vertices 2301
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2306

319 Number of ways to arrange N items under given constraints 2307


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2309

320 Number of ways to form a heap with n distinct integers 2310


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2314

321 Number of ways to form an array with distinct adjacent elements 2315
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2324

322 Number of ways to insert a character to increase the LCS by one 2325
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2328

20
Contents

323 Number of ways to reach Nth floor by taking at-most K leaps 2329
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2336

324 Number of ways to represent a number as sum of k fibonacci numbers2337


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2339

325 Padovan Sequence 2340


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2345

326 Painting Fence Algorithm 2346


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2350

327 Paper Cut into Minimum Number of Squares | Set 2 2351


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2358

328 Partition a set into two subsets such that the difference of subset sums
is minimum 2359
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2367

329 Partitioning into two contiguous element subarrays with equal sums 2368
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2371

330 Path with maximum average value 2372


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2377

331 Perfect Sum Problem (Print all subsets with given sum) 2378
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2383

332 Permutation Coefficient 2384


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2398

333 Prefix Sum of Matrix (Or 2D Array) 2399


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2406

334 Print Fibonacci Series in reverse order 2407


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2412

335 Print Fibonacci sequence using 2 variables 2413


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2420

336 Print Longest Palindromic Subsequence 2421


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2423

337 Print Maximum Length Chain of Pairs 2424


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2427

338 Print all distinct characters of a string in order (3 Methods) 2428


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2436

339 Print all longest common sub-sequences in lexicographical order 2437


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2440

21
Contents

340 Print all possible ways to convert one string into another string | Edit-
Distance 2441
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2449

341 Print equal sum sets of array (Partition Problem) | Set 2 2450
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2459

342 Print equal sum sets of array (Partition problem) | Set 1 2460
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2473

343 Print n terms of Newman-Conway Sequence 2474


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2478

344 Printing Items in 0/1 Knapsack 2479


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2484

345 Printing Longest Bitonic Subsequence 2485


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2489

346 Printing Longest Common Subsequence | Set 2 (Printing All) 2490


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2493

347 Printing Maximum Sum Increasing Subsequence 2494


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2497

348 Printing Shortest Common Supersequence 2498


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2502

349 Printing brackets in Matrix Chain Multiplication Problem 2503


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2507

350 Printing longest Increasing consecutive subsequence 2508


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2510

351 Probability of Knight to remain in the chessboard 2511


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2519

352 Probability of getting at least K heads in N tosses of Coins 2520


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2527

353 Probability of reaching a point with 2 or 3 steps at a time 2528


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2532

354 Program for Bridge and Torch problem 2533


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2537

355 Program for Fibonacci numbers 2538


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2560

356 Program for nth Catalan Number 2561


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2569

22
Contents

357 Program to find amount of water in a given glass 2570


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2579

358 Pyramid form (increasing then decreasing) consecutive array using


reduce operations 2580
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2583

359 Queries on number of Binary sub-matrices of Given size 2584


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2592

360 Queries to find distance between two nodes of a Binary tree 2593
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2595

361 Recursively break a number in 3 parts to get maximum sum 2596


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2602

362 Remove array end element to maximize the sum of product 2603
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2604

363 Remove minimum elements from either side such that 2*min becomes
more than max 2605
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2610

364 Rencontres Number (Counting partial derangements) 2611


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2624

365 Semiperfect Number 2625


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2627

366 Sequence Alignment problem 2628


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2639

367 Sequences of given length where every element is more than or equal
to twice of previous 2640
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2650

368 Shortest Common Supersequence 2651


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2664

369 Shortest Uncommon Subsequence 2665


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2669

370 Shortest path with exactly k edges in a directed and weighted graph 2670
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2676

371 Shortest possible combination of two strings 2677


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2687

372 Sieve of Eratosthenes 2688


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2695

23
Contents

373 Size of The Subarray With Maximum Sum 2696


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2701

374 Size of array after repeated deletion of LIS 2702


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2705

375 Smallest length string with repeated replacement of two distinct adjacent 2706
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2711

376 Smallest number with given sum of digits and sum of square of digits 2712
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2715

377 Smallest sum contiguous subarray 2716


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2722

378 Space and time efficient Binomial Coefficient 2723


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2727

379 Sub-tree with minimum color difference in a 2-coloured tree 2728


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2731

380 Subset Sum Problem in O(sum) space 2732


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2736

381 Subset with sum divisible by m 2737


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2745

382 Sudo Placement[1.5] | Wolfish 2746


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2750

383 Sum of all substrings of a string representing a number | Set 1 2751


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2757

384 Sum of all substrings of a string representing a number | Set 2 (Con-


stant Extra Space) 2758
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2763

385 Sum of average of all subsets 2764


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2772

386 Sum of elements of all partitions of number such that no element is


less than K 2773
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2778

387 Sum of product of consecutive Binomial Coefficients 2779


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2786

388 Sum of product of r and rth Binomial Coefficient (r * nCr) 2787


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2794

389 Sum of products of all combination taken (1 to n) at a time 2795

24
Contents

Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2804

390 Super Ugly Number (Number whose prime factors are in given set) 2805
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2808

391 Tabulation vs Memoizatation 2809


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2811

392 Temple Offerings 2812


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2820

393 Tetranacci Numbers 2821


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2826

394 The Two Water Jug Puzzle 2827


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2831

395 The painter’s partition problem 2832


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2845

396 The painter’s partition problem | Set 2 2846


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2855

397 Tile Stacking Problem 2856


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2858

398 Tiling Problem 2859


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2860

399 Tiling with Dominoes 2861


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2867

400 Total number of decreasing paths in a matrix 2868


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2875

401 Total number of non-decreasing numbers with n digits 2876


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2884

402 Total number of possible Binary Search Trees and Binary Trees with
n keys 2885
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2895

403 Travelling Salesman Problem | Set 1 (Naive and Dynamic Programming) 2896
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2897

404 Traversal of tree with k jumps allowed between nodes of same height 2898
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2903

405 Ugly Numbers 2904


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2918

25
Contents

406 Unbounded Knapsack (Repetition of items allowed) 2919


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2925

407 Unique paths in a Grid with Obstacles 2926


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2928

408 Value of continuous floor function : F(x) = F(floor(x/2)) + x 2929


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2933

409 Vertex Cover Problem | Set 2 (Dynamic Programming Solution for Tree) 2934
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2939

410 Water Jug Problem using Memoization 2940


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2942

411 Ways of transforming one string to other by removing 0 or more char-


acters 2943
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2944

412 Ways to arrange Balls such that adjacent balls are of different types 2945
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2958

413 Ways to sum to N using array elements with repetition allowed 2959
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2963

414 Ways to write n as sum of two or more positive integers 2964


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2968

415 Weighted Job Scheduling 2969


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2974

416 Weighted Job Scheduling in O(n Log n) time 2975


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2982

417 Weighted Job Scheduling | Set 2 (Using LIS) 2983


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2986

418 Weird Number 2987


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2994

419 WildCard pattern matching having three symbols ( * , + , ? ) 2995


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2999

420 Wildcard Pattern Matching 3000


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3007

421 Word Wrap problem ( Space optimized solution ) 3008


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3014

422 n-th number with digits in {0, 1, 2, 3, 4, 5} 3015


Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3020

26
Chapter 1

DP-01 | Overlapping
Subproblems Property in
Dynamic Programming

Overlapping Subproblems Property in Dynamic Programming | DP-1 - GeeksforGeeks


Dynamic Programming is an algorithmic paradigm that solves a given complex problem by
breaking it into subproblems and stores the results of subproblems to avoid computing the
same results again. Following are the two main properties of a problem that suggests that
the given problem can be solved using Dynamic programming.
In this post, we will discuss first property (Overlapping Subproblems) in detail. The second
property of Dynamic programming is discussed in next post i.e. Set 2.
1) Overlapping Subproblems
2) Optimal Substructure
1) Overlapping Subproblems:
Like Divide and Conquer, Dynamic Programming combines solutions to sub-problems. Dy-
namic Programming is mainly used when solutions of same subproblems are needed again
and again. In dynamic programming, computed solutions to subproblems are stored in a
table so that these don’t have to be recomputed. So Dynamic Programming is not useful
when there are no common (overlapping) subproblems because there is no point storing the
solutions if they are not needed again. For example, Binary Search doesn’t have common
subproblems. If we take an example of following recursive program for Fibonacci Numbers,
there are many subproblems which are solved again and again.

/* simple recursive program for Fibonacci numbers */


int fib(int n)
{
   if ( n <= 1 )
      return n;
   return fib(n-1) + fib(n-2);

27
Chapter 1. DP-01 | Overlapping Subproblems Property in Dynamic Programming

Recursion tree for execution of fib(5)

fib(5)
/ \
fib(4) fib(3)
/ \ / \
fib(3) fib(2) fib(2) fib(1)
/ \ / \ / \
fib(2) fib(1) fib(1) fib(0) fib(1) fib(0)
/ \
fib(1) fib(0)

We can see that the function fib(3) is being called 2 times. If we would have stored the
value of fib(3), then instead of computing it again, we could have reused the old stored value.
There are following two different ways to store the values so that these values can be reused:
a) Memoization (Top Down)
b) Tabulation (Bottom Up)
a) Memoization (Top Down): The memoized program for a problem is similar to the
recursive version with a small modification that it looks into a lookup table before computing
solutions. We initialize a lookup array with all initial values as NIL. Whenever we need the
solution to a subproblem, we first look into the lookup table. If the precomputed value is
there then we return that value, otherwise, we calculate the value and put the result in the
lookup table so that it can be reused later.
Following is the memoized version for nth Fibonacci Number.
C/C++

/* C/C++ program for Memoized version for nth Fibonacci number */


#include<stdio.h>
#define NIL -1
#define MAX 100
  
int lookup[MAX];
  
/* Function to initialize NIL values in lookup table */
void _initialize()
{
  int i;
  for (i = 0; i < MAX; i++)
    lookup[i] = NIL;
}
  
/* function for nth Fibonacci number */
int fib(int n)

28
Chapter 1. DP-01 | Overlapping Subproblems Property in Dynamic Programming

{
   if (lookup[n] == NIL)
   {
      if (n <= 1)
         lookup[n] = n;
      else
         lookup[n] = fib(n-1) + fib(n-2);
   }
  
   return lookup[n];
}
  
int main ()
{
  int n = 40;
  _initialize();
  printf("Fibonacci number is %d ", fib(n));
  return 0;
}

Java

/* Java program for Memoized version */


public class Fibonacci
{
  final int MAX = 100;
  final int NIL = -1;
  
  int lookup[] = new int[MAX];
  
  /* Function to initialize NIL values in lookup table */
  void _initialize()
  {
    for (int i = 0; i < MAX; i++)
        lookup[i] = NIL;
  }
  
  /* function for nth Fibonacci number */
  int fib(int n)
  {
    if (lookup[n] == NIL)
    {
      if (n <= 1)
          lookup[n] = n;
      else
          lookup[n] = fib(n-1) + fib(n-2);
    }
    return lookup[n];

29
Chapter 1. DP-01 | Overlapping Subproblems Property in Dynamic Programming

  }
  
  public static void main(String[] args)
  {
    Fibonacci f = new Fibonacci();
    int n = 40;
    f._initialize();
    System.out.println("Fibonacci number is" + " " + f.fib(n));
  }
  
}
// This Code is Contributed by Saket Kumar

Python

# Python program for Memoized version of nth Fibonacci number


  
# Function to calculate nth Fibonacci number
def fib(n, lookup):
  
    # Base case
    if n == 0 or n == 1 :
        lookup[n] = n
  
    # If the value is not calculated previously then calculate it
    if lookup[n] is None:
        lookup[n] = fib(n-1 , lookup)  + fib(n-2 , lookup) 
  
    # return the value corresponding to that value of n
    return lookup[n]
# end of function
  
# Driver program to test the above function
def main():
    n = 34 
    # Declaration of lookup table
    # Handles till n = 100 
    lookup = [None]*(101)
    print "Fibonacci Number is ", fib(n, lookup)
  
if __name__=="__main__":
    main()
  
# This code is contributed by Nikhil Kumar Singh(nickzuck_007)

C#

// C# program for Memoized versionof nth Fibonacci number 

30
Chapter 1. DP-01 | Overlapping Subproblems Property in Dynamic Programming

using System;
  
class GFG
{
      
    static int MAX = 100;
    static int NIL = -1;
    static int []lookup = new int[MAX];
      
    /* Function to initialize NIL 
    values in lookup table */
    static void initialize()
    {
        for (int i = 0; i < MAX; i++)
            lookup[i] = NIL;
    }
      
    /* function for nth Fibonacci number */
    static int fib(int n)
    {
        if (lookup[n] == NIL)
        {
        if (n <= 1)
            lookup[n] = n;
        else
            lookup[n] = fib(n - 1) + fib(n - 2);
        }
        return lookup[n];
    }
      
    // Driver code
    public static void Main()
    {
      
        int n = 40;
        initialize();
        Console.Write("Fibonacci number is" + " " + fib(n));
    }
}
  
// This Code is Contributed by Sam007

b) Tabulation (Bottom Up): The tabulated program for a given problem builds a table
in bottom up fashion and returns the last entry from table. For example, for the same
Fibonacci number, we first calculate fib(0) then fib(1) then fib(2) then fib(3) and so on. So
literally, we are building the solutions of subproblems bottom-up.
Following is the tabulated version for nth Fibonacci Number.

31
Chapter 1. DP-01 | Overlapping Subproblems Property in Dynamic Programming

C/C++

/* C program for Tabulated version */


#include<stdio.h>
int fib(int n)
{
  int f[n+1];
  int i;
  f[0] = 0;   f[1] = 1; 
  for (i = 2; i <= n; i++)
      f[i] = f[i-1] + f[i-2];
  
  return f[n];
}
   
int main ()
{
  int n = 9;
  printf("Fibonacci number is %d ", fib(n));
  return 0;
}

Java

/* Java program for Tabulated version */


public class Fibonacci
{
  int fib(int n)
  {
    int f[] = new int[n+1];
    f[0] = 0;
    f[1] = 1;
    for (int i = 2; i <= n; i++)
          f[i] = f[i-1] + f[i-2];
    return f[n];
  }
  
  public static void main(String[] args)
  {
    Fibonacci f = new Fibonacci();
    int n = 9;
    System.out.println("Fibonacci number is" + " " + f.fib(n));
  }
  
}
// This Code is Contributed by Saket Kumar

Python

32
Chapter 1. DP-01 | Overlapping Subproblems Property in Dynamic Programming

# Python program Tabulated (bottom up) version


def fib(n):
  
    # array declaration
    f = [0]*(n+1)
  
    # base case assignment
    f[1] = 1
  
    # calculating the fibonacci and storing the values
    for i in xrange(2 , n+1):
        f[i] = f[i-1] + f[i-2]
    return f[n]
  
# Driver program to test the above function
def main():
    n = 9
    print "Fibonacci number is " , fib(n)
  
if __name__=="__main__":
    main()
  
# This code is contributed by Nikhil Kumar Singh (nickzuck_007)

C#

// C# program for Tabulated version


using System;
  
class GFG
{
    static int fib(int n)
    {
        int []f = new int[n + 1];
        f[0] = 0;
        f[1] = 1;
        for (int i = 2; i <= n; i++)
            f[i] = f[i - 1] + f[i - 2];
        return f[n];
    }
      
    public static void Main()
    {
          
        int n = 9;
        Console.Write("Fibonacci number is" + " " + fib(n));
    }
}

33
Chapter 1. DP-01 | Overlapping Subproblems Property in Dynamic Programming

  
// This Code is Contributed by Sam007

PHP

<?php
// PHP program for Tabulated version
  
function fib($n)
{
    $f[$n + 1]=0;
    $i;
    $f[0] = 0;
    $f[1] = 1; 
    for ($i = 2; $i <= $n; $i++)
        $f[$i] = $f[$i - 1] + 
                 $f[$i - 2];
      
    return $f[$n];
}
  
// Driver Code
$n = 9;
echo("Fibonacci number is "); 
echo(fib($n));
  
// This code is contributed by nitin mittal.
?>

Output:

Fibonacci number is 34

Both Tabulated and Memoized store the solutions of subproblems. In Memoized version,
table is filled on demand while in Tabulated version, starting from the first entry, all entries
are filled one by one. Unlike the Tabulated version, all entries of the lookup table are not
necessarily filled in Memoized version. For example, Memoized solution of the LCS problem
doesn’t necessarily fill all entries.
To see the optimization achieved by Memoized and Tabulated solutions over the basic Re-
cursive solution, see the time taken by following runs for calculating 40th Fibonacci number:
Recursive solution
Memoized solution
Tabulated solution
Time taken by Recursion method is much more than the two Dynamic Programming tech-
niques mentioned above – Memoization and Tabulation!

34
Chapter 1. DP-01 | Overlapping Subproblems Property in Dynamic Programming

Also, see method 2 of Ugly Number post for one more simple example where we have
overlapping subproblems and we store the results of subproblems.
We will be covering Optimal Substructure Property and some more example problems in
future posts on Dynamic Programming.
Try following questions as an exercise of this post.
1) Write a Memoized solution for LCS problem. Note that the Tabular solution is given in
the CLRS book.
2) How would you choose between Memoization and Tabulation?
References:
http://www.youtube.com/watch?v=V5hZoJ6uK-s
Improved By : nitin mittal

Source

https://www.geeksforgeeks.org/overlapping-subproblems-property-in-dynamic-programming-dp-1/

35
Chapter 2

DP-02 | Optimal Substructure


Property in Dynamic
Programming

Optimal Substructure Property in Dynamic Programming | DP-2 - GeeksforGeeks


As we discussed in Set 1, following are the two main properties of a problem that suggest
that the given problem can be solved using Dynamic programming:
1) Overlapping Subproblems
2) Optimal Substructure
We have already discussed Overlapping Subproblem property in the Set 1. Let us discuss
Optimal Substructure property here.
2) Optimal Substructure: A given problems has Optimal Substructure Property if op-
timal solution of the given problem can be obtained by using optimal solutions of its sub-
problems.
For example, the Shortest Path problem has following optimal substructure property:
If a node x lies in the shortest path from a source node u to destination node v then the
shortest path from u to v is combination of shortest path from u to x and shortest path
from x to v. The standard All Pair Shortest Path algorithms like Floyd–Warshall and
Bellman–Fordare typical examples of Dynamic Programming.
On the other hand, the Longest Path problem doesn’t have the Optimal Substructure prop-
erty. Here by Longest Path we mean longest simple path (path without cycle) between two
nodes. Consider the following unweighted graph given in the CLRS book. There are two
longest paths from q to t: q→r→t and q→s→t. Unlike shortest paths, these longest paths
do not have the optimal substructure property. For example, the longest path q→r→t is
not a combination of longest path from q to r and longest path from r to t, because the
longest path from q to r is q→s→t→r and the longest path from r to t is r→q→s→t.

36
Chapter 2. DP-02 | Optimal Substructure Property in Dynamic Programming

We will be covering some example problems in future posts on Dynamic Programming.


References:
http://en.wikipedia.org/wiki/Optimal_substructure
CLRS book
Improved By : ASAJ RAWAT

Source

https://www.geeksforgeeks.org/optimal-substructure-property-in-dynamic-programming-dp-2/

37
Chapter 3

DP-03 | Longest Increasing


Subsequence

Longest Increasing Subsequence | DP-3 - GeeksforGeeks


We have discussed Overlapping Subproblems and Optimal Substructure properties.
Let us discuss Longest Increasing Subsequence (LIS) problem as an example problem that
can be solved using Dynamic Programming.
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. For example, the length of LIS for {10, 22, 9, 33, 21, 50, 41, 60, 80} is 6
and LIS is {10, 22, 33, 50, 60, 80}.

More Examples:

Input : arr[] = {3, 10, 2, 1, 20}


Output : Length of LIS = 3
The longest increasing subsequence is 3, 10, 20

Input : arr[] = {3, 2}


Output : Length of LIS = 1
The longest increasing subsequences are {3} and {2}

Input : arr[] = {50, 3, 10, 7, 40, 80}


Output : Length of LIS = 4
The longest increasing subsequence is {3, 7, 40, 80}

38
Chapter 3. DP-03 | Longest Increasing Subsequence

Optimal Substructure:
Let arr[0..n-1] be the input array and L(i) be the length of the LIS ending at index i such
that arr[i] is the last element of the LIS.
Then, L(i) can be recursively written as:
L(i) = 1 + max( L(j) ) where 0 < j < i and arr[j] < arr[i]; or
L(i) = 1, if no such j exists.
To find the LIS for a given array, we need to return max(L(i)) where 0 < i < n.
Thus, we see the LIS problem satisfies the optimal substructure property as the main prob-
lem can be solved using solutions to subproblems.
Following is a simple recursive implementation of the LIS problem. It follows the recursive
structure discussed above.
C/C++

/* A Naive C/C++ recursive implementation of LIS problem */


#include<stdio.h>
#include<stdlib.h>
  
/* To make use of recursive calls, this function must return
   two things:
   1) Length of LIS ending with element arr[n-1]. We use
      max_ending_here for this purpose
   2) Overall maximum as the LIS may end with an element
      before arr[n-1] max_ref is used this purpose.
   The value of LIS of full array of size n is stored in
   *max_ref which is our final result */
int _lis( int arr[], int n, int *max_ref)
{
    /* Base case */
    if (n == 1)
        return 1;
  
    // 'max_ending_here' is length of LIS ending with arr[n-1]
    int res, max_ending_here = 1; 
  
    /* Recursively get all LIS ending with arr[0], arr[1] ...
       arr[n-2]. If   arr[i-1] is smaller than arr[n-1], and
       max ending with arr[n-1] needs to be updated, then
       update it */
    for (int i = 1; i < n; i++)
    {
        res = _lis(arr, i, max_ref);
        if (arr[i-1] < arr[n-1] && res + 1 > max_ending_here)
            max_ending_here = res + 1;
    }
  
    // Compare max_ending_here with the overall max. And
    // update the overall max if needed

39
Chapter 3. DP-03 | Longest Increasing Subsequence

    if (*max_ref < max_ending_here)


       *max_ref = max_ending_here;
  
    // Return length of LIS ending with arr[n-1]
    return max_ending_here;
}
  
// The wrapper function for _lis()
int lis(int arr[], int n)
{
    // The max variable holds the result
    int max = 1;
  
    // The function _lis() stores its result in max
    _lis( arr, n, &max );
  
    // returns max
    return max;
}
  
/* Driver program to test above function */
int main()
{
    int arr[] = { 10, 22, 9, 33, 21, 50, 41, 60 };
    int n = sizeof(arr)/sizeof(arr[0]);
    printf("Length of lis is %dn",
           lis( arr, n ));
    return 0;
}

Java

/* A Naive Java Program for LIS Implementation */


class LIS
{
   static int max_ref; // stores the LIS
  
   /* To make use of recursive calls, this function must return
   two things:
   1) Length of LIS ending with element arr[n-1]. We use
      max_ending_here for this purpose
   2) Overall maximum as the LIS may end with an element
      before arr[n-1] max_ref is used this purpose.
   The value of LIS of full array of size n is stored in
   *max_ref which is our final result */
   static int _lis(int arr[], int n)
   {
       // base case

40
Chapter 3. DP-03 | Longest Increasing Subsequence

       if (n == 1)
           return 1;
  
       // 'max_ending_here' is length of LIS ending with arr[n-1]
       int res, max_ending_here = 1;
  
        /* Recursively get all LIS ending with arr[0], arr[1] ...
           arr[n-2]. If   arr[i-1] is smaller than arr[n-1], and
           max ending with arr[n-1] needs to be updated, then
           update it */
        for (int i = 1; i < n; i++)
        {
            res = _lis(arr, i);
            if (arr[i-1] < arr[n-1] && res + 1 > max_ending_here)
                max_ending_here = res + 1;
        }
  
        // Compare max_ending_here with the overall max. And
        // update the overall max if needed
        if (max_ref < max_ending_here)
           max_ref = max_ending_here;
  
        // Return length of LIS ending with arr[n-1]
        return max_ending_here;
   }
  
    // The wrapper function for _lis()
    static int lis(int arr[], int n)
    {
        // The max variable holds the result
         max_ref = 1;
  
        // The function _lis() stores its result in max
        _lis( arr, n);
  
        // returns max
        return max_ref;
    }
  
    // driver program to test above functions
    public static void main(String args[])
    {
        int arr[] = { 10, 22, 9, 33, 21, 50, 41, 60 };
        int n = arr.length;
        System.out.println("Length of lis is "
                           + lis(arr, n) + "n");
    }
 }

41
Chapter 3. DP-03 | Longest Increasing Subsequence

/*This code is contributed by Rajat Mishra*/

Python

# A naive Python implementation of LIS problem


  
""" To make use of recursive calls, this function must return
 two things:
 1) Length of LIS ending with element arr[n-1]. We use
 max_ending_here for this purpose
 2) Overall maximum as the LIS may end with an element
 before arr[n-1] max_ref is used this purpose.
 The value of LIS of full array of size n is stored in
 *max_ref which is our final result """
  
# global variable to store the maximum
global maximum
  
def _lis(arr , n ):
  
    # to allow the access of global variable
    global maximum
  
    # Base Case
    if n == 1 :
        return 1
  
    # maxEndingHere is the length of LIS ending with arr[n-1]
    maxEndingHere = 1
  
    """Recursively get all LIS ending with arr[0], arr[1]..arr[n-2]
       IF arr[n-1] is maller than arr[n-1], and max ending with
       arr[n-1] needs to be updated, then update it"""
    for i in xrange(1, n):
        res = _lis(arr , i)
        if arr[i-1] < arr[n-1] and res+1 > maxEndingHere:
            maxEndingHere = res +1
  
    # Compare maxEndingHere with overall maximum. And
    # update the overall maximum if needed
    maximum = max(maximum , maxEndingHere)
  
    return maxEndingHere
  
def lis(arr):
  
    # to allow the access of global variable
    global maximum

42
Chapter 3. DP-03 | Longest Increasing Subsequence

  
    # lenght of arr
    n = len(arr)
  
    # maximum variable holds the result
    maximum = 1
  
    # The function _lis() stores its result in maximum
    _lis(arr , n)
  
    return maximum
  
# Driver program to test the above function
arr = [10 , 22 , 9 , 33 , 21 , 50 , 41 , 60]
n = len(arr)
print "Length of lis is ", lis(arr)
  
# This code is contributed by NIKHIL KUMAR SINGH

Length of lis is 5

Overlapping Subproblems:
Considering the above implementation, following is recursion tree for an array of size 4.
lis(n) gives us the length of LIS for arr[].

lis(4)
/ |
lis(3) lis(2) lis(1)
/ /
lis(2) lis(1) lis(1)
/
lis(1)

We can see that there are many subproblems which are solved again and again. So this
problem has Overlapping Substructure property and recomputation of same subproblems
can be avoided by either using Memoization or Tabulation. Following is a tabluated imple-
mentation for the LIS problem.
C/C++

/* Dynamic Programming C/C++ implementation of LIS problem */


#include<stdio.h>
#include<stdlib.h>
  
/* lis() returns the length of the longest increasing
  subsequence in arr[] of size n */
int lis( int arr[], int n )

43
Chapter 3. DP-03 | Longest Increasing Subsequence

{
    int *lis, i, j, max = 0;
    lis = (int*) malloc ( sizeof( int ) * n );
  
    /* Initialize LIS values for all indexes */
    for (i = 0; i < n; i++ )
        lis[i] = 1;
  
    /* Compute optimized LIS values in bottom up manner */
    for (i = 1; i < n; i++ )
        for (j = 0; j < i; j++ ) 
            if ( arr[i] > arr[j] && lis[i] < lis[j] + 1)
                lis[i] = lis[j] + 1;
  
    /* Pick maximum of all LIS values */
    for (i = 0; i < n; i++ )
        if (max < lis[i])
            max = lis[i];
  
    /* Free memory to avoid memory leak */
    free(lis);
  
    return max;
}
  
/* Driver program to test above function */
int main()
{
    int arr[] = { 10, 22, 9, 33, 21, 50, 41, 60 };
    int n = sizeof(arr)/sizeof(arr[0]);
    printf("Length of lis is %dn", lis( arr, n ) );
    return 0;
}

Java

/* Dynamic Programming Java implementation of LIS problem */


  
class LIS
{
    /* lis() returns the length of the longest increasing
       subsequence in arr[] of size n */
    static int lis(int arr[],int n)
    {
          int lis[] = new int[n];
          int i,j,max = 0;
  
          /* Initialize LIS values for all indexes */

44
Chapter 3. DP-03 | Longest Increasing Subsequence

           for ( i = 0; i < n; i++ )


              lis[i] = 1;
  
           /* Compute optimized LIS values in bottom up manner */
           for ( i = 1; i < n; i++ )
              for ( j = 0; j < i; j++ ) 
                         if ( arr[i] > arr[j] && lis[i] < lis[j] + 1)
                    lis[i] = lis[j] + 1;
  
           /* Pick maximum of all LIS values */
           for ( i = 0; i < n; i++ )
              if ( max < lis[i] )
                 max = lis[i];
  
            return max;
    }
  
    public static void main(String args[])
    {
        int arr[] = { 10, 22, 9, 33, 21, 50, 41, 60 };
            int n = arr.length;
            System.out.println("Length of lis is " + lis( arr, n ) + "n" );
    }
}
/*This code is contributed by Rajat Mishra*/

Python

# Dynamic programming Python implementation of LIS problem


  
# lis returns length of the longest increasing subsequence
# in arr of size n
def lis(arr):
    n = len(arr)
  
    # Declare the list (array) for LIS and initialize LIS
    # values for all indexes
    lis = [1]*n
  
    # Compute optimized LIS values in bottom up manner
    for i in range (1 , n):
        for j in range(0 , i):
            if arr[i] > arr[j] and lis[i]< lis[j] + 1 :
                lis[i] = lis[j]+1
  
    # Initialize maximum to 0 to get the maximum of all
    # LIS
    maximum = 0

45
Chapter 3. DP-03 | Longest Increasing Subsequence

  
    # Pick maximum of all LIS values
    for i in range(n):
        maximum = max(maximum , lis[i])
  
    return maximum
# end of lis function
  
# Driver program to test above function
arr = [10, 22, 9, 33, 21, 50, 41, 60]
print "Length of lis is", lis(arr)
# This code is contributed by Nikhil Kumar Singh

Output:

Length of lis is 5

Note that the time complexity of the above Dynamic Programming (DP) solution is O(n^2)
and there is a O(nLogn) solution for the LIS problem. We have not discussed the O(n Log
n) solution here as the purpose of this post is to explain Dynamic Programming with a
simple example. See below post for O(n Log n) solution.
Longest Increasing Subsequence Size (N log N)

• Printing LIS of array


• Recent articles based on LIS!

Source

https://www.geeksforgeeks.org/longest-increasing-subsequence-dp-3/

46
Chapter 4

DP-04 | Longest Common


Subsequence

Longest Common Subsequence | DP-4 - GeeksforGeeks


We have discussed Overlapping Subproblems and Optimal Substructure properties in Set
1 and Set 2 respectively. We also discussed one example problem in Set 3. Let us discuss
Longest Common Subsequence (LCS) problem as one more example problem that can be
solved using Dynamic Programming.
LCS Problem Statement: Given two sequences, find the length of longest subsequence present
in both of them. A subsequence is a sequence that appears in the same relative order, but
not necessarily contiguous. For example, “abc”, “abg”, “bdf”, “aeg”, ‘”acefg”, .. etc are
subsequences of “abcdefg”. So a string of length n has 2^n different possible subsequences.
It is a classic computer science problem, the basis of diff(a file comparison program that
outputs the differences between two files), and has applications in bioinformatics.
Examples:
LCS for input Sequences “ABCDGH” and “AEDFHR” is “ADH” of length 3.
LCS for input Sequences “AGGTAB” and “GXTXAYB” is “GTAB” of length 4.
The naive solution for this problem is to generate all subsequences of both given sequences
and find the longest matching subsequence. This solution is exponential in term of time
complexity. Let us see how this problem possesses both important properties of a Dynamic
Programming (DP) Problem.
1) Optimal Substructure:
Let the input sequences be X[0..m-1] and Y[0..n-1] of lengths m and n respectively. And let
L(X[0..m-1], Y[0..n-1]) be the length of LCS of the two sequences X and Y. Following is the
recursive definition of L(X[0..m-1], Y[0..n-1]).
If last characters of both sequences match (or X[m-1] == Y[n-1]) then
L(X[0..m-1], Y[0..n-1]) = 1 + L(X[0..m-2], Y[0..n-2])
If last characters of both sequences do not match (or X[m-1] != Y[n-1]) then
L(X[0..m-1], Y[0..n-1]) = MAX ( L(X[0..m-2], Y[0..n-1]), L(X[0..m-1], Y[0..n-2]) )

47
Chapter 4. DP-04 | Longest Common Subsequence

Examples:
1) Consider the input strings “AGGTAB” and “GXTXAYB”. Last characters match for the
strings. So length of LCS can be written as:
L(“AGGTAB”, “GXTXAYB”) = 1 + L(“AGGTA”, “GXTXAY”)

2) Consider the input strings “ABCDGH” and “AEDFHR. Last characters do not match
for the strings. So length of LCS can be written as:
L(“ABCDGH”, “AEDFHR”) = MAX ( L(“ABCDG”, “AEDFHR”), L(“ABCDGH”,
“AEDFH”) )
So the LCS problem has optimal substructure property as the main problem can be solved
using solutions to subproblems.
2) Overlapping Subproblems:
Following is simple recursive implementation of the LCS problem. The implementation
simply follows the recursive structure mentioned above.
C/C++

/* A Naive recursive implementation of LCS problem */


#include<bits/stdc++.h>
  
int max(int a, int b);
  
/* Returns length of LCS for X[0..m-1], Y[0..n-1] */
int lcs( char *X, char *Y, int m, int n )
{
   if (m == 0 || n == 0)
     return 0;
   if (X[m-1] == Y[n-1])
     return 1 + lcs(X, Y, m-1, n-1);
   else
     return max(lcs(X, Y, m, n-1), lcs(X, Y, m-1, n));
}
  
/* Utility function to get max of 2 integers */

48
Chapter 4. DP-04 | Longest Common Subsequence

int max(int a, int b)


{
    return (a > b)? a : b;
}
  
/* Driver program to test above function */
int main()
{
  char X[] = "AGGTAB";
  char Y[] = "GXTXAYB";
  
  int m = strlen(X);
  int n = strlen(Y);
  
  printf("Length of LCS is %d", lcs( X, Y, m, n ) );
  
  return 0;
}

Java

/* A Naive recursive implementation of LCS problem in java*/


public class LongestCommonSubsequence
{
  
  /* Returns length of LCS for X[0..m-1], Y[0..n-1] */
  int lcs( char[] X, char[] Y, int m, int n )
  {
    if (m == 0 || n == 0)
      return 0;
    if (X[m-1] == Y[n-1])
      return 1 + lcs(X, Y, m-1, n-1);
    else
      return max(lcs(X, Y, m, n-1), lcs(X, Y, m-1, n));
  }
  
  /* Utility function to get max of 2 integers */
  int max(int a, int b)
  {
    return (a > b)? a : b;
  }
  
  public static void main(String[] args)
  {
    LongestCommonSubsequence lcs = new LongestCommonSubsequence();
    String s1 = "AGGTAB";
    String s2 = "GXTXAYB";
  

49
Chapter 4. DP-04 | Longest Common Subsequence

    char[] X=s1.toCharArray();
    char[] Y=s2.toCharArray();
    int m = X.length;
    int n = Y.length;
  
    System.out.println("Length of LCS is" + " " +
                                  lcs.lcs( X, Y, m, n ) );
  }
  
}
  
// This Code is Contributed by Saket Kumar

Python

# A Naive recursive Python implementation of LCS problem


  
def lcs(X, Y, m, n):
  
    if m == 0 or n == 0:
       return 0;
    elif X[m-1] == Y[n-1]:
       return 1 + lcs(X, Y, m-1, n-1);
    else:
       return max(lcs(X, Y, m, n-1), lcs(X, Y, m-1, n));
  
  
# Driver program to test the above function
X = "AGGTAB"
Y = "GXTXAYB"
print "Length of LCS is ", lcs(X , Y, len(X), len(Y))

C#

/* C#  Naive recursive implementation of LCS problem */


using System;
  
class GFG
{
      
  
    /* Returns length of LCS for X[0..m-1], Y[0..n-1] */
    static int lcs( char[] X, char[] Y, int m, int n )
    {
        if (m == 0 || n == 0)
        return 0;
        if (X[m - 1] == Y[n - 1])

50
Chapter 4. DP-04 | Longest Common Subsequence

        return 1 + lcs(X, Y, m - 1, n - 1);


        else
        return max(lcs(X, Y, m, n - 1), lcs(X, Y, m - 1, n));
    }
      
    /* Utility function to get max of 2 integers */
    static int max(int a, int b)
    {
        return (a > b)? a : b;
    }
      
    public static void Main()
    {
        String s1 = "AGGTAB";
        String s2 = "GXTXAYB";
      
        char[] X=s1.ToCharArray();
        char[] Y=s2.ToCharArray();
        int m = X.Length;
        int n = Y.Length;
      
        Console.Write("Length of LCS is" + " " 
                      +lcs( X, Y, m, n ) );
    }
}
// This code is Contributed by Sam007

PHP

<?php 
// A Naive recursive PHP
// implementation of LCS problem 
function lcs($X, $Y, $m, $n)

    if($m == 0 || $n == 0) 
    return 0; 
    else if ($X[$m - 1] == $Y[$n - 1]) 
        return 1 + lcs($X, $Y, 
                       $m - 1, $n - 1); 
    else
        return max(lcs($X, $Y, $m, $n - 1), 
                   lcs($X, $Y, $m - 1, $n)); 
}
  
// Driver Code
$X = "AGGTAB";
$Y = "GXTXAYB";
echo "Length of LCS is ";

51
Chapter 4. DP-04 | Longest Common Subsequence

echo lcs($X , $Y, strlen($X),


                  strlen($Y)); 
  
// This code is contributed
// by Shivi_Aggarwal
?>

Output:

Length of LCS is 4

Time complexity of the above naive recursive approach is O(2^n) in worst case and worst
case happens when all characters of X and Y mismatch i.e., length of LCS is 0.
Considering the above implementation, following is a partial recursion tree for input strings
“AXYT” and “AYZX”

lcs("AXYT", "AYZX")
/
lcs("AXY", "AYZX") lcs("AXYT", "AYZ")
/ /
lcs("AX", "AYZX") lcs("AXY", "AYZ") lcs("AXY", "AYZ") lcs("AXYT", "AY")

In the above partial recursion tree, lcs(“AXY”, “AYZ”) is being solved twice. If we draw the
complete recursion tree, then we can see that there are many subproblems which are solved
again and again. So this problem has Overlapping Substructure property and recomputation
of same subproblems can be avoided by either using Memoization or Tabulation. Following
is a tabulated implementation for the LCS problem.
C/C++

/* Dynamic Programming C/C++ implementation of LCS problem */


#include<bits/stdc++.h>
   
int max(int a, int b);
   
/* Returns length of LCS for X[0..m-1], Y[0..n-1] */
int lcs( char *X, char *Y, int m, int n )
{
   int L[m+1][n+1];
   int i, j;
   
   /* Following steps build L[m+1][n+1] in bottom up fashion. Note 
      that L[i][j] contains length of LCS of X[0..i-1] and Y[0..j-1] */
   for (i=0; i<=m; i++)
   {
     for (j=0; j<=n; j++)
     {

52
Chapter 4. DP-04 | Longest Common Subsequence

       if (i == 0 || j == 0)
         L[i][j] = 0;
   
       else if (X[i-1] == Y[j-1])
         L[i][j] = L[i-1][j-1] + 1;
   
       else
         L[i][j] = max(L[i-1][j], L[i][j-1]);
     }
   }
     
   /* L[m][n] contains length of LCS for X[0..n-1] and Y[0..m-1] */
   return L[m][n];
}
   
/* Utility function to get max of 2 integers */
int max(int a, int b)
{
    return (a > b)? a : b;
}
   
/* Driver program to test above function */
int main()
{
  char X[] = "AGGTAB";
  char Y[] = "GXTXAYB";
   
  int m = strlen(X);
  int n = strlen(Y);
   
  printf("Length of LCS is %d", lcs( X, Y, m, n ) );
  
  return 0;
}

Java

/* Dynamic Programming Java implementation of LCS problem */


public class LongestCommonSubsequence
{
  
  /* Returns length of LCS for X[0..m-1], Y[0..n-1] */
  int lcs( char[] X, char[] Y, int m, int n )
  {
    int L[][] = new int[m+1][n+1];
  
    /* Following steps build L[m+1][n+1] in bottom up fashion. Note
         that L[i][j] contains length of LCS of X[0..i-1] and Y[0..j-1] */

53
Chapter 4. DP-04 | Longest Common Subsequence

    for (int i=0; i<=m; i++)


    {
      for (int j=0; j<=n; j++)
      {
        if (i == 0 || j == 0)
            L[i][j] = 0;
        else if (X[i-1] == Y[j-1])
            L[i][j] = L[i-1][j-1] + 1;
        else
            L[i][j] = max(L[i-1][j], L[i][j-1]);
      }
    }
  return L[m][n];
  }
  
  /* Utility function to get max of 2 integers */
  int max(int a, int b)
  {
    return (a > b)? a : b;
  }
  
  public static void main(String[] args)
  {
    LongestCommonSubsequence lcs = new LongestCommonSubsequence();
    String s1 = "AGGTAB";
    String s2 = "GXTXAYB";
  
    char[] X=s1.toCharArray();
    char[] Y=s2.toCharArray();
    int m = X.length;
    int n = Y.length;
  
    System.out.println("Length of LCS is" + " " +
                                  lcs.lcs( X, Y, m, n ) );
  }
  
}
  
// This Code is Contributed by Saket Kumar

Python

# Dynamic Programming implementation of LCS problem


  
def lcs(X , Y):
    # find the length of the strings
    m = len(X)
    n = len(Y)

54
Chapter 4. DP-04 | Longest Common Subsequence

  
    # declaring the array for storing the dp values
    L = [[None]*(n+1) for i in xrange(m+1)]
  
    """Following steps build L[m+1][n+1] in bottom up fashion
    Note: L[i][j] contains length of LCS of X[0..i-1]
    and Y[0..j-1]"""
    for i in range(m+1):
        for j in range(n+1):
            if i == 0 or j == 0 :
                L[i][j] = 0
            elif X[i-1] == Y[j-1]:
                L[i][j] = L[i-1][j-1]+1
            else:
                L[i][j] = max(L[i-1][j] , L[i][j-1])
  
    # L[m][n] contains the length of LCS of X[0..n-1] & Y[0..m-1]
    return L[m][n]
#end of function lcs
  
  
# Driver program to test the above function
X = "AGGTAB"
Y = "GXTXAYB"
print "Length of LCS is ", lcs(X, Y)
  
# This code is contributed by Nikhil Kumar Singh(nickzuck_007)

C#

// Dynamic Programming C# implementation 


// of LCS problem 
using System;
  
class GFG
{
  
    /* Returns length of LCS for X[0..m-1], Y[0..n-1] */
    static int lcs( char[] X, char[] Y, int m, int n )
    {
        int [,]L = new int[m+1,n+1];
      
        /* Following steps build L[m+1][n+1] 
        in bottom up fashion. Note
        that L[i][j] contains length of 
        LCS of X[0..i-1] and Y[0..j-1] */
        for (int i = 0; i <= m; i++)
        {

55
Chapter 4. DP-04 | Longest Common Subsequence

            for (int j = 0; j <= n; j++)


            {
                if (i == 0 || j == 0)
                    L[i, j] = 0;
                else if (X[i - 1] == Y[j - 1])
                    L[i, j] = L[i - 1, j - 1] + 1;
                else
                    L[i, j] = max(L[i - 1, j], L[i, j - 1]);
            }
        }
        return L[m, n];
    }
      
    /* Utility function to get max of 2 integers */
    static int max(int a, int b)
    {
        return (a > b)? a : b;
    }
      
    // Driver code
    public static void Main()
    {
          
        String s1 = "AGGTAB";
        String s2 = "GXTXAYB";
      
        char[] X=s1.ToCharArray();
        char[] Y=s2.ToCharArray();
        int m = X.Length;
        int n = Y.Length;
      
        Console.Write("Length of LCS is" + " " +lcs( X, Y, m, n ) );
    }
}
// This Code is Contributed by Sam007 

PHP

<?php 
// Dynamic Programming C# 
// implementation of LCS problem 
function lcs($X , $Y)
{
// find the length of the strings 
$m = strlen($X); 
$n = strlen($Y) ;
  
// declaring the array for 

56
Chapter 4. DP-04 | Longest Common Subsequence

// storing the dp values 


  
/*Following steps build L[m+1][n+1] 
in bottom up fashion .
Note: L[i][j] contains length of 
LCS of X[0..i-1] and Y[0..j-1] */
for ($i = 0; $i <= $m; $i++) 

for ($j = 0; $j <= $n; $j++) 

    if ($i == 0 || $j == 0) 
    $L[$i][$j] = 0; 
  
    else if ($X[$i - 1] == $Y[$j - 1]) 
    $L[$i][$j] = $L[$i - 1][$j - 1] + 1; 
  
    else
    $L[$i][$j] = max($L[$i - 1][$j],
                     $L[$i][$j - 1]); 


  
// L[m][n] contains the length of
// LCS of X[0..n-1] & Y[0..m-1] 
  
return $L[$m][$n];
}
  
// Driver Code
$X = "AGGTAB";
$Y = "GXTXAYB";
echo "Length of LCS is ";
echo lcs($X, $Y); 
  
// This code is contributed
// by Shivi_Aggarwal
?>

Output:

Length of LCS is 4

Time Complexity of the above implementation is O(mn) which is much better than the
worst-case time complexity of Naive Recursive implementation.
The above algorithm/code returns only length of LCS. Please see the following post for
printing the LCS.
Printing Longest Common Subsequence

57
Chapter 4. DP-04 | Longest Common Subsequence

You can also check the space optimized version of LCS at


Space Optimized Solution of LCS
Recent Articles based on LCS!
References:
http://www.youtube.com/watch?v=V5hZoJ6uK-s
http://www.algorithmist.com/index.php/Longest_Common_Subsequence
http://www.ics.uci.edu/~eppstein/161/960229.html
http://en.wikipedia.org/wiki/Longest_common_subsequence_problem
Improved By : sirrobot, Shivi_Aggarwal

Source

https://www.geeksforgeeks.org/longest-common-subsequence-dp-4/

58
Chapter 5

DP-05 | Edit Distance

Edit Distance | DP-5 - GeeksforGeeks


Given two strings str1 and str2 and below operations that can performed on str1. Find
minimum number of edits (operations) required to convert ‘str1’ into ‘str2’.

1. Insert
2. Remove
3. Replace

All of the above operations are of equal cost.

Examples:

Input: str1 = "geek", str2 = "gesek"


Output: 1
We can convert str1 into str2 by inserting a 's'.

Input: str1 = "cat", str2 = "cut"


Output: 1
We can convert str1 into str2 by replacing 'a' with 'u'.

Input: str1 = "sunday", str2 = "saturday"


Output: 3
Last three and first characters are same. We basically
need to convert "un" to "atur". This can be done using
below three operations.
Replace 'n' with 'r', insert t, insert a

What are the subproblems in this case?


The idea is process all characters one by one staring from either from left or right sides of
both strings.

59
Chapter 5. DP-05 | Edit Distance

Let us traverse from right corner, there are two possibilities for every pair of character being
traversed.

m: Length of str1 (first string)


n: Length of str2 (second string)

1. If last characters of two strings are same, nothing much to do. Ignore last characters
and get count for remaining strings. So we recur for lengths m-1 and n-1.
2. Else (If last characters are not same), we consider all operations on ‘str1’, consider all
three operations on last character of first string, recursively compute minimum cost
for all three operations and take minimum of three values.
(a) Insert: Recur for m and n-1
(b) Remove: Recur for m-1 and n
(c) Replace: Recur for m-1 and n-1

Below is C++ implementation of above Naive recursive solution.


C++

// A Naive recursive C++ program to find minimum number


// operations to convert str1 to str2
#include<bits/stdc++.h>
using namespace std;
  
// Utility function to find minimum of three numbers
int min(int x, int y, int z)
{
   return min(min(x, y), z);
}
  
int editDist(string str1 , string str2 , int m ,int n)
{
    // If first string is empty, the only option is to
    // insert all characters of second string into first
    if (m == 0) return n;
  
    // If second string is empty, the only option is to
    // remove all characters of first string
    if (n == 0) return m;
  
    // If last characters of two strings are same, nothing
    // much to do. Ignore last characters and get count for
    // remaining strings.
    if (str1[m-1] == str2[n-1])
        return editDist(str1, str2, m-1, n-1);
  
    // If last characters are not same, consider all three

60
Chapter 5. DP-05 | Edit Distance

    // operations on last character of first string, recursively


    // compute minimum cost for all three operations and take
    // minimum of three values.
    return 1 + min ( editDist(str1,  str2, m, n-1),    // Insert
                     editDist(str1,  str2, m-1, n),   // Remove
                     editDist(str1,  str2, m-1, n-1) // Replace
                   );
}
  
// Driver program
int main()
{
    // your code goes here
    string str1 = "sunday";
    string str2 = "saturday";
  
    cout << editDist( str1 , str2 , str1.length(), str2.length());
  
    return 0;
}

Java

// A Naive recursive Java program to find minimum number


// operations to convert str1 to str2
class EDIST
{
    static int min(int x,int y,int z)
    {
        if (x<=y && x<=z) return x;
        if (y<=x && y<=z) return y;
        else return z;
    }
  
    static int editDist(String str1 , String str2 , int m ,int n)
    {
        // If first string is empty, the only option is to
    // insert all characters of second string into first
    if (m == 0) return n;
       
    // If second string is empty, the only option is to
    // remove all characters of first string
    if (n == 0) return m;
       
    // If last characters of two strings are same, nothing
    // much to do. Ignore last characters and get count for
    // remaining strings.
    if (str1.charAt(m-1) == str2.charAt(n-1))

61
Chapter 5. DP-05 | Edit Distance

        return editDist(str1, str2, m-1, n-1);


       
    // If last characters are not same, consider all three
    // operations on last character of first string, recursively
    // compute minimum cost for all three operations and take
    // minimum of three values.
    return 1 + min ( editDist(str1,  str2, m, n-1),    // Insert
                     editDist(str1,  str2, m-1, n),   // Remove
                     editDist(str1,  str2, m-1, n-1) // Replace                     
                   );
    }
  
    public static void main(String args[])
    {
        String str1 = "sunday";
        String str2 = "saturday";
   
        System.out.println( editDist( str1 , str2 , str1.length(), str2.length()) );
    }
}
/*This code is contributed by Rajat Mishra*/

Python

# A Naive recursive Python program to fin minimum number


# operations to convert str1 to str2
def editDistance(str1, str2, m , n):
  
    # If first string is empty, the only option is to
    # insert all characters of second string into first
    if m==0:
         return n
  
    # If second string is empty, the only option is to
    # remove all characters of first string
    if n==0:
        return m
  
    # If last characters of two strings are same, nothing
    # much to do. Ignore last characters and get count for
    # remaining strings.
    if str1[m-1]==str2[n-1]:
        return editDistance(str1,str2,m-1,n-1)
  
    # If last characters are not same, consider all three
    # operations on last character of first string, recursively
    # compute minimum cost for all three operations and take
    # minimum of three values.

62
Chapter 5. DP-05 | Edit Distance

    return 1 + min(editDistance(str1, str2, m, n-1),    # Insert


                   editDistance(str1, str2, m-1, n),    # Remove
                   editDistance(str1, str2, m-1, n-1)    # Replace
                   )
  
# Driver program to test the above function
str1 = "sunday"
str2 = "saturday"
print editDistance(str1, str2, len(str1), len(str2))
  
# This code is contributed by Bhavya Jain

C#

// A Naive recursive C# program to


// find minimum numberoperations 
// to convert str1 to str2
using System;
  
class GFG
{
    static int min(int x, int y, int z)
    {
        if (x <= y && x <= z) return x;
        if (y <= x && y <= z) return y;
        else return z;
    }
  
    static int editDist(String str1 , String str2 , int m ,int n)
    {
        // If first string is empty, the only option is to
        // insert all characters of second string into first
        if (m == 0) return n;
          
        // If second string is empty, the only option is to
        // remove all characters of first string
        if (n == 0) return m;
          
        // If last characters of two strings are same, nothing
        // much to do. Ignore last characters and get count for
        // remaining strings.
        if (str1[m - 1] == str2[n - 1])
            return editDist(str1, str2, m - 1, n - 1);
          
        // If last characters are not same, consider all three
        // operations on last character of first string, recursively
        // compute minimum cost for all three operations and take
        // minimum of three values.

63
Chapter 5. DP-05 | Edit Distance

        return 1 + min ( editDist(str1, str2, m, n - 1), // Insert


                        editDist(str1, str2, m - 1, n), // Remove
                        editDist(str1, str2, m - 1, n - 1) // Replace                     
                    );
    }
      
    // Driver code
    public static void Main()
    {
        String str1 = "sunday";
        String str2 = "saturday";
        Console.WriteLine( editDist( str1 , str2 , str1.Length, 
                                                 str2.Length ));
    }
}
  
// This Code is Contributed by Sam007

PHP

<?php 
// A Naive recursive Python program  
// to find minimum number operations 
// to convert str1 to str2 
function editDistance($str1, $str2, 
                      $m, $n)

    // If first string is empty, 
    // the only option is to insert.
    // all characters of second
    // string into first 
    if ($m == 0)
        return $n; 
  
    // If second string is empty,
    // the only option is to 
    // remove all characters of 
    // first string 
    if ($n == 0) 
        return $m; 
  
    // If last characters of two 
    // strings are same, nothing 
    // much to do. Ignore last 
    // characters and get count 
    // for remaining strings. 
    if ($str1[$m - 1] == $str2[$n - 1])
    { 

64
Chapter 5. DP-05 | Edit Distance

        return editDistance($str1, $str2, 


                            $m - 1, $n - 1); 
    }
      
    // If last characters are not same, 
    // consider all three operations on 
    // last character of first string, 
    // recursively compute minimum cost 
    // for all three operations and take 
    // minimum of three values. 
  
    return 1 + min(editDistance($str1, $str2, 
                                $m, $n - 1), // Insert 
                   editDistance($str1, $str2, 
                                $m - 1, $n), // Remove 
                   editDistance($str1, $str2, 
                                $m - 1, $n - 1)); // Replace 

  
// Driver Code
$str1 = "sunday";
$str2 = "saturday";
echo editDistance($str1, $str2, strlen($str1), 
                                strlen($str2)); 
  
// This code is contributed 
// by Shivi_Aggarwal
?>

Output:

The time complexity of above solution is exponential. In worst case, we may end up doing
O(3m ) operations. The worst case happens when none of characters of two strings match.
Below is a recursive call diagram for worst case.

65
Chapter 5. DP-05 | Edit Distance

We can see that many subproblems are solved, again and again, for example, eD(2,2) is
called three times. Since same suproblems are called again, this problem has Overlapping
Subprolems property. So Edit Distance problem has both properties (see thisand this) of a
dynamic programming problem. Like other typical Dynamic Programming(DP) problems,
recomputations of same subproblems can be avoided by constructing a temporary array that
stores results of subproblems.
C++

// A Dynamic Programming based C++ program to find minimum


// number operations to convert str1 to str2
#include<bits/stdc++.h>
using namespace std;
  
// Utility function to find the minimum of three numbers
int min(int x, int y, int z)
{
    return min(min(x, y), z);
}
  
int editDistDP(string str1, string str2, int m, int n)
{
    // Create a table to store results of subproblems
    int dp[m+1][n+1];
  
    // Fill d[][] in bottom up manner
    for (int i=0; i<=m; i++)
    {
        for (int j=0; j<=n; j++)
        {

66
Chapter 5. DP-05 | Edit Distance

            // If first string is empty, only option is to


            // isnert all characters of second string
            if (i==0)
                dp[i][j] = j;  // Min. operations = j
  
            // If second string is empty, only option is to
            // remove all characters of second string
            else if (j==0)
                dp[i][j] = i; // Min. operations = i
  
            // If last characters are same, ignore last char
            // and recur for remaining string
            else if (str1[i-1] == str2[j-1])
                dp[i][j] = dp[i-1][j-1];
  
            // If the last character is different, consider all
            // possibilities and find the minimum
            else
                dp[i][j] = 1 + min(dp[i][j-1],  // Insert
                                   dp[i-1][j],  // Remove
                                   dp[i-1][j-1]); // Replace
        }
    }
  
    return dp[m][n];
}
  
// Driver program
int main()
{
    // your code goes here
    string str1 = "sunday";
    string str2 = "saturday";
  
    cout << editDistDP(str1, str2, str1.length(), str2.length());
  
    return 0;
}

Java

// A Dynamic Programming based Java program to find minimum


// number operations to convert str1 to str2
class EDIST
{
    static int min(int x,int y,int z)
    {
        if (x <= y && x <= z) return x;

67
Chapter 5. DP-05 | Edit Distance

        if (y <= x && y <= z) return y;


        else return z;
    }
  
    static int editDistDP(String str1, String str2, int m, int n)
    {
        // Create a table to store results of subproblems
        int dp[][] = new int[m+1][n+1];
       
        // Fill d[][] in bottom up manner
        for (int i=0; i<=m; i++)
        {
            for (int j=0; j<=n; j++)
            {
                // If first string is empty, only option is to
                // isnert all characters of second string
                if (i==0)
                    dp[i][j] = j;  // Min. operations = j
       
                // If second string is empty, only option is to
                // remove all characters of second string
                else if (j==0)
                    dp[i][j] = i; // Min. operations = i
       
                // If last characters are same, ignore last char
                // and recur for remaining string
                else if (str1.charAt(i-1) == str2.charAt(j-1))
                    dp[i][j] = dp[i-1][j-1];
       
                // If the last character is different, consider all
                // possibilities and find the minimum
                else
                    dp[i][j] = 1 + min(dp[i][j-1],  // Insert
                                       dp[i-1][j],  // Remove
                                       dp[i-1][j-1]); // Replace
            }
        }
   
        return dp[m][n];
    }
  
      
  
    public static void main(String args[])
    {
        String str1 = "sunday";
        String str2 = "saturday";
        System.out.println( editDistDP( str1 , str2 , str1.length(), str2.length()) );

68
Chapter 5. DP-05 | Edit Distance

    }
}/*This code is contributed by Rajat Mishra*/

Python

# A Dynamic Programming based Python program for edit


# distance problem
def editDistDP(str1, str2, m, n):
    # Create a table to store results of subproblems
    dp = [[0 for x in range(n+1)] for x in range(m+1)]
  
    # Fill d[][] in bottom up manner
    for i in range(m+1):
        for j in range(n+1):
  
            # If first string is empty, only option is to
            # isnert all characters of second string
            if i == 0:
                dp[i][j] = j    # Min. operations = j
  
            # If second string is empty, only option is to
            # remove all characters of second string
            elif j == 0:
                dp[i][j] = i    # Min. operations = i
  
            # If last characters are same, ignore last char
            # and recur for remaining string
            elif str1[i-1] == str2[j-1]:
                dp[i][j] = dp[i-1][j-1]
  
            # If last character are different, consider all
            # possibilities and find minimum
            else:
                dp[i][j] = 1 + min(dp[i][j-1],        # Insert
                                   dp[i-1][j],        # Remove
                                   dp[i-1][j-1])    # Replace
  
    return dp[m][n]
  
# Driver program
str1 = "sunday"
str2 = "saturday"
  
print(editDistDP(str1, str2, len(str1), len(str2)))
# This code is contributed by Bhavya Jain

C#

69
Chapter 5. DP-05 | Edit Distance

// A Dynamic Programming based 


// C# program to find minimum
// number operations to 
// convert str1 to str2
using System;
  
class GFG
{
    static int min(int x, int y, int z)
    {
        if (x <= y && x <= z) return x;
        if (y <= x && y <= z) return y;
        else return z;
    }
  
    static int editDistDP(String str1, String str2, int m, int n)
    {
        // Create a table to store
        // results of subproblems
        int [,]dp = new int[m + 1,n + 1];
      
        // Fill d[][] in bottom up manner
        for (int i = 0; i <= m; i++)
        {
            for (int j = 0; j <= n; j++)
            {
                // If first string is empty, only option is to
                // isnert all characters of second string
                if (i == 0)
                  
                    // Min. operations = j
                    dp[i, j] = j; 
      
                // If second string is empty, only option is to
                // remove all characters of second string
                else if (j == 0)
                       
                     // Min. operations = i
                    dp[i,j] = i; 
      
                // If last characters are same, ignore last char
                // and recur for remaining string
                else if (str1[i - 1] == str2[j - 1])
                    dp[i, j] = dp[i - 1, j - 1];
      
                // If the last character is different, consider all
                // possibilities and find the minimum
                else

70
Chapter 5. DP-05 | Edit Distance

                    dp[i, j] = 1 + min(dp[i, j - 1], // Insert


                                    dp[i - 1, j], // Remove
                                    dp[i - 1, j - 1]); // Replace
            }
        }
  
        return dp[m, n];
    }
  
      
    // Driver code
    public static void Main()
    {
        String str1 = "sunday";
        String str2 = "saturday";
        Console.Write( editDistDP( str1 , str2 , str1.Length, 
                                               str2.Length ));
    }
}
// This Code is Contributed by Sam007

PHP

<?php
// A Dynamic Programming based 
// Python program for edit 
// distance problem 
function editDistDP($str1, $str2, 
                    $m, $n)

// Fill d[][] in bottom up manner 
for ($i = 0; $i <= $m; $i++) 
{  
    for ($j = 0; $j <= $n; $j++) 
    { 
  
        // If first string is empty, 
        // only option is to insert 
        // all characters of second string 
        if ($i == 0) 
            $dp[$i][$j] = $j ; // Min. operations = j 
  
        // If second string is empty, 
        // only option is to remove 
        // all characters of second string 
        else if($j == 0) 
            $dp[$i][$j] = $i; // Min. operations = i 
  

71
Chapter 5. DP-05 | Edit Distance

        // If last characters are same, 


        // ignore last char and recur 
        // for remaining string 
        else if($str1[$i - 1] == $str2[$j - 1]) 
            $dp[$i][$j] = $dp[$i - 1][$j - 1];
  
        // If last character are different, 
        // consider all possibilities and 
        // find minimum 
        else
        { 
            $dp[$i][$j] = 1 + min($dp[$i][$j - 1],     // Insert 
                                  $dp[$i - 1][$j],     // Remove 
                                  $dp[$i - 1][$j - 1]); // Replace 
        }
    }
}
return $dp[$m][$n] ;
}
  
// Driver Code 
$str1 = "sunday";
$str2 = "saturday";
  
echo editDistDP($str1, $str2, strlen($str1), 
                              strlen($str2));
  
// This code is contributed 
// by Shivi_Aggarwal
?>

Output:

Time Complexity: O(m x n)


Auxiliary Space: O(m x n)
Applications: There are many practical applications of edit distance algorithm, refer
Lucene API for sample. Another example, display all the words in a dictionary that are
near proximity to a given wordincorrectly spelled word.
Thanks to Vivek Kumar for suggesting updates.
Thanks to Venki for providing initial post. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above
Improved By : Shivi_Aggarwal

72
Chapter 5. DP-05 | Edit Distance

Source

https://www.geeksforgeeks.org/edit-distance-dp-5/

73
Chapter 6

DP-06 | Min Cost Path

Min Cost Path | DP-6 - GeeksforGeeks


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. You may assume that all costs are positive integers.
For example, in the following figure, what is the minimum cost path to (2, 2)?

The path with minimum cost is highlighted in the following figure. The path is (0, 0) –>
(0, 1) –> (1, 2) –> (2, 2). The cost of the path is 8 (1 + 2 + 2 + 3).

74
Chapter 6. DP-06 | Min Cost Path

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
Following is simple recursive implementation of the MCP (Minimum Cost Path) problem.
The implementation simply follows the recursive structure mentioned above.

/* A Naive recursive implementation of MCP(Minimum Cost Path) problem */


#include<stdio.h>
#include<limits.h>
#define R 3
#define C 3
  
int min(int x, int y, int z);
  
/* Returns cost of minimum cost path from (0,0) to (m, n) in mat[R][C]*/
int minCost(int cost[R][C], int m, int n)
{
   if (n < 0 || m < 0)
      return INT_MAX;
   else if (m == 0 && n == 0)
      return cost[m][n];
   else
      return cost[m][n] + min( minCost(cost, m-1, n-1),
                               minCost(cost, m-1, n), 
                               minCost(cost, m, n-1) );
}
  
/* A utility function that returns minimum of 3 integers */
int min(int x, int y, int z)
{
   if (x < y)
      return (x < z)? x : z;
   else
      return (y < z)? y : z;
}
  
/* Driver program to test above functions */
int main()
{
   int cost[R][C] = { {1, 2, 3},
                      {4, 8, 2},

75
Chapter 6. DP-06 | Min Cost Path

                      {1, 5, 3} };
   printf(" %d ", minCost(cost, 2, 2));
   return 0;
}

Java

/* A Naive recursive implementation of


MCP(Minimum Cost Path) problem */
public class GFG {
  
    /* A utility function that returns 
    minimum of 3 integers */
    static int min(int x, int y, int z)
    {
        if (x < y)
            return (x < z) ? x : z;
        else
            return (y < z) ? y : z;
    } 
      
    /* Returns cost of minimum cost path 
    from (0,0) to (m, n) in mat[R][C]*/
    static int minCost(int cost[][], int m,
                                     int n)
    {
        if (n < 0 || m < 0)
            return Integer.MAX_VALUE;
        else if (m == 0 && n == 0)
            return cost[m][n];
        else
            return cost[m][n] + 
                min( minCost(cost, m-1, n-1),
                     minCost(cost, m-1, n), 
                     minCost(cost, m, n-1) );
    }
  
    // Driver code
    public static void main(String args[]) 
    {
          
        int cost[][] = { {1, 2, 3},
                         {4, 8, 2},
                         {1, 5, 3} };
                           
        System.out.print(minCost(cost, 2, 2));
    }
}

76
Chapter 6. DP-06 | Min Cost Path

  
// This code is contributed by Sam007

Python3

# A Naive recursive implementation of MCP(Minimum Cost Path) problem


R = 3
C = 3
import sys
  
# Returns cost of minimum cost path from (0,0) to (m, n) in mat[R][C]
def minCost(cost, m, n):
    if (n < 0 or m < 0):
        return sys.maxsize
    elif (m == 0 and n == 0):
        return cost[m][n]
    else:
        return cost[m][n] + min( minCost(cost, m-1, n-1),
                                minCost(cost, m-1, n),
                                minCost(cost, m, n-1) )
  
#A utility function that returns minimum of 3 integers */
def min(x, y, z):
    if (x < y):
        return x if (x < z) else z
    else:
        return y if (y < z) else z
  
  
# Driver program to test above functions 
cost= [ [1, 2, 3],
        [4, 8, 2],
        [1, 5, 3] ]
print(minCost(cost, 2, 2))
  
# This code is contributed by
# Smitha Dinesh Semwal

C#

/* A Naive recursive implementation of


MCP(Minimum Cost Path) problem */
using System;
  
class GFG
{
  

77
Chapter 6. DP-06 | Min Cost Path

    /* A utility function that 


    returns minimum of 3 integers */
    static int min(int x, 
                   int y, int z)
    {
        if (x < y)
            return ((x < z) ? x : z);
        else
            return ((y < z) ? y : z);
    } 
      
    /* Returns cost of minimum 
    cost path from (0,0) to 
    (m, n) in mat[R][C]*/
    static int minCost(int [,]cost, 
                       int m , int n)
    {
        if (n < 0 || m < 0)
            return int.MaxValue;
        else if (m == 0 && n == 0)
            return cost[m, n];
        else
            return cost[m, n] + 
                   min(minCost(cost, m - 1, n - 1), 
                   minCost(cost, m - 1, n), 
                   minCost(cost, m, n - 1) );
    }
  
    // Driver code
    public static void Main() 
    {
          
        int [,]cost = {{1, 2, 3},
                       {4, 8, 2},
                       {1, 5, 3}};
                          
        Console.Write(minCost(cost, 2, 2));
    }
}
  
// This code is contributed
// by shiv_bhakt.

PHP

<?php
/* A Naive recursive implementation 
of MCP(Minimum Cost Path) problem */

78
Chapter 6. DP-06 | Min Cost Path

  
$R = 3;
$C = 3;
  
  
/* Returns cost of minimum  
cost path from (0,0) to 
(m, n) in mat[R][C]*/
function minCost($cost, $m, $n)
{
global $R;
global $C;
if ($n < 0 || $m < 0)
    return PHP_INT_MAX;
else if ($m == 0 && $n == 0)
    return $cost[$m][$n];
else
    return $cost[$m][$n] +  
            min1(minCost($cost, $m - 1, $n - 1),
            minCost($cost, $m - 1, $n), 
            minCost($cost, $m, $n - 1) );
}
  
/* A utility function that 
returns minimum of 3 integers */
function min1($x, $y, $z)
{
if ($x < $y)
    return ($x < $z)? $x : $z;
else
    return ($y < $z)? $y : $z;
}
  
// Driver Code
$cost = array(array(1, 2, 3),
              array (4, 8, 2),
              array (1, 5, 3));
echo minCost($cost, 2, 2);
  
// This code is contributed by mits.
?>

Output:

It should be noted that the above function computes the same subproblems again and again.

79
Chapter 6. DP-06 | Min Cost Path

See the following recursion tree, there are many nodes which apear more than once. Time
complexity of this naive recursive solution is exponential and it is terribly slow.

mC refers to minCost()
mC(2, 2)
/ | \
/ | \
mC(1, 1) mC(1, 2) mC(2, 1)
/ | \ / | \ / | \
/ | \ / | \ / | \
mC(0,0) mC(0,1) mC(1,0) mC(0,1) mC(0,2) mC(1,1) mC(1,0) mC(1,1) mC(2,0)

So the MCP problem has both properties (see thisand this) of a dynamic programming
problem. Like other typical Dynamic Programming(DP) problems, recomputations of same
subproblems can be avoided by constructing a temporary array tc[][] in bottom up manner.
C++

/* Dynamic Programming implementation of MCP problem */


#include<stdio.h>
#include<limits.h>
#define R 3
#define C 3
  
int min(int x, int y, int z);
  
int minCost(int cost[R][C], int m, int n)
{
     int i, j;
  
     // Instead of following line, we can use int tc[m+1][n+1] or 
     // dynamically allocate memory to save space. The following line is
     // used to keep the program simple and make it working on all compilers.
     int tc[R][C];  
  
     tc[0][0] = cost[0][0];
  
     /* Initialize first column of total cost(tc) array */
     for (i = 1; i <= m; i++)
        tc[i][0] = tc[i-1][0] + cost[i][0];
  
     /* Initialize first row of tc array */
     for (j = 1; j <= n; j++)
        tc[0][j] = tc[0][j-1] + cost[0][j];
  
     /* Construct rest of the tc array */
     for (i = 1; i <= m; i++)

80
Chapter 6. DP-06 | Min Cost Path

        for (j = 1; j <= n; j++)


            tc[i][j] = min(tc[i-1][j-1], 
                           tc[i-1][j], 
                           tc[i][j-1]) + cost[i][j];
  
     return tc[m][n];
}
  
/* A utility function that returns minimum of 3 integers */
int min(int x, int y, int z)
{
   if (x < y)
      return (x < z)? x : z;
   else
      return (y < z)? y : z;
}
  
/* Driver program to test above functions */
int main()
{
   int cost[R][C] = { {1, 2, 3},
                      {4, 8, 2},
                      {1, 5, 3} };
   printf(" %d ", minCost(cost, 2, 2));
   return 0;
}

Java

/* Java program for Dynamic Programming implementation


   of Min Cost Path problem */
import java.util.*;
  
class MinimumCostPath
{
    /* A utility function that returns minimum of 3 integers */
    private static int min(int x, int y, int z)
    {
        if (x < y)
            return (x < z)? x : z;
        else
            return (y < z)? y : z;
    }
  
    private static int minCost(int cost[][], int m, int n)
    {
        int i, j;
        int tc[][]=new int[m+1][n+1];

81
Chapter 6. DP-06 | Min Cost Path

  
        tc[0][0] = cost[0][0];
  
        /* Initialize first column of total cost(tc) array */
        for (i = 1; i <= m; i++)
            tc[i][0] = tc[i-1][0] + cost[i][0];
  
        /* Initialize first row of tc array */
        for (j = 1; j <= n; j++)
            tc[0][j] = tc[0][j-1] + cost[0][j];
  
        /* Construct rest of the tc array */
        for (i = 1; i <= m; i++)
            for (j = 1; j <= n; j++)
                tc[i][j] = min(tc[i-1][j-1], 
                               tc[i-1][j],
                               tc[i][j-1]) + cost[i][j];
  
        return tc[m][n];
    }
  
    /* Driver program to test above functions */
    public static void main(String args[])
    {
        int cost[][]= {{1, 2, 3},
                       {4, 8, 2},
                       {1, 5, 3}};
        System.out.println(minCost(cost,2,2));
    }
}
// This code is contributed by Pankaj Kumar

Python

# Dynamic Programming Python implementation of Min Cost Path


# problem
R = 3
C = 3
  
def minCost(cost, m, n):
  
    # Instead of following line, we can use int tc[m+1][n+1] or
    # dynamically allocate memoery to save space. The following
    # line is used to keep te program simple and make it working
    # on all compilers.
    tc = [[0 for x in range(C)] for x in range(R)]
  
    tc[0][0] = cost[0][0]

82
Chapter 6. DP-06 | Min Cost Path

  
    # Initialize first column of total cost(tc) array
    for i in range(1, m+1):
        tc[i][0] = tc[i-1][0] + cost[i][0]
  
    # Initialize first row of tc array
    for j in range(1, n+1):
        tc[0][j] = tc[0][j-1] + cost[0][j]
  
    # Construct rest of the tc array
    for i in range(1, m+1):
        for j in range(1, n+1):
            tc[i][j] = min(tc[i-1][j-1], tc[i-1][j], tc[i][j-1]) + cost[i][j]
  
    return tc[m][n]
  
# Driver program to test above functions
cost = [[1, 2, 3],
        [4, 8, 2],
        [1, 5, 3]]
print(minCost(cost, 2, 2))
  
# This code is contributed by Bhavya Jain

C#

// C# program for Dynamic Programming implementation


// of Min Cost Path problem 
using System;
  
class GFG
{
    // A utility function that 
    // returns minimum of 3 integers 
    private static int min(int x, int y, int z)
    {
        if (x < y)
            return (x < z)? x : z;
        else
            return (y < z)? y : z;
    }
  
    private static int minCost(int [,]cost, int m, int n)
    {
        int i, j;
        int [,]tc=new int[m+1,n+1];
  
        tc[0,0] = cost[0,0];

83
Chapter 6. DP-06 | Min Cost Path

  
        /* Initialize first column of total cost(tc) array */
        for (i = 1; i <= m; i++)
            tc[i, 0] = tc[i - 1, 0] + cost[i, 0];
  
        /* Initialize first row of tc array */
        for (j = 1; j <= n; j++)
            tc[0, j] = tc[0, j - 1] + cost[0, j];
  
        /* Construct rest of the tc array */
        for (i = 1; i <= m; i++)
            for (j = 1; j <= n; j++)
                tc[i, j] = min(tc[i - 1, j - 1], 
                            tc[i - 1, j],
                            tc[i, j - 1]) + cost[i, j];
  
        return tc[m, n];
    }
  
    // Driver program 
    public static void Main()
    {
        int [,]cost= {{1, 2, 3},
                    {4, 8, 2},
                    {1, 5, 3}};
        Console.Write(minCost(cost,2,2));
    }
}
  
// This code is contributed by Sam007.

PHP

<?php
// DP implementation
// of MCP problem 
$R = 3;
$C = 3;
  
function minCost($cost, $m, $n)
{
    global $R;
    global $C;
    // Instead of following line, 
    // we can use int tc[m+1][n+1] 
    // or dynamically allocate 
    // memory to save space. The 
    // following line is used to keep 

84
Chapter 6. DP-06 | Min Cost Path

    // the program simple and make


    // it working on all compilers.
    $tc;
    for ($i = 0; $i <= $R; $i++)
    for ($j = 0; $j <= $C; $j++)
    $tc[$i][$j] = 0; 
  
    $tc[0][0] = $cost[0][0];
  
    /* Initialize first column of
       total cost(tc) array */
    for ($i = 1; $i <= $m; $i++)
        $tc[$i][0] = $tc[$i - 1][0] + 
                     $cost[$i][0];
  
    /* Initialize first 
       row of tc array */
    for ($j = 1; $j <= $n; $j++)
        $tc[0][$j] = $tc[0][$j - 1] + 
                     $cost[0][$j];
  
    /* Construct rest of
       the tc array */
    for ($i = 1; $i <= $m; $i++)
        for ($j = 1; $j <= $n; $j++)
          
            // returns minimum of 3 integers 
            $tc[$i][$j] = min($tc[$i - 1][$j - 1], 
                              $tc[$i - 1][$j], 
                              $tc[$i][$j - 1]) +
                              $cost[$i][$j];
  
    return $tc[$m][$n];
}
  
  
// Driver Code
$cost = array(array(1, 2, 3),
              array(4, 8, 2),
              array(1, 5, 3));
echo minCost($cost, 2, 2);
  
// This code is contributed by mits
?>

Output:

85
Chapter 6. DP-06 | Min Cost Path

Time Complexity of the DP implementation is O(mn) which is much better than Naive
Recursive implementation.
Improved By : Sam007, Mithun Kumar, shiv_bhakt, maveriek

Source

https://www.geeksforgeeks.org/min-cost-path-dp-6/

86
Chapter 7

DP-07 | Coin Change

Coin Change | DP-7 - GeeksforGeeks


Given a value N, if we want to make change for N cents, and we have infinite supply of each
of S = { S1, S2, .. , Sm} valued coins, how many ways can we make the change? The order
of coins doesn’t matter.
For example, for N = 4 and S = {1,2,3}, there are four solutions: {1,1,1,1},{1,1,2},{2,2},{1,3}.
So output should be 4. For N = 10 and S = {2, 5, 3, 6}, there are five solutions: {2,2,2,2,2},
{2,2,3,3}, {2,2,6}, {2,3,5} and {5,5}. So the output should be 5.
1) Optimal Substructure
To count the total number of solutions, we can divide all set solutions into two sets.
1) Solutions that do not contain mth coin (or Sm).
2) Solutions that contain at least one Sm.
Let count(S[], m, n) be the function to count the number of solutions, then it can be written
as sum of count(S[], m-1, n) and count(S[], m, n-Sm).
Therefore, the problem has optimal substructure property as the problem can be solved
using solutions to subproblems.
2) Overlapping Subproblems
Following is a simple recursive implementation of the Coin Change problem. The implemen-
tation simply follows the recursive structure mentioned above.
C++

// Recursive C program for


// coin change problem.
#include<stdio.h>
  
// Returns the count of ways we can 
// sum S[0...m-1] coins to get sum n
int count( int S[], int m, int n )
{

87
Chapter 7. DP-07 | Coin Change

    // If n is 0 then there is 1 solution 


    // (do not include any coin)
    if (n == 0)
        return 1;
      
    // If n is less than 0 then no 
    // solution exists
    if (n < 0)
        return 0;
  
    // If there are no coins and n 
    // is greater than 0, then no
    // solution exist
    if (m <=0 && n >= 1)
        return 0;
  
    // count is sum of solutions (i) 
    // including S[m-1] (ii) excluding S[m-1]
    return count( S, m - 1, n ) + count( S, m, n-S[m-1] );
}
  
// Driver program to test above function
int main()
{
    int i, j;
    int arr[] = {1, 2, 3};
    int m = sizeof(arr)/sizeof(arr[0]);
    printf("%d ", count(arr, m, 4));
    getchar();
    return 0;
}

Java

// Recursive java program for


// coin change problem.
import java.io.*;
  
class GFG {
      
    // Returns the count of ways we can 
    // sum S[0...m-1] coins to get sum n
    static int count( int S[], int m, int n )
    {
        // If n is 0 then there is 1 solution 
        // (do not include any coin)
        if (n == 0)
            return 1;

88
Chapter 7. DP-07 | Coin Change

          
        // If n is less than 0 then no 
        // solution exists
        if (n < 0)
            return 0;
      
        // If there are no coins and n 
        // is greater than 0, then no
        // solution exist
        if (m <=0 && n >= 1)
            return 0;
      
        // count is sum of solutions (i) 
        // including S[m-1] (ii) excluding S[m-1]
        return count( S, m - 1, n ) +
               count( S, m, n-S[m-1] );
    }
      
    // Driver program to test above function
    public static void main(String[] args)
    {
        int i, j;
        int arr[] = {1, 2, 3};
        int m = arr.length;
        System.out.println( count(arr, m, 4));
          
          
    }
  
}
  
// This article is contributed by vt_m.

Python3

# Recursive Python3 program for


# coin change problem.
  
# Returns the count of ways we can sum
# S[0...m-1] coins to get sum n
def count(S, m, n ):
  
    # If n is 0 then there is 1
    # solution (do not include any coin)
    if (n == 0):
        return 1
  
    # If n is less than 0 then no

89
Chapter 7. DP-07 | Coin Change

    # solution exists


    if (n < 0):
        return 0;
  
    # If there are no coins and n
    # is greater than 0, then no
    # solution exist
    if (m <=0 and n >= 1):
        return 0
  
    # count is sum of solutions (i) 
    # including S[m-1] (ii) excluding S[m-1]
    return count( S, m - 1, n ) + count( S, m, n-S[m-1] );
  
# Driver program to test above function
arr = [1, 2, 3]
m = len(arr)
print(count(arr, m, 4))
  
# This code is contributed by Smitha Dinesh Semwal

C#

// Recursive C# program for


// coin change problem.
using System;
  
class GFG
{
    // Returns the count of ways we can 
    // sum S[0...m-1] coins to get sum n
    static int count( int []S, int m, int n )
    {
        // If n is 0 then there is 1 solution 
        // (do not include any coin)
        if (n == 0)
            return 1;
          
        // If n is less than 0 then no 
        // solution exists
        if (n < 0)
            return 0;
      
        // If there are no coins and n 
        // is greater than 0, then no
        // solution exist
        if (m <=0 && n >= 1)
            return 0;

90
Chapter 7. DP-07 | Coin Change

      
        // count is sum of solutions (i) 
        // including S[m-1] (ii) excluding S[m-1]
        return count( S, m - 1, n ) +
            count( S, m, n - S[m - 1] );
    }
      
    // Driver program
    public static void Main()
    {
          
        int []arr = {1, 2, 3};
        int m = arr.Length;
        Console.Write( count(arr, m, 4));
          
          
    }
}
// This code is contributed by Sam007

PHP

<?php
// Recursive PHP program for
// coin change problem.
  
// Returns the count of ways we can 
// sum S[0...m-1] coins to get sum n
function coun($S, $m, $n)
{
      
    // If n is 0 then there is 
    // 1 solution (do not include
    // any coin)
    if ($n == 0)
        return 1;
      
    // If n is less than 0 then no 
    // solution exists
    if ($n < 0)
        return 0;
  
    // If there are no coins and n 
    // is greater than 0, then no
    // solution exist
    if ($m <= 0 && $n >= 1)
        return 0;
  

91
Chapter 7. DP-07 | Coin Change

    // count is sum of solutions (i) 


    // including S[m-1] (ii) excluding S[m-1]
    return coun($S, $m - 1,$n ) + 
           coun($S, $m, $n - $S[$m - 1] );
}
  
    // Driver Code
    $arr = array(1, 2, 3);
    $m = count($arr);
    echo coun($arr, $m, 4); 
      
// This code is contributed by Sam007
?>

Output :

It should be noted that the above function computes the same subproblems again and again.
See the following recursion tree for S = {1, 2, 3} and n = 5.
The function C({1}, 3) is called two times. If we draw the complete tree, then we can see
that there are many subproblems being called more than once.

C() --> count()


C({1,2,3}, 5)
/ \
/ \
C({1,2,3}, 2) C({1,2}, 5)
/ \ / \
/ \ / \
C({1,2,3}, -1) C({1,2}, 2) C({1,2}, 3) C({1}, 5)
/ \ / \ / \
/ \ / \ / \
C({1,2},0) C({1},2) C({1,2},1) C({1},3) C({1}, 4) C({}, 5)
/ \ / \ /\ / \
/ \ / \ / \ / \
. . . . . . C({1}, 3) C({}, 4)
/ \
/ \
. .

Since same suproblems are called again, this problem has Overlapping Subprolems property.
So the Coin Change problem has both properties (see thisand this) of a dynamic program-
ming problem. Like other typical Dynamic Programming(DP) problems, recomputations of

92
Chapter 7. DP-07 | Coin Change

same subproblems can be avoided by constructing a temporary array table[][] in bottom up


manner.
Dynamic Programming Solution

// C program for coin change problem.


#include<stdio.h>
  
int count( int S[], int m, int n )
{
    int i, j, x, y;
  
    // We need n+1 rows as the table is constructed 
    // in bottom up manner using the base case 0
    // value case (n = 0)
    int table[n+1][m];
     
    // Fill the enteries for 0 value case (n = 0)
    for (i=0; i<m; i++)
        table[0][i] = 1;
  
    // Fill rest of the table entries in bottom 
    // up manner  
    for (i = 1; i < n+1; i++)
    {
        for (j = 0; j < m; j++)
        {
            // Count of solutions including S[j]
            x = (i-S[j] >= 0)? table[i - S[j]][j]: 0;
  
            // Count of solutions excluding S[j]
            y = (j >= 1)? table[i][j-1]: 0;
  
            // total count
            table[i][j] = x + y;
        }
    }
    return table[n][m-1];
}
  
// Driver program to test above function
int main()
{
    int arr[] = {1, 2, 3};
    int m = sizeof(arr)/sizeof(arr[0]);
    int n = 4;

93
Chapter 7. DP-07 | Coin Change

    printf(" %d ", count(arr, m, n));


    return 0;
}

Java

/* Dynamic Programming Java implementation of Coin


   Change problem */
import java.util.Arrays;
  
class CoinChange
{
    static long countWays(int S[], int m, int n)
    {
        //Time complexity of this function: O(mn)
        //Space Complexity of this function: O(n)
  
        // table[i] will be storing the number of solutions
        // for value i. We need n+1 rows as the table is
        // constructed in bottom up manner using the base
        // case (n = 0)
        long[] table = new long[n+1];
  
        // Initialize all table values as 0
        Arrays.fill(table, 0);   //O(n)
  
        // Base case (If given value is 0)
        table[0] = 1;
  
        // Pick all coins one by one and update the table[]
        // values after the index greater than or equal to
        // the value of the picked coin
        for (int i=0; i<m; i++)
            for (int j=S[i]; j<=n; j++)
                table[j] += table[j-S[i]];
  
        return table[n];
    }
  
    // Driver Function to test above function
    public static void main(String args[])
    {
        int arr[] = {1, 2, 3};
        int m = arr.length;
        int n = 4;
        System.out.println(countWays(arr, m, n));
    }
}

94
Chapter 7. DP-07 | Coin Change

// This code is contributed by Pankaj Kumar

Python

# Dynamic Programming Python implementation of Coin 


# Change problem
def count(S, m, n):
    # We need n+1 rows as the table is constructed 
    # in bottom up manner using the base case 0 value
    # case (n = 0)
    table = [[0 for x in range(m)] for x in range(n+1)]
  
    # Fill the entries for 0 value case (n = 0)
    for i in range(m):
        table[0][i] = 1
  
    # Fill rest of the table entries in bottom up manner
    for i in range(1, n+1):
        for j in range(m):
  
            # Count of solutions including S[j]
            x = table[i - S[j]][j] if i-S[j] >= 0 else 0
  
            # Count of solutions excluding S[j]
            y = table[i][j-1] if j >= 1 else 0
  
            # total count
            table[i][j] = x + y
  
    return table[n][m-1]
  
# Driver program to test above function
arr = [1, 2, 3]
m = len(arr)
n = 4
print(count(arr, m, n))
  
# This code is contributed by Bhavya Jain

C#

/* Dynamic Programming C# implementation of Coin


Change problem */
using System;
  
class GFG
{

95
Chapter 7. DP-07 | Coin Change

    static long countWays(int []S, int m, int n)


    {
        //Time complexity of this function: O(mn)
        //Space Complexity of this function: O(n)
  
        // table[i] will be storing the number of solutions
        // for value i. We need n+1 rows as the table is
        // constructed in bottom up manner using the base
        // case (n = 0)
        int[] table = new int[n+1];
  
        // Initialize all table values as 0
        for(int i = 0; i < table.Length; i++) 
        {
            table[i] = 0;
        }
  
        // Base case (If given value is 0)
        table[0] = 1;
  
        // Pick all coins one by one and update the table[]
        // values after the index greater than or equal to
        // the value of the picked coin
        for (int i = 0; i < m; i++)
            for (int j = S[i]; j <= n; j++)
                table[j] += table[j - S[i]];
  
        return table[n];
    }
  
    // Driver Function
    public static void Main()
    {
        int []arr = {1, 2, 3};
        int m = arr.Length;
        int n = 4;
        Console.Write(countWays(arr, m, n));
    }
}
// This code is contributed by Sam007

PHP

<?php
// PHP program for 
// coin change problem.
  
function count1($S, $m, $n)

96
Chapter 7. DP-07 | Coin Change

{
    // We need n+1 rows as 
    // the table is constructed 
    // in bottom up manner 
    // using the base case 0
    // value case (n = 0)
    $table;
    for ($i = 0; $i < $n + 1; $i++)
    for ($j = 0; $j < $m; $j++)
        $table[$i][$j] = 0;
      
    // Fill the enteries for
    // 0 value case (n = 0)
    for ($i = 0; $i < $m; $i++)
        $table[0][$i] = 1;
  
    // Fill rest of the table 
    // entries in bottom up manner 
    for ($i = 1; $i < $n + 1; $i++)
    {
        for ($j = 0; $j < $m; $j++)
        {
            // Count of solutions
            // including S[j]
            $x = ($i-$S[$j] >= 0) ? 
                  $table[$i - $S[$j]][$j] : 0;
  
            // Count of solutions
            // excluding S[j]
            $y = ($j >= 1) ? 
                  $table[$i][$j - 1] : 0;
  
            // total count
            $table[$i][$j] = $x + $y;
        }
    }
    return $table[$n][$m-1];
}
  
// Driver Code
$arr = array(1, 2, 3);
$m = count($arr);
$n = 4;
echo count1($arr, $m, $n);
  
// This code is contributed by mits
?>

97
Chapter 7. DP-07 | Coin Change

Output:

Time Complexity: O(mn)


Following is a simplified version of method 2. The auxiliary space required here is O(n) only.

int count( int S[], int m, int n )


{
    // table[i] will be storing the number of solutions for
    // value i. We need n+1 rows as the table is constructed
    // in bottom up manner using the base case (n = 0)
    int table[n+1];
  
    // Initialize all table values as 0
    memset(table, 0, sizeof(table));
  
    // Base case (If given value is 0)
    table[0] = 1;
  
    // Pick all coins one by one and update the table[] values
    // after the index greater than or equal to the value of the
    // picked coin
    for(int i=0; i<m; i++)
        for(int j=S[i]; j<=n; j++)
            table[j] += table[j-S[i]];
  
    return table[n];
}

Java

public static int count( int S[], int m, int n )


{
    // table[i] will be storing the number of solutions for
    // value i. We need n+1 rows as the table is constructed
    // in bottom up manner using the base case (n = 0)
    int table[]=new int[n+1];
  
    // Base case (If given value is 0)
    table[0] = 1;
  
    // Pick all coins one by one and update the table[] values
    // after the index greater than or equal to the value of the

98
Chapter 7. DP-07 | Coin Change

    // picked coin


    for(int i=0; i<m; i++)
        for(int j=S[i]; j<=n; j++)
            table[j] += table[j-S[i]];
  
    return table[n];
}

Python

# Dynamic Programming Python implementation of Coin 


# Change problem
def count(S, m, n):
  
    # table[i] will be storing the number of solutions for
    # value i. We need n+1 rows as the table is constructed
    # in bottom up manner using the base case (n = 0)
    # Initialize all table values as 0
    table = [0 for k in range(n+1)]
  
    # Base case (If given value is 0)
    table[0] = 1
  
    # Pick all coins one by one and update the table[] values
    # after the index greater than or equal to the value of the
    # picked coin
    for i in range(0,m):
        for j in range(S[i],n+1):
            table[j] += table[j-S[i]]
  
    return table[n]
  
# Driver program to test above function
arr = [1, 2, 3]
m = len(arr)
n = 4
x = count(arr, m, n)
print (x)
  
# This code is contributed by Afzal Ansari

Thanks to Rohan Laishram for suggesting this space optimized version.


References:
http://www.algorithmist.com/index.php/Coin_Change
Improved By : Sam007, khyatigrover, Mithun Kumar

99
Chapter 7. DP-07 | Coin Change

Source

https://www.geeksforgeeks.org/coin-change-dp-7/

100
Chapter 8

DP-08 | Matrix Chain


Multiplication

Matrix Chain Multiplication | DP-8 - GeeksforGeeks


Given a sequence of matrices, find the most efficient way to multiply these matrices together.
The problem is not actually to perform the multiplications, but merely to decide in which
order to perform the multiplications.
We have many options to multiply a chain of matrices because matrix multiplication is
associative. In other words, no matter how we parenthesize the product, the result will be
the same. For example, if we had four matrices A, B, C, and D, we would have:

(ABC)D = (AB)(CD) = A(BCD) = ....

However, the order in which we parenthesize the product affects the number of simple arith-
metic operations needed to compute the product, or the efficiency. For example, suppose A
is a 10 × 30 matrix, B is a 30 × 5 matrix, and C is a 5 × 60 matrix. Then,

(AB)C = (10×30×5) + (10×5×60) = 1500 + 3000 = 4500 operations


A(BC) = (30×5×60) + (10×30×60) = 9000 + 18000 = 27000 operations.

Clearly the first parenthesization requires less number of operations.


Given an array p[] which represents the chain of matrices such that the ith matrix Ai is of
dimension p[i-1] x p[i]. We need to write a function MatrixChainOrder() that should return
the minimum number of multiplications needed to multiply the chain.

Input: p[] = {40, 20, 30, 10, 30}


Output: 26000
There are 4 matrices of dimensions 40x20, 20x30, 30x10 and 10x30.
Let the input 4 matrices be A, B, C and D. The minimum number of

101
Chapter 8. DP-08 | Matrix Chain Multiplication

multiplications are obtained by putting parenthesis in following way


(A(BC))D --> 20*30*10 + 40*20*10 + 40*10*30

Input: p[] = {10, 20, 30, 40, 30}


Output: 30000
There are 4 matrices of dimensions 10x20, 20x30, 30x40 and 40x30.
Let the input 4 matrices be A, B, C and D. The minimum number of
multiplications are obtained by putting parenthesis in following way
((AB)C)D --> 10*20*30 + 10*30*40 + 10*40*30

Input: p[] = {10, 20, 30}


Output: 6000
There are only two matrices of dimensions 10x20 and 20x30. So there
is only one way to multiply the matrices, cost of which is 10*20*30

1) Optimal Substructure:
A simple solution is to place parenthesis at all possible places, calculate the cost for each
placement and return the minimum value. In a chain of matrices of size n, we can place
the first set of parenthesis in n-1 ways. For example, if the given chain is of 4 matrices.
let the chain be ABCD, then there are 3 ways to place first set of parenthesis outer side:
(A)(BCD), (AB)(CD) and (ABC)(D). So when we place a set of parenthesis, we divide the
problem into subproblems of smaller size. Therefore, the problem has optimal substructure
property and can be easily solved using recursion.
Minimum number of multiplication needed to multiply a chain of size n = Minimum of all
n-1 placements (these placements create subproblems of smaller size)
2) Overlapping Subproblems
Following is a recursive implementation that simply follows the above optimal substructure
property.

/* A naive recursive implementation that simply


  follows the above optimal substructure property */
#include<stdio.h>
#include<limits.h>
  
// Matrix Ai has dimension p[i-1] x p[i] for i = 1..n
int MatrixChainOrder(int p[], int i, int j)
{
    if(i == j)
        return 0;
    int k;
    int min = INT_MAX;
    int count;
  
    // place parenthesis at different places between first

102
Chapter 8. DP-08 | Matrix Chain Multiplication

    // and last matrix, recursively calculate count of


    // multiplications for each parenthesis placement and
    // return the minimum count
    for (k = i; k <j; k++)
    {
        count = MatrixChainOrder(p, i, k) +
                MatrixChainOrder(p, k+1, j) +
                p[i-1]*p[k]*p[j];
  
        if (count < min)
            min = count;
    }
  
    // Return minimum count
    return min;
}
  
// Driver program to test above function
int main()
{
    int arr[] = {1, 2, 3, 4, 3};
    int n = sizeof(arr)/sizeof(arr[0]);
  
    printf("Minimum number of multiplications is %d ",
                          MatrixChainOrder(arr, 1, n-1));
  
    getchar();
    return 0;
}

Java

/* A naive recursive implementation that simply follows


   the above optimal substructure property */
class MatrixChainMultiplication
{
    // Matrix Ai has dimension p[i-1] x p[i] for i = 1..n
    static int MatrixChainOrder(int p[], int i, int j)
    {
        if (i == j)
            return 0;
  
        int min = Integer.MAX_VALUE;
  
        // place parenthesis at different places between first
        // and last matrix, recursively calculate count of
        // multiplications for each parenthesis placement and
        // return the minimum count

103
Chapter 8. DP-08 | Matrix Chain Multiplication

        for (int k=i; k<j; k++)


        {
            int count = MatrixChainOrder(p, i, k) +
                        MatrixChainOrder(p, k+1, j) +
                        p[i-1]*p[k]*p[j];
  
            if (count < min)
                min = count;
        }
  
        // Return minimum count
        return min;
    }
  
    // Driver program to test above function
    public static void main(String args[])
    {
        int arr[] = new int[] {1, 2, 3, 4, 3};
        int n = arr.length;
  
        System.out.println("Minimum number of multiplications is "+
                           MatrixChainOrder(arr, 1, n-1));
  
    }
}
/* This code is contributed by Rajat Mishra*/

Python3

# A naive recursive implementation that


# simply follows the above optimal 
# substructure property 
import sys
  
# Matrix A[i] has dimension p[i-1] x p[i]
# for i = 1..n
def MatrixChainOrder(p, i, j):
  
    if i == j:
        return 0
  
    _min = sys.maxsize
      
    # place parenthesis at different places 
    # between first and last matrix, 
    # recursively calculate count of
    # multiplications for each parenthesis
    # placement and return the minimum count

104
Chapter 8. DP-08 | Matrix Chain Multiplication

    for k in range(i, j):


      
        count = (MatrixChainOrder(p, i, k) 
             + MatrixChainOrder(p, k+1, j)
                   + p[i-1] * p[k] * p[j])
  
        if count < _min:
            _min = count;
      
  
    # Return minimum count
    return _min;
  
  
# Driver program to test above function
arr = [1, 2, 3, 4, 3];
n = len(arr);
  
print("Minimum number of multiplications is ",
                MatrixChainOrder(arr, 1, n-1));
  
# This code is contributed by Aryan Garg

C#

/* C# code for naive recursive implementation 


that simply follows the above optimal 
substructure property */
using System;
  
class GFG {
      
    // Matrix Ai has dimension p[i-1] x p[i]
    // for i = 1..n
    static int MatrixChainOrder(int[] p, int i, int j)
    {
          
        if (i == j)
            return 0;
  
        int min = int.MaxValue;
  
        // place parenthesis at different places 
        // between first and last matrix, recursively 
        // calculate count of multiplications for each
        // parenthesis placement and return the 
        // minimum count
        for (int k = i; k < j; k++) {

105
Chapter 8. DP-08 | Matrix Chain Multiplication

            int count = MatrixChainOrder(p, i, k) +


            MatrixChainOrder(p, k + 1, j) + p[i - 1] 
                                       * p[k] * p[j];
  
            if (count < min)
                min = count;
        }
  
        // Return minimum count
        return min;
    }
  
    // Driver program to test above function
    public static void Main()
    {
        int[] arr = new int[]{ 1, 2, 3, 4, 3 };
        int n = arr.Length;
  
        Console.Write("Minimum number of multiplications is "
                          + MatrixChainOrder(arr, 1, n - 1));
    }
}
  
// This code is contributed by Sam007.

Time complexity of the above naive recursive approach is exponential. It should be noted
that the above function computes the same subproblems again and again. See the following
recursion tree for a matrix chain of size 4. The function MatrixChainOrder(p, 3, 4) is called
two times. We can see that there are many subproblems being called more than once.

106
Chapter 8. DP-08 | Matrix Chain Multiplication

Since same suproblems are called again, this problem has Overlapping Subprolems property.
So Matrix Chain Multiplication problem has both properties (see thisand this) of a dynamic
programming problem. Like other typical Dynamic Programming(DP) problems, recompu-
tations of same subproblems can be avoided by constructing a temporary array m[][] in
bottom up manner.
Dynamic Programming Solution
Following is C/C++ implementation for Matrix Chain Multiplication problem using
Dynamic Programming.

// See the Cormen book for details of the following algorithm


#include<stdio.h>
#include<limits.h>
  
// Matrix Ai has dimension p[i-1] x p[i] for i = 1..n
int MatrixChainOrder(int p[], int n)
{
  
    /* For simplicity of the program, one extra row and one
       extra column are allocated in m[][].  0th row and 0th
       column of m[][] are not used */
    int m[n][n];
  
    int i, j, k, L, q;
  
    /* m[i,j] = Minimum number of scalar multiplications needed
       to compute the matrix A[i]A[i+1]...A[j] = A[i..j] where
       dimension of A[i] is p[i-1] x p[i] */
  
    // cost is zero when multiplying one matrix.
    for (i=1; i<n; i++)
        m[i][i] = 0;
  
    // L is chain length.
    for (L=2; L<n; L++)
    {
        for (i=1; i<n-L+1; i++)
        {
            j = i+L-1;
            m[i][j] = INT_MAX;
            for (k=i; k<=j-1; k++)
            {
                // q = cost/scalar multiplications
                q = m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j];
                if (q < m[i][j])
                    m[i][j] = q;

107
Chapter 8. DP-08 | Matrix Chain Multiplication

            }
        }
    }
  
    return m[1][n-1];
}
  
int main()
{
    int arr[] = {1, 2, 3, 4};
    int size = sizeof(arr)/sizeof(arr[0]);
  
    printf("Minimum number of multiplications is %d ",
                       MatrixChainOrder(arr, size));
  
    getchar();
    return 0;
}

Java

// Dynamic Programming Python implementation of Matrix


// Chain Multiplication.
// See the Cormen book for details of the following algorithm
class MatrixChainMultiplication
{
    // Matrix Ai has dimension p[i-1] x p[i] for i = 1..n
    static int MatrixChainOrder(int p[], int n)
    {
        /* For simplicity of the program, one extra row and one
        extra column are allocated in m[][].  0th row and 0th
        column of m[][] are not used */
        int m[][] = new int[n][n];
  
        int i, j, k, L, q;
  
        /* m[i,j] = Minimum number of scalar multiplications needed
        to compute the matrix A[i]A[i+1]...A[j] = A[i..j] where
        dimension of A[i] is p[i-1] x p[i] */
  
        // cost is zero when multiplying one matrix.
        for (i = 1; i < n; i++)
            m[i][i] = 0;
  
        // L is chain length.
        for (L=2; L<n; L++)
        {
            for (i=1; i<n-L+1; i++)

108
Chapter 8. DP-08 | Matrix Chain Multiplication

            {
                j = i+L-1;
                if(j == n) continue;
                m[i][j] = Integer.MAX_VALUE;
                for (k=i; k<=j-1; k++)
                {
                    // q = cost/scalar multiplications
                    q = m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j];
                    if (q < m[i][j])
                        m[i][j] = q;
                }
            }
        }
  
        return m[1][n-1];
    }
  
    // Driver program to test above function
    public static void main(String args[])
    {
        int arr[] = new int[] {1, 2, 3, 4};
        int size = arr.length;
  
        System.out.println("Minimum number of multiplications is "+
                           MatrixChainOrder(arr, size));
    }
}
/* This code is contributed by Rajat Mishra*/

Python

# Dynamic Programming Python implementation of Matrix


# Chain Multiplication. See the Cormen book for details
# of the following algorithm
import sys
  
# Matrix Ai has dimension p[i-1] x p[i] for i = 1..n
def MatrixChainOrder(p, n):
    # For simplicity of the program, one extra row and one
    # extra column are allocated in m[][].  0th row and 0th
    # column of m[][] are not used
    m = [[0 for x in range(n)] for x in range(n)]
  
    # m[i,j] = Minimum number of scalar multiplications needed
    # to compute the matrix A[i]A[i+1]...A[j] = A[i..j] where
    # dimension of A[i] is p[i-1] x p[i]
  
    # cost is zero when multiplying one matrix.

109
Chapter 8. DP-08 | Matrix Chain Multiplication

    for i in range(1, n):


        m[i][i] = 0
  
    # L is chain length.
    for L in range(2, n):
        for i in range(1, n-L+1):
            j = i+L-1
            m[i][j] = sys.maxint
            for k in range(i, j):
  
                # q = cost/scalar multiplications
                q = m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j]
                if q < m[i][j]:
                    m[i][j] = q
  
    return m[1][n-1]
  
# Driver program to test above function
arr = [1, 2, 3 ,4]
size = len(arr)
  
print("Minimum number of multiplications is " +
       str(MatrixChainOrder(arr, size)))
# This Code is contributed by Bhavya Jain

C#

// Dynamic Programming C# implementation of 


// Matrix Chain Multiplication.
// See the Cormen book for details of the 
// following algorithm
using System;
  
class GFG
{
      
    // Matrix Ai has dimension p[i-1] x p[i] 
    // for i = 1..n
    static int MatrixChainOrder(int []p, int n)
    {
          
        /* For simplicity of the program, one 
        extra row and one extra column are 
        allocated in m[][]. 0th row and 0th
        column of m[][] are not used */
        int [ , ]m = new int[n, n];
  
        int i, j, k, L, q;

110
Chapter 8. DP-08 | Matrix Chain Multiplication

  
        /* m[i,j] = Minimum number of scalar 
        multiplications needed
        to compute the matrix A[i]A[i+1]...A[j]
        = A[i..j] where dimension of A[i] is 
        p[i-1] x p[i] */
  
        // cost is zero when multiplying 
        // one matrix.
        for (i = 1; i < n; i++)
            m[i, i] = 0;
  
        // L is chain length.
        for (L = 2; L < n; L++)
        {
            for (i = 1; i < n-L+1; i++)
            {
                j = i+L-1;
                if(j == n) continue;
                m[i, j] = int.MaxValue;
                for (k = i; k <= j-1; k++)
                {
                    // q = cost/scalar multiplications
                    q = m[i, k] + m[k+1, j] + 
                                     p[i-1]*p[k]*p[j];
                    if (q < m[i, j])
                        m[i, j] = q;
                }
            }
        }
  
        return m[1, n-1];
    }
  
    // Driver program to test above function
    public static void Main()
    {
        int []arr = new int[] {1, 2, 3, 4};
        int size = arr.Length;
  
        Console.Write("Minimum number of " + 
                             "multiplications is "+
                        MatrixChainOrder(arr, size));
    }
}
  
// This code is contributed by Sam007

111
Chapter 8. DP-08 | Matrix Chain Multiplication

Output:

Minimum number of multiplications is 18

Time Complexity: O(n^3)


Auxiliary Space: O(n^2)
Printing brackets in Matrix Chain Multiplication Problem
Applications:
Minimum and Maximum values of an expression with * and +
References:
http://en.wikipedia.org/wiki/Matrix_chain_multiplication
http://www.personal.kent.edu/~rmuhamma/Algorithms/MyAlgorithms/Dynamic/
chainMatrixMult.htm
Improved By : aryan21

Source

https://www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/

112
Chapter 9

DP-09 | Binomial Coefficient

Binomial Coefficient | DP-9 - GeeksforGeeks


Following are common definition of Binomial Coefficients.

1. A binomial coefficient C(n, k) can be defined as the coefficient of X^k in the expansion
of (1 + X)^n.
2. A binomial coefficient C(n, k) also gives the number of ways, disregarding order, that
k objects can be chosen from among n objects; more formally, the number of k-element
subsets (or k-combinations) of an n-element set.

The Problem
Write a function that takes two parameters n and k and returns the value of Binomial
Coefficient C(n, k). For example, your function should return 6 for n = 4 and k = 2, and it
should return 10 for n = 5 and k = 2.
1) Optimal Substructure
The value of C(n, k) can be recursively calculated using following standard formula for
Binomial Coefficients.

C(n, k) = C(n-1, k-1) + C(n-1, k)


C(n, 0) = C(n, n) = 1

Following is a simple recursive implementation that simply follows the recursive structure
mentioned above.
C/C++

// A Naive Recursive Implementation


#include<stdio.h>
  
// Returns value of Binomial Coefficient C(n, k)
int binomialCoeff(int n, int k)

113
Chapter 9. DP-09 | Binomial Coefficient

{
  // Base Cases
  if (k==0 || k==n)
    return 1;
  
  // Recur
  return  binomialCoeff(n-1, k-1) + binomialCoeff(n-1, k);
}
  
/* Driver program to test above function*/
int main()
{
    int n = 5, k = 2;
    printf("Value of C(%d, %d) is %d ", n, k, binomialCoeff(n, k));
    return 0;
}

Java

// JAVA Code for Dynamic Programming |


// Set 9 (Binomial Coefficient)
import java.util.*;
  
class GFG {
      
    // Returns value of Binomial 
    // Coefficient C(n, k)
    static int binomialCoeff(int n, int k) 
    {
      
        // Base Cases
        if (k == 0 || k == n)
            return 1;
          
        // Recur
        return binomialCoeff(n - 1, k - 1) + 
                    binomialCoeff(n - 1, k);
    }
      
    /* Driver program to test above function */
    public static void main(String[] args) 
   {
        int n = 5, k = 2;
        System.out.printf("Value of C(%d, %d) is %d ",
                        n, k, binomialCoeff(n, k));
    }
}
  

114
Chapter 9. DP-09 | Binomial Coefficient

// This code is contributed by Arnav Kr. Mandal.

Python

# A naive recursive Python implementation


  
def binomialCoeff(n , k):
  
    if k==0 or k ==n :
        return 1
  
    # Recursive Call
    return binomialCoeff(n-1 , k-1) + binomialCoeff(n-1 , k)
  
# Driver Program to test ht above function
n = 5
k = 2
print "Value of C(%d,%d) is (%d)" %(n , k , binomialCoeff(n , k))
  
# This code is contributed by Nikhil Kumar Singh (nickzuck_007)

C#

// C# Code for Dynamic Programming |


// Set 9 (Binomial Coefficient)
using System;
  
class GFG {
      
    // Returns value of Binomial 
    // Coefficient C(n, k)
    static int binomialCoeff(int n, int k) 
    {
          
        // Base Cases
        if (k == 0 || k == n)
            return 1;
          
        // Recur
        return binomialCoeff(n - 1, k - 1) + 
                    binomialCoeff(n - 1, k);
    }
      
    /* Driver program to test above function */
    public static void Main() 
    {
        int n = 5, k = 2;

115
Chapter 9. DP-09 | Binomial Coefficient

        Console.Write("Value of C(" + n + "," 


                            + k + ") is " +
                        binomialCoeff(n, k));
    }
}
  
// This code is contributed by Sam007.

PHP

<?php
// PHP Code for Dynamic Programming |
// Set 9 (Binomial Coefficient)
  
// Returns value of 
// Binomial Coefficient C(n, k)
function binomialCoeff($n, $k)
{
    // Base Cases
    if ($k==0 || $k==$n)
        return 1;
      
    // Recur
    return binomialCoeff($n - 1, $k - 1) + 
               binomialCoeff($n - 1, $k);
}
  
    // Driver Code
    $n = 5; 
    $k = 2;
    echo "Value of C","(",$n ,$k,") is "
               , binomialCoeff($n, $k);
  
// This code is contributed by aj_36
?>

Output:

Value of C(52) is 10

2) Overlapping Subproblems
It should be noted that the above function computes the same subproblems again and again.
See the following recursion tree for n = 5 an k = 2. The function C(3, 1) is called two times.
For large values of n, there will be many common subproblems.

C(5, 2)

116
Chapter 9. DP-09 | Binomial Coefficient

/ \
C(4, 1) C(4, 2)
/ \ / \
C(3, 0) C(3, 1) C(3, 1) C(3, 2)
/ \ / \ / \
C(2, 0) C(2, 1) C(2, 0) C(2, 1) C(2, 1) C(2, 2)
/ \ / \ / \
C(1, 0) C(1, 1) C(1, 0) C(1, 1) C(1, 0) C(1, 1)

Since same suproblems are called again, this problem has Overlapping Subproblems prop-
erty. So the Binomial Coefficient problem has both properties (see thisand this) of a dy-
namic programming problem. Like other typical Dynamic Programming(DP) problems,
re-computations of same subproblems can be avoided by constructing a temporary array
C[][] in bottom up manner. Following is Dynamic Programming based implementation.
C

// A Dynamic Programming based solution that uses table C[][] to


// calculate the Binomial Coefficient
#include<stdio.h>
  
// Prototype of a utility function that returns minimum of two integers
int min(int a, int b);
  
// Returns value of Binomial Coefficient C(n, k)
int binomialCoeff(int n, int k)
{
    int C[n+1][k+1];
    int i, j;
  
    // Caculate value of Binomial Coefficient in bottom up manner
    for (i = 0; i <= n; i++)
    {
        for (j = 0; j <= min(i, k); j++)
        {
            // Base Cases
            if (j == 0 || j == i)
                C[i][j] = 1;
  
            // Calculate value using previosly stored values
            else
                C[i][j] = C[i-1][j-1] + C[i-1][j];
        }
    }
  
    return C[n][k];
}
  

117
Chapter 9. DP-09 | Binomial Coefficient

// A utility function to return minimum of two integers


int min(int a, int b)
{
    return (a<b)? a: b;
}
  
/* Drier program to test above function*/
int main()
{
    int n = 5, k = 2;
    printf ("Value of C(%d, %d) is %d ", n, k, binomialCoeff(n, k) );
    return 0;
}

Java

// A Dynamic Programming based solution that uses table C[][] to 


// calculate the Binomial Coefficient 
  
class BinomialCoefficient
{
    // Returns value of Binomial Coefficient C(n, k)
    static int binomialCoeff(int n, int k)
    {
    int C[][] = new int[n+1][k+1];
    int i, j;
      
        // Calculate  value of Binomial Coefficient in bottom up manner
    for (i = 0; i <= n; i++)
    {
        for (j = 0; j <= min(i, k); j++)
        {
            // Base Cases
            if (j == 0 || j == i)
                C[i][j] = 1;
       
            // Calculate value using previosly stored values
            else
                C[i][j] = C[i-1][j-1] + C[i-1][j];
          }
     }
       
    return C[n][k];
    }
  
    // A utility function to return minimum of two integers
    static int min(int a, int b)
    {

118
Chapter 9. DP-09 | Binomial Coefficient

    return (a<b)? a: b; 


    }
  
    /* Driver program to test above function*/
    public static void main(String args[])
    {
    int n = 5, k = 2;
    System.out.println("Value of C("+n+","+k+") is "+binomialCoeff(n, k));
    }
}
/*This code is contributed by Rajat Mishra*/

Python

# A Dynamic Programming based Python Program that uses table C[][]


# to calculate the Binomial Coefficient
  
# Returns value of Binomial Coefficient C(n, k)
def binomialCoef(n, k):
    C = [[0 for x in range(k+1)] for x in range(n+1)]
  
    # Calculate value of Binomial Coefficient in bottom up manner
    for i in range(n+1):
        for j in range(min(i, k)+1):
            # Base Cases
            if j == 0 or j == i:
                C[i][j] = 1
  
            # Calculate value using previosly stored values
            else:
                C[i][j] = C[i-1][j-1] + C[i-1][j]
  
    return C[n][k]
  
# Driver program to test above function
n = 5
k = 2
print("Value of C[" + str(n) + "][" + str(k) + "] is "
      + str(binomialCoef(n,k)))
  
# This code is contributed by Bhavya Jain

C#

// A Dynamic Programming based solution that


// uses table C[][] to calculate the Binomial
// Coefficient 

119
Chapter 9. DP-09 | Binomial Coefficient

using System;
  
class GFG {
      
    // Returns value of Binomial Coefficient
    // C(n, k)
    static int binomialCoeff(int n, int k)
    {
        int [,]C = new int[n+1,k+1];
        int i, j;
          
        // Calculate value of Binomial 
        // Coefficient in bottom up manner
        for (i = 0; i <= n; i++)
        {
            for (j = 0; j <= Math.Min(i, k); j++)
            {
                // Base Cases
                if (j == 0 || j == i)
                    C[i,j] = 1;
          
                // Calculate value using previosly
                // stored values
                else
                    C[i,j] = C[i-1,j-1] + C[i-1,j];
            }
        }
          
        return C[n,k];
    }
  
    // A utility function to return minimum
    // of two integers
    static int min(int a, int b)
    {
        return (a < b) ? a : b; 
    }
  
    /* Driver program to test above function*/
    public static void Main()
    {
        int n = 5, k = 2;
        Console.WriteLine("Value of C(" + n
                        + "," + k + ") is "
                    + binomialCoeff(n, k));
    }
}
  

120
Chapter 9. DP-09 | Binomial Coefficient

// This code is contributed by anuj_67.

PHP

<?php
// A Dynamic Programming based 
// solution that uses table C[][] to
// calculate the Binomial Coefficient
  
// Returns value of Binomial 
// Coefficient C(n, k)
function binomialCoeff( $n, $k)
{
    $C = array(array());
    $i; $j;
  
    // Caculate value of Binomial
    // Coefficient in bottom up manner
    for ($i = 0; $i <= $n; $i++)
    {
        for ($j = 0; $j <= min($i, $k); $j++)
        {
              
            // Base Cases
            if ($j == 0 || $j == $i)
                $C[$i][$j] = 1;
  
            // Calculate value using 
            // previosly stored values
            else
                $C[$i][$j] = $C[$i - 1][$j - 1] + 
                                 $C[$i - 1][$j];
        }
    }
  
    return $C[$n][$k];
}
  
    // Driver Code
    $n = 5; 
    $k = 2;
    echo "Value of C(" ,$n," ",$k, ") is"," "
                 , binomialCoeff($n, $k) ;
  
// This code is contributed by anuj_67.
?>

Output:

121
Chapter 9. DP-09 | Binomial Coefficient

Value of C[5][2] is 10

Time Complexity: O(n*k)


Auxiliary Space: O(n*k)
Following is a space optimized version of the above code. The following code only uses
O(k). Thanks to AK for suggesting this method.

C/C++

// C++ program for space optimized Dynamic Programming


// Solution of Binomial Coefficient
#include<bits/stdc++.h>
using namespace std;
  
int binomialCoeff(int n, int k)
{
    int C[k+1];
    memset(C, 0, sizeof(C));
  
    C[0] = 1;  // nC0 is 1
  
    for (int i = 1; i <= n; i++)
    {
        // Compute next row of pascal triangle using
        // the previous row
        for (int j = min(i, k); j > 0; j--)
            C[j] = C[j] + C[j-1];
    }
    return C[k];
}
  
/* Drier program to test above function*/
int main()
{
    int n = 5, k = 2;
    printf ("Value of C(%d, %d) is %d ",
            n, k, binomialCoeff(n, k) );
    return 0;
}

Java

// JAVA Code for Dynamic Programming | 


// Set 9 (Binomial Coefficient)
import java.util.*;
  

122
Chapter 9. DP-09 | Binomial Coefficient

class GFG {
      
    static int binomialCoeff(int n, int k)
    {
        int C[] = new int[k + 1];
         
        // nC0 is 1
        C[0] = 1;  
       
        for (int i = 1; i <= n; i++)
        {
            // Compute next row of pascal 
            // triangle using the previous row
            for (int j = Math.min(i, k); j > 0; j--)
                C[j] = C[j] + C[j-1];
        }
        return C[k];
    }
      
    /* Driver program  */
    public static void main(String[] args) 
    {
         int n = 5, k = 2;
            System.out.printf("Value of C(%d, %d) is %d "
                                , n, k, binomialCoeff(n, k));
    }
}

Python

# Python program for Optimized Dynamic Programming solution to


# Binomail Coefficient. This one uses the concept of pascal
# Triangle and less memory
  
def binomialCoeff(n , k):
  
    # Declaring an empty array
    C = [0 for i in xrange(k+1)]
    C[0] = 1 #since nC0 is 1
  
    for i in range(1,n+1):
  
        # Compute next row of pascal triangle using
        # the previous row
        j = min(i ,k)
        while (j>0):
            C[j] = C[j] + C[j-1]
            j -= 1

123
Chapter 9. DP-09 | Binomial Coefficient

  
    return C[k]
  
# Driver Program to test the above function
n = 5
k = 2
print "Value of C(%d,%d) is %d" %(n,k,binomialCoeff(n,k))
  
# This code is contribtued by Nikhil Kumar Singh(nickzuck_007)

C#

// C# Code for Dynamic Programming | 


// Set 9 (Binomial Coefficient)
using System;
  
class GFG {
      
    static int binomialCoeff(int n, int k)
    {
        int[] C = new int[k + 1];
          
        // nC0 is 1
        C[0] = 1; 
      
        for (int i = 1; i <= n; i++)
        {
            // Compute next row of pascal 
            // triangle using the previous
            // row
            for (int j = Math.Min(i, k);
                              j > 0; j--)
                C[j] = C[j] + C[j-1];
        }
        return C[k];
    }
      
    /* Driver program */
    public static void Main() 
    {
        int n = 5, k = 2;
        Console.WriteLine("Value of C(" 
                + n + " " + k + ") is " 
                + binomialCoeff(n, k));
    }
}
  
// This code is contribtued by anuj_67.

124
Chapter 9. DP-09 | Binomial Coefficient

PHP

<?php
// PHP program for space optimized 
// Dynamic Programming Solution of 
// Binomial Coefficient
function binomialCoeff($n, $k)
{
    $C = array_fill(0, $k + 1, 0);
  
    $C[0] = 1; // nC0 is 1
  
    for ($i = 1; $i <= $n; $i++)
    {
        // Compute next row of pascal 
        // triangle using the previous row
        for ($j = min($i, $k); $j > 0; $j--)
            $C[$j] = $C[$j] + $C[$j - 1];
    }
    return $C[$k];
}
  
// Driver Code
$n = 5; $k = 2;
echo "Value of C[$n, $k] is ". 
        binomialCoeff($n, $k);
      
// This code is contributed by mits.
?>

Output:

Value of C[5][2] is 10

Time Complexity: O(n*k)


Auxiliary Space: O(k)
Explanation:
1==========>> n = 0, C(0,0) = 1
1–1========>> n = 1, C(1,0) = 1, C(1,1) = 1
1–2–1======>> n = 2, C(2,0) = 1, C(2,1) = 2, C(2,2) = 1
1–3–3–1====>> n = 3, C(3,0) = 1, C(3,1) = 3, C(3,2) = 3, C(3,3)=1
1–4–6–4–1==>> n = 4, C(4,0) = 1, C(4,1) = 4, C(4,2) = 6, C(4,3)=4, C(4,4)=1
So here every loop on i, builds i’th row of pascal triangle, using (i-1)th row
At any time, every element of array C will have some value (ZERO or more) and in next
iteration, value for those elements comes from previous iteration.
In statement,

125
Chapter 9. DP-09 | Binomial Coefficient

C[j] = C[j] + C[j-1]


Right hand side represents the value coming from previous iteration (A row of Pascal’s
triangle depends on previous row). Left Hand side represents the value of current iteration
which will be obtained by this statement.

Let's say we want to calculate C(4, 3),


i.e. n=4, k=3:

All elements of array C of size 4 (k+1) are


initialized to ZERO.

i.e. C[0] = C[1] = C[2] = C[3] = C[4] = 0;


Then C[0] is set to 1

For i = 1:
C[1] = C[1] + C[0] = 0 + 1 = 1 ==>> C(1,1) = 1

For i = 2:
C[2] = C[2] + C[1] = 0 + 1 = 1 ==>> C(2,2) = 1
C[1] = C[1] + C[0] = 1 + 1 = 2 ==>> C(2,2) = 2

For i=3:
C[3] = C[3] + C[2] = 0 + 1 = 1 ==>> C(3,3) = 1
C[2] = C[2] + C[1] = 1 + 2 = 3 ==>> C(3,2) = 3
C[1] = C[1] + C[0] = 2 + 1 = 3 ==>> C(3,1) = 3

For i=4:
C[4] = C[4] + C[3] = 0 + 1 = 1 ==>> C(4,4) = 1
C[3] = C[3] + C[2] = 1 + 3 = 4 ==>> C(4,3) = 4
C[2] = C[2] + C[1] = 3 + 3 = 6 ==>> C(4,2) = 6
C[1] = C[1] + C[0] = 3 + 1 = 4 ==>> C(4,1) = 4

C(4,3) = 4 is would be the answer in our example.

See this for Space and time efficient Binomial Coefficient


References:
http://www.csl.mtu.edu/cs4321/www/Lectures/Lecture%2015%20-%20Dynamic%
20Programming%20Binomial%20Coefficients.htm
Improved By : jit_t, vt_m, Mithun Kumar

Source

https://www.geeksforgeeks.org/binomial-coefficient-dp-9/

126
Chapter 10

DP-10 | 0-1 Knapsack Problem

0-1 Knapsack Problem | DP-10 - GeeksforGeeks


Given weights and values of n items, put these items in a knapsack of capacity W to get the
maximum total value in the knapsack. In other words, given two integer arrays val[0..n-1]
and wt[0..n-1] which represent values and weights associated with n items respectively. Also
given an integer W which represents knapsack capacity, find out the maximum value subset
of val[] such that sum of the weights of this subset is smaller than or equal to W. You cannot
break an item, either pick the complete item, or don’t pick it (0-1 property).

A simple solution is to consider all subsets of items and calculate the total weight and value
of all subsets. Consider the only subsets whose total weight is smaller than W. From all
such subsets, pick the maximum value subset.
1) Optimal Substructure:
To consider all subsets of items, there can be two cases for every item: (1) the item is
included in the optimal subset, (2) not included in the optimal set.
Therefore, the maximum value that can be obtained from n items is max of following two
values.
1) Maximum value obtained by n-1 items and W weight (excluding nth item).

127
Chapter 10. DP-10 | 0-1 Knapsack Problem

2) Value of nth item plus maximum value obtained by n-1 items and W minus weight of the
nth item (including nth item).
If weight of nth item is greater than W, then the nth item cannot be included and case 1 is
the only possibility.
2) Overlapping Subproblems
Following is recursive implementation that simply follows the recursive structure mentioned
above.

C/C++

/* A Naive recursive implementation of 0-1 Knapsack problem */


#include<stdio.h>
  
// A utility function that returns maximum of two integers
int max(int a, int b) { return (a > b)? a : b; }
  
// Returns the maximum value that can be put in a knapsack of capacity W
int knapSack(int W, int wt[], int val[], int n)
{
   // Base Case
   if (n == 0 || W == 0)
       return 0;
  
   // If weight of the nth item is more than Knapsack capacity W, then
   // this item cannot be included in the optimal solution
   if (wt[n-1] > W)
       return knapSack(W, wt, val, n-1);
  
   // Return the maximum of two cases: 
   // (1) nth item included 
   // (2) not included
   else return max( val[n-1] + knapSack(W-wt[n-1], wt, val, n-1),
                    knapSack(W, wt, val, n-1)
                  );
}
  
// Driver program to test above function
int main()
{
    int val[] = {60, 100, 120};
    int wt[] = {10, 20, 30};
    int  W = 50;
    int n = sizeof(val)/sizeof(val[0]);
    printf("%d", knapSack(W, wt, val, n));
    return 0;
}

128
Chapter 10. DP-10 | 0-1 Knapsack Problem

Java

/* A Naive recursive implementation of 0-1 Knapsack problem */


class Knapsack
{
  
    // A utility function that returns maximum of two integers
     static int max(int a, int b) { return (a > b)? a : b; }
       
     // Returns the maximum value that can be put in a knapsack of capacity W
     static int knapSack(int W, int wt[], int val[], int n)
     {
        // Base Case
    if (n == 0 || W == 0)
        return 0;
       
    // If weight of the nth item is more than Knapsack capacity W, then
    // this item cannot be included in the optimal solution
    if (wt[n-1] > W)
       return knapSack(W, wt, val, n-1);
       
    // Return the maximum of two cases: 
    // (1) nth item included 
    // (2) not included
    else return max( val[n-1] + knapSack(W-wt[n-1], wt, val, n-1),
                     knapSack(W, wt, val, n-1)
                      );
      }
  
    
   // Driver program to test above function
   public static void main(String args[])
   {
        int val[] = new int[]{60, 100, 120};
        int wt[] = new int[]{10, 20, 30};
    int  W = 50;
    int n = val.length;
    System.out.println(knapSack(W, wt, val, n));
    }
}
/*This code is contributed by Rajat Mishra */

Python

#A naive recursive implementation of 0-1 Knapsack Problem


  
# Returns the maximum value that can be put in a knapsack of

129
Chapter 10. DP-10 | 0-1 Knapsack Problem

# capacity W
def knapSack(W , wt , val , n):
  
    # Base Case
    if n == 0 or W == 0 :
        return 0
  
    # If weight of the nth item is more than Knapsack of capacity
    # W, then this item cannot be included in the optimal solution
    if (wt[n-1] > W):
        return knapSack(W , wt , val , n-1)
  
    # return the maximum of two cases:
    # (1) nth item included
    # (2) not included
    else:
        return max(val[n-1] + knapSack(W-wt[n-1] , wt , val , n-1),
                   knapSack(W , wt , val , n-1))
  
# end of function knapSack
  
# To test above function
val = [60, 100, 120]
wt = [10, 20, 30]
W = 50
n = len(val)
print knapSack(W , wt , val , n)
  
# This code is contributed by Nikhil Kumar Singh

C#

/* A Naive recursive implementation of 


0-1 Knapsack problem */
using System;
  
class GFG {
      
    // A utility function that returns
    // maximum of two integers
    static int max(int a, int b) 
    {
        return (a > b)? a : b; 
    }
      
    // Returns the maximum value that can 
    // be put in a knapsack of capacity W
    static int knapSack(int W, int []wt, 

130
Chapter 10. DP-10 | 0-1 Knapsack Problem

                        int []val, int n)


    {
          
        // Base Case
        if (n == 0 || W == 0)
            return 0;
      
        // If weight of the nth item is 
        // more than Knapsack capacity W,
        // then this item cannot be 
        // included in the optimal solution
        if (wt[n-1] > W)
            return knapSack(W, wt, val, n-1);
          
        // Return the maximum of two cases: 
        // (1) nth item included 
        // (2) not included
        else return max( val[n-1] +
            knapSack(W-wt[n-1], wt, val, n-1),
                   knapSack(W, wt, val, n-1));
    }
  
    // Driver function
    public static void Main()
    {
        int []val = new int[]{60, 100, 120};
        int []wt = new int[]{10, 20, 30};
        int W = 50;
        int n = val.Length;
          
        Console.WriteLine(knapSack(W, wt, val, n));
    }
}
  
// This code is contributed by Sam007

PHP

<?php
// A Naive recursive implementation
// of 0-1 Knapsack problem 
  
// Returns the maximum value that
// can be put in a knapsack of 
// capacity W
function knapSack($W, $wt, $val, $n)
{
    // Base Case

131
Chapter 10. DP-10 | 0-1 Knapsack Problem

    if ($n == 0 || $W == 0)
        return 0;
      
    // If weight of the nth item is 
    // more than Knapsack capacity 
    // W, then this item cannot be
    // included in the optimal solution
    if ($wt[$n - 1] > $W)
        return knapSack($W, $wt, $val, $n - 1);
      
    // Return the maximum of two cases: 
    // (1) nth item included 
    // (2) not included
    else
        return max($val[$n - 1] + 
               knapSack($W - $wt[$n - 1], 
               $wt, $val, $n - 1), 
               knapSack($W, $wt, $val, $n-1));
}
  
    // Driver Code
    $val = array(60, 100, 120);
    $wt = array(10, 20, 30);
    $W = 50;
    $n = count($val);
    echo knapSack($W, $wt, $val, $n);
  
// This code is contributed by Sam007
?>

Output:

220

It should be noted that the above function computes the same subproblems again and again.
See the following recursion tree, K(1, 1) is being evaluated twice. Time complexity of this
naive recursive solution is exponential (2^n).

In the following recursion tree, K() refers to knapSack(). The two


parameters indicated in the following recursion tree are n and W.
The recursion tree is for following sample inputs.
wt[] = {1, 1, 1}, W = 2, val[] = {10, 20, 30}

K(3, 2) ---------> K(n, W)


/ \
/ \
K(2,2) K(2,1)

132
Chapter 10. DP-10 | 0-1 Knapsack Problem

/ \ / \
/ \ / \
K(1,2) K(1,1) K(1,1) K(1,0)
/ \ / \ / \
/ \ / \ / \
K(0,2) K(0,1) K(0,1) K(0,0) K(0,1) K(0,0)
Recursion tree for Knapsack capacity 2 units and 3 items of 1 unit weight.

Since suproblems are evaluated again, this problem has Overlapping Subprolems property.
So the 0-1 Knapsack problem has both properties (see thisand this) of a dynamic program-
ming problem. Like other typical Dynamic Programming(DP) problems, recomputations
of same subproblems can be avoided by constructing a temporary array K[][] in bottom up
manner. Following is Dynamic Programming based implementation.
C++

// A Dynamic Programming based solution for 0-1 Knapsack problem


#include<stdio.h>
  
// A utility function that returns maximum of two integers
int max(int a, int b) { return (a > b)? a : b; }
  
// Returns the maximum value that can be put in a knapsack of capacity W
int knapSack(int W, int wt[], int val[], int n)
{
   int i, w;
   int K[n+1][W+1];
  
   // Build table K[][] in bottom up manner
   for (i = 0; i <= n; i++)
   {
       for (w = 0; w <= W; w++)
       {
           if (i==0 || w==0)
               K[i][w] = 0;
           else if (wt[i-1] <= w)
                 K[i][w] = max(val[i-1] + K[i-1][w-wt[i-1]],  K[i-1][w]);
           else
                 K[i][w] = K[i-1][w];
       }
   }
  
   return K[n][W];
}
  
int main()
{
    int val[] = {60, 100, 120};

133
Chapter 10. DP-10 | 0-1 Knapsack Problem

    int wt[] = {10, 20, 30};


    int  W = 50;
    int n = sizeof(val)/sizeof(val[0]);
    printf("%d", knapSack(W, wt, val, n));
    return 0;
}

Java

// A Dynamic Programming based solution for 0-1 Knapsack problem


class Knapsack
{
  
    // A utility function that returns maximum of two integers
    static int max(int a, int b) { return (a > b)? a : b; }
       
   // Returns the maximum value that can be put in a knapsack of capacity W
    static int knapSack(int W, int wt[], int val[], int n)
    {
         int i, w;
     int K[][] = new int[n+1][W+1];
       
     // Build table K[][] in bottom up manner
     for (i = 0; i <= n; i++)
     {
         for (w = 0; w <= W; w++)
         {
             if (i==0 || w==0)
                  K[i][w] = 0;
             else if (wt[i-1] <= w)
                   K[i][w] = max(val[i-1] + K[i-1][w-wt[i-1]],  K[i-1][w]);
             else
                   K[i][w] = K[i-1][w];
         }
      }
       
      return K[n][W];
    }
  
    
    // Driver program to test above function
    public static void main(String args[])
    {
        int val[] = new int[]{60, 100, 120};
    int wt[] = new int[]{10, 20, 30};
    int  W = 50;
    int n = val.length;
    System.out.println(knapSack(W, wt, val, n));

134
Chapter 10. DP-10 | 0-1 Knapsack Problem

    }
}
/*This code is contributed by Rajat Mishra */

Python

# A Dynamic Programming based Python Program for 0-1 Knapsack problem


# Returns the maximum value that can be put in a knapsack of capacity W
def knapSack(W, wt, val, n):
    K = [[0 for x in range(W+1)] for x in range(n+1)]
  
    # Build table K[][] in bottom up manner
    for i in range(n+1):
        for w in range(W+1):
            if i==0 or w==0:
                K[i][w] = 0
            elif wt[i-1] <= w:
                K[i][w] = max(val[i-1] + K[i-1][w-wt[i-1]],  K[i-1][w])
            else:
                K[i][w] = K[i-1][w]
  
    return K[n][W]
  
# Driver program to test above function
val = [60, 100, 120]
wt = [10, 20, 30]
W = 50
n = len(val)
print(knapSack(W, wt, val, n))
  
# This code is contributed by Bhavya Jain

C#

// A Dynamic Programming based solution for


// 0-1 Knapsack problem
using System;
  
class GFG {
      
    // A utility function that returns 
    // maximum of two integers
    static int max(int a, int b)
    {
        return (a > b) ? a : b;
    }
      

135
Chapter 10. DP-10 | 0-1 Knapsack Problem

    // Returns the maximum value that


    // can be put in a knapsack of 
    // capacity W
    static int knapSack(int W, int []wt, 
                         int []val, int n)
    {
        int i, w;
        int [,]K = new int[n+1,W+1];
          
        // Build table K[][] in bottom 
        // up manner
        for (i = 0; i <= n; i++)
        {
            for (w = 0; w <= W; w++)
            {
                if (i == 0 || w == 0)
                    K[i,w] = 0;
                else if (wt[i-1] <= w)
                    K[i,w] = Math.Max(val[i-1] 
                           + K[i-1,w-wt[i-1]],
                                    K[i-1,w]);
                else
                    K[i,w] = K[i-1,w];
            }
        }
          
        return K[n,W];
    }
      
    // Driver code
    static void Main()
    {
        int []val = new int[]{60, 100, 120};
        int []wt = new int[]{10, 20, 30};
        int W = 50;
        int n = val.Length;
          
        Console.WriteLine(
                  knapSack(W, wt, val, n));
    }
}
  
// This code is contributed by Sam007

PHP

<?php
// A Dynamic Programming based solution

136
Chapter 10. DP-10 | 0-1 Knapsack Problem

// for 0-1 Knapsack problem


  
// Returns the maximum value that
// can be put in a knapsack of 
// capacity W
function knapSack($W, $wt, $val, $n)
{
      
    $K = array(array());
      
    // Build table K[][] in
    // bottom up manner
    for ($i = 0; $i <= $n; $i++)
    {
        for ($w = 0; $w <= $W; $w++)
        {
            if ($i == 0 || $w == 0)
                $K[$i][$w] = 0;
            else if ($wt[$i - 1] <= $w)
                    $K[$i][$w] = max($val[$i - 1] + 
                                     $K[$i - 1][$w - 
                                     $wt[$i - 1]], 
                                     $K[$i - 1][$w]);
            else
                    $K[$i][$w] = $K[$i - 1][$w];
        }
    }
      
    return $K[$n][$W];
}
  
    // Driver Code
    $val = array(60, 100, 120);
    $wt = array(10, 20, 30);
    $W = 50;
    $n = count($val);
    echo knapSack($W, $wt, $val, $n);
      
// This code is contributed by Sam007.
?>

Output:

220

Time Complexity: O(nW) where n is the number of items and W is the capacity of knapsack.
References:
http://www.es.ele.tue.nl/education/5MC10/Solutions/knapsack.pdf

137
Chapter 10. DP-10 | 0-1 Knapsack Problem

http://www.cse.unl.edu/~goddard/Courses/CSCE310J/Lectures/Lecture8-DynamicProgramming.
pdf
Improved By : Sam007

Source

https://www.geeksforgeeks.org/0-1-knapsack-problem-dp-10/

138
Chapter 11

DP-11 | Egg Dropping Puzzle

Egg Dropping Puzzle | DP-11 - GeeksforGeeks


The following is a description of the instance of this famous puzzle involving n=2 eggs and
a building with k=36 floors.
Suppose that we wish to know which stories in a 36-story building are safe to drop eggs
from, and which will cause the eggs to break on landing. We make a few assumptions:
…..An egg that survives a fall can be used again.
…..A broken egg must be discarded.
…..The effect of a fall is the same for all eggs.
…..If an egg breaks when dropped, then it would break if dropped from a higher floor.
…..If an egg survives a fall then it would survive a shorter fall.
…..It is not ruled out that the first-floor windows break eggs, nor is it ruled out that the
36th-floor do not cause an egg to break.
If only one egg is available and we wish to be sure of obtaining the right result, the experiment
can be carried out in only one way. Drop the egg from the first-floor window; if it survives,
drop it from the second floor window. Continue upward until it breaks. In the worst case,
this method may require 36 droppings. Suppose 2 eggs are available. What is the least
number of egg-droppings that is guaranteed to work in all cases?
The problem is not actually to find the critical floor, but merely to decide floors from which
eggs should be dropped so that total number of trials are minimized.
Source: Wiki for Dynamic Programming
In this post, we will discuss solution to a general problem with n eggs and k floors. The
solution is to try dropping an egg from every floor (from 1 to k) and recursively calculate the
minimum number of droppings needed in worst case. The floor which gives the minimum
value in worst case is going to be part of the solution.
In the following solutions, we return the minimum number of trials in worst case; these
solutions can be easily modified to print floor numbers of every trials also.
1) Optimal Substructure:
When we drop an egg from a floor x, there can be two cases (1) The egg breaks (2) The egg
doesn’t break.

139
Chapter 11. DP-11 | Egg Dropping Puzzle

1) If the egg breaks after dropping from xth floor, then we only need to check for floors
lower than x with remaining eggs; so the problem reduces to x-1 floors and n-1 eggs
2) If the egg doesn’t break after dropping from the xth floor, then we only need to check for
floors higher than x; so the problem reduces to k-x floors and n eggs.
Since we need to minimize the number of trials in worst case, we take the maximum of two
cases. We consider the max of above two cases for every floor and choose the floor which
yields minimum number of trials.

k ==> Number of floors


n ==> Number of Eggs
eggDrop(n, k) ==> Minimum number of trials needed to find the critical
floor in worst case.
eggDrop(n, k) = 1 + min{max(eggDrop(n - 1, x - 1), eggDrop(n, k - x)):
x in {1, 2, ..., k}}

2) Overlapping Subproblems
Following is recursive implementation that simply follows the recursive structure mentioned
above.
C

# include <stdio.h>
# include <limits.h>
  
// A utility function to get maximum of two integers
int max(int a, int b) { return (a > b)? a: b; }
  
/* Function to get minimum number of trials needed in worst
  case with n eggs and k floors */
int eggDrop(int n, int k)
{
    // If there are no floors, then no trials needed. OR if there is
    // one floor, one trial needed.
    if (k == 1 || k == 0)
        return k;
  
    // We need k trials for one egg and k floors
    if (n == 1)
        return k;
  
    int min = INT_MAX, x, res;
  
    // Consider all droppings from 1st floor to kth floor and
    // return the minimum of these values plus 1.
    for (x = 1; x <= k; x++)
    {

140
Chapter 11. DP-11 | Egg Dropping Puzzle

        res = max(eggDrop(n-1, x-1), eggDrop(n, k-x));


        if (res < min)
            min = res;
    }
  
    return min + 1;
}
  
/* Driver program to test to pront printDups*/
int main()
{
    int n = 2, k = 10;
    printf ("nMinimum number of trials in worst case with %d eggs and "
             "%d floors is %d \n", n, k, eggDrop(n, k));
    return 0;
}

C#

using System;
  
class GFG {
      
    /* Function to get minimum number of 
    trials needed in worst case with n 
    eggs and k floors */
    static int eggDrop(int n, int k)
    {
        // If there are no floors, then 
        // no trials needed. OR if there
        // is one floor, one trial needed.
        if (k == 1 || k == 0)
            return k;
      
        // We need k trials for one egg
        // and k floors
        if (n == 1)
            return k;
      
        int min = int.MaxValue;
        int x, res;
      
        // Consider all droppings from 
        //1st floor to kth floor and
        // return the minimum of these
        // values plus 1.
        for (x = 1; x <= k; x++)
        {

141
Chapter 11. DP-11 | Egg Dropping Puzzle

            res = Math.Max(eggDrop(n-1, x-1), 


                           eggDrop(n, k-x));
            if (res < min)
                min = res;
        }
      
        return min + 1;
    }
      
    // Driver code
    static void Main()
    {
        int n = 2, k = 10;
        Console.Write("Minimum number of "
            + "trials in worst case with "
                   + n + " eggs and " + k
          + " floors is " + eggDrop(n, k));
    }
}
  
// This code is contributed by Sam007.

Output:
Minimum number of trials in worst case with 2 eggs and 10 floors is 4

It should be noted that the above function computes the same subproblems again and again.
See the following partial recursion tree, E(2, 2) is being evaluated twice. There will many
repeated subproblems when you draw the complete recursion tree even for small values of
n and k.

E(2,4)
|
-------------------------------------
| | | |
| | | |
x=1/ x=2/ x=3/ x=4/
/ / .... ....
/ /
E(1,0) E(2,3) E(1,1) E(2,2)
/ /... /
x=1/ .....
/
E(1,0) E(2,2)
/

142
Chapter 11. DP-11 | Egg Dropping Puzzle

......

Partial recursion tree for 2 eggs and 4 floors.

Since same suproblems are called again, this problem has Overlapping Subprolems property.
So Egg Dropping Puzzle has both properties (see thisand this) of a dynamic programming
problem. Like other typical Dynamic Programming(DP) problems, recomputations of same
subproblems can be avoided by constructing a temporary array eggFloor[][] in bottom up
manner.
Dynamic Programming Solution
Following are the implementations for Egg Dropping problem using Dynamic Programming.

C++

// A Dynamic Programming based C++ Program for the Egg Dropping Puzzle
# include <stdio.h>
# include <limits.h>
  
// A utility function to get maximum of two integers
int max(int a, int b) { return (a > b)? a: b; }
  
/* Function to get minimum number of trials needed in worst
  case with n eggs and k floors */
int eggDrop(int n, int k)
{
    /* A 2D table where entery eggFloor[i][j] will represent minimum
       number of trials needed for i eggs and j floors. */
    int eggFloor[n+1][k+1];
    int res;
    int i, j, x;
  
    // We need one trial for one floor and0 trials for 0 floors
    for (i = 1; i <= n; i++)
    {
        eggFloor[i][1] = 1;
        eggFloor[i][0] = 0;
    }
  
    // We always need j trials for one egg and j floors.
    for (j = 1; j <= k; j++)
        eggFloor[1][j] = j;
  
    // Fill rest of the entries in table using optimal substructure
    // property
    for (i = 2; i <= n; i++)
    {
        for (j = 2; j <= k; j++)

143
Chapter 11. DP-11 | Egg Dropping Puzzle

        {
            eggFloor[i][j] = INT_MAX;
            for (x = 1; x <= j; x++)
            {
                res = 1 + max(eggFloor[i-1][x-1], eggFloor[i][j-x]);
                if (res < eggFloor[i][j])
                    eggFloor[i][j] = res;
            }
        }
    }
  
    // eggFloor[n][k] holds the result
    return eggFloor[n][k];
}
  
/* Driver program to test to pront printDups*/
int main()
{
    int n = 2, k = 36;
    printf ("nMinimum number of trials in worst case with %d eggs and "
             "%d floors is %d \n", n, k, eggDrop(n, k));
    return 0;
}

Java

//A Dynamic Programming based Python Program for the Egg Dropping Puzzle
class EggDrop
{
    // A utility function to get maximum of two integers
    static int max(int a, int b) { return (a > b)? a: b; }
       
    /* Function to get minimum number of trials needed in worst
    case with n eggs and k floors */
    static int eggDrop(int n, int k)
    {
       /* A 2D table where entery eggFloor[i][j] will represent minimum
       number of trials needed for i eggs and j floors. */
        int eggFloor[][] = new int[n+1][k+1];
        int res;
        int i, j, x;
           
        // We need one trial for one floor and0 trials for 0 floors
        for (i = 1; i <= n; i++)
        {
            eggFloor[i][1] = 1;
            eggFloor[i][0] = 0;
        }

144
Chapter 11. DP-11 | Egg Dropping Puzzle

           
       // We always need j trials for one egg and j floors.
        for (j = 1; j <= k; j++)
            eggFloor[1][j] = j;
           
        // Fill rest of the entries in table using optimal substructure
        // property
        for (i = 2; i <= n; i++)
        {
            for (j = 2; j <= k; j++)
            {
                eggFloor[i][j] = Integer.MAX_VALUE;
                for (x = 1; x <= j; x++)
                {
                     res = 1 + max(eggFloor[i-1][x-1], eggFloor[i][j-x]);
                     if (res < eggFloor[i][j])
                        eggFloor[i][j] = res;
                }
            }
        }
           
        // eggFloor[n][k] holds the result
        return eggFloor[n][k];
  
    }
           
    /* Driver program to test to pront printDups*/
    public static void  main(String args[] )
    {
        int n = 2, k = 10;
        System.out.println("Minimum number of trials in worst case with "+n+"  eggs and "+k+
                 " floors is "+eggDrop(n, k));   
    }
}
/*This code is contributed by Rajat Mishra*/

Python

# A Dynamic Programming based Python Program for the Egg Dropping Puzzle
INT_MAX = 32767
  
# Function to get minimum number of trials needed in worst
# case with n eggs and k floors
def eggDrop(n, k):
    # A 2D table where entery eggFloor[i][j] will represent minimum
    # number of trials needed for i eggs and j floors.
    eggFloor = [[0 for x in range(k+1)] for x in range(n+1)]
  

145
Chapter 11. DP-11 | Egg Dropping Puzzle

    # We need one trial for one floor and0 trials for 0 floors
    for i in range(1, n+1):
        eggFloor[i][1] = 1
        eggFloor[i][0] = 0
  
    # We always need j trials for one egg and j floors.
    for j in range(1, k+1):
        eggFloor[1][j] = j
  
    # Fill rest of the entries in table using optimal substructure
    # property
    for i in range(2, n+1):
        for j in range(2, k+1):
            eggFloor[i][j] = INT_MAX
            for x in range(1, j+1):
                res = 1 + max(eggFloor[i-1][x-1], eggFloor[i][j-x])
                if res < eggFloor[i][j]:
                    eggFloor[i][j] = res
  
    # eggFloor[n][k] holds the result
    return eggFloor[n][k]
  
# Driver program to test to pront printDups
n = 2
k = 36
print("Minimum number of trials in worst case with" + str(n) + "eggs and " 
       + str(k) + " floors is " + str(eggDrop(n, k)))
  
# This code is contributed by Bhavya Jain

C#

// A Dynamic Programming based Python Program


// for the Egg Dropping Puzzle
using System;
  
class GFG {
      
    // A utility function to get maximum of 
    // two integers
    static int max(int a, int b) 
    {
        return (a > b) ? a: b;
    }
      
    /* Function to get minimum number of 
    trials needed in worst case with n
    eggs and k floors */

146
Chapter 11. DP-11 | Egg Dropping Puzzle

    static int eggDrop(int n, int k)


    {
          
        /* A 2D table where entery eggFloor[i][j]
        will represent minimum number of trials
        needed for i eggs and j floors. */
        int [,]eggFloor = new int[n+1,k+1];
        int res;
        int i, j, x;
          
        // We need one trial for one floor and0
        // trials for 0 floors
        for (i = 1; i <= n; i++)
        {
            eggFloor[i,1] = 1;
            eggFloor[i,0] = 0;
        }
          
        // We always need j trials for one egg
        // and j floors.
        for (j = 1; j <= k; j++)
            eggFloor[1,j] = j;
          
        // Fill rest of the entries in table 
        // using optimal substructure property
        for (i = 2; i <= n; i++)
        {
            for (j = 2; j <= k; j++)
            {
                eggFloor[i,j] = int.MaxValue;
                for (x = 1; x <= j; x++)
                {
                    res = 1 + max(eggFloor[i-1,x-1],
                                  eggFloor[i,j-x]);
                    if (res < eggFloor[i,j])
                        eggFloor[i,j] = res;
                }
            }
        }
          
        // eggFloor[n][k] holds the result
        return eggFloor[n,k];
  
    }
  
    // Driver function
    public static void Main()
    {

147
Chapter 11. DP-11 | Egg Dropping Puzzle

        int n = 2, k = 36;
        Console.WriteLine("Minimum number of trials "
           + "in worst case with " + n + " eggs and "
                 + k + "floors is " + eggDrop(n, k)); 
    }
}
  
// This code is contributed by Sam007.

PHP

<?php
// A Dynamic Programming based PHP 
// Program for the Egg Dropping Puzzle
  
/* Function to get minimum number
   of trials needed in worst
   case with n eggs and k floors */
function eggDrop($n, $k)
{
      
    /* A 2D table where entery eggFloor[i][j]
       will represent minimum number of 
       trials needed for i eggs and j floors. */
    $eggFloor = array(array());;
      
    // We need one trial for one 
    // floor and0 trials for 0 floors
    for ($i = 1; $i <=$n;$i++)
    {
        $eggFloor[$i][1] = 1;
        $eggFloor[$i][0] = 0;
    }
  
    // We always need j trials
    // for one egg and j floors.
    for ($j = 1; $j <= $k; $j++)
        $eggFloor[1][$j] = $j;
  
    // Fill rest of the entries in 
    // table using optimal substructure
    // property
    for ($i = 2; $i <= $n; $i++)
    {
        for ($j = 2; $j <= $k; $j++)
        {
            $eggFloor[$i][$j] = 999999;
            for ($x = 1; $x <= $j; $x++)

148
Chapter 11. DP-11 | Egg Dropping Puzzle

            {
                $res = 1 + max($eggFloor[$i - 1][$x - 1], 
                                 $eggFloor[$i][$j - $x]);
                if ($res < $eggFloor[$i][$j])
                    $eggFloor[$i][$j] = $res;
            }
        }
    }
  
    // eggFloor[n][k] holds the result
    return $eggFloor[$n][$k];
}
  
    // Driver Code
    $n = 2;
    $k = 36;
    echo "Minimum number of trials in worst case with " .$n. " eggs and "
                                    .$k. " floors is " .eggDrop($n, $k) ;
                                      
// This code is contributed by Sam007
?>

Output :

Minimum number of trials in worst case with 2 eggs and 36 floors is 8

Time Complexity: O(nk^2)


Auxiliary Space: O(nk)
As an exercise, you may try modifying the above DP solution to print all intermediate floors
(The floors used for minimum trial solution).
More Efficient Solution : Eggs dropping puzzle (Binomial Coefficient and Binary Search
Solution)
Egg Dropping Puzzle with 2 Eggs and K Floors
2 Eggs and 100 Floor Puzzle
References:
http://archive.ite.journal.informs.org/Vol4No1/Sniedovich/index.php
Improved By : Sam007

Source

https://www.geeksforgeeks.org/egg-dropping-puzzle-dp-11/

149
Chapter 12

DP-12 | Longest Palindromic


Subsequence

Longest Palindromic Subsequence | DP-12 - GeeksforGeeks


Given a sequence, find the length of the longest palindromic subsequence in it.

As another example, if the given sequence is “BBABCBCAB”, then the output should be 7
as “BABCBAB” is the longest palindromic subseuqnce in it. “BBBBB” and “BBCBB” are
also palindromic subsequences of the given sequence, but not the longest ones.
The naive solution for this problem is to generate all subsequences of the given sequence
and find the longest palindromic subsequence. This solution is exponential in term of time
complexity. Let us see how this problem possesses both important properties of a Dynamic
Programming (DP) Problem and can efficiently solved using Dynamic Programming.
1) Optimal Substructure:
Let X[0..n-1] be the input sequence of length n and L(0, n-1) be the length of the longest
palindromic subsequence of X[0..n-1].
If last and first characters of X are same, then L(0, n-1) = L(1, n-2) + 2.
Else L(0, n-1) = MAX (L(1, n-1), L(0, n-2)).
Following is a general recursive solution with all cases handled.

150
Chapter 12. DP-12 | Longest Palindromic Subsequence

// Every single character is a palindrome of length 1


L(i, i) = 1 for all indexes i in given sequence

// IF first and last characters are not same


If (X[i] != X[j]) L(i, j) = max{L(i + 1, j),L(i, j - 1)}

// If there are only 2 characters and both are same


Else if (j == i + 1) L(i, j) = 2

// If there are more than two characters, and first and last
// characters are same
Else L(i, j) = L(i + 1, j - 1) + 2

2) Overlapping Subproblems
Following is simple recursive implementation of the LPS problem. The implementation
simply follows the recursive structure mentioned above.

#include<stdio.h>
#include<string.h>
  
// A utility function to get max of two integers
int max (int x, int y) { return (x > y)? x : y; }
  
// Returns the length of the longest palindromic subsequence in seq
int lps(char *seq, int i, int j)
{
   // Base Case 1: If there is only 1 character
   if (i == j)
     return 1;
  
   // Base Case 2: If there are only 2 characters and both are same
   if (seq[i] == seq[j] && i + 1 == j)
     return 2;
  
   // If the first and last characters match
   if (seq[i] == seq[j])
      return lps (seq, i+1, j-1) + 2;
  
   // If the first and last characters do not match
   return max( lps(seq, i, j-1), lps(seq, i+1, j) );
}
  
/* Driver program to test above functions */
int main()
{
    char seq[] = "GEEKSFORGEEKS";
    int n = strlen(seq);
    printf ("The length of the LPS is %d", lps(seq, 0, n-1));

151
Chapter 12. DP-12 | Longest Palindromic Subsequence

    getchar();
    return 0;
}

Output:

The length of the LPS is 5

Considering the above implementation, following is a partial recursion tree for a sequence
of length 6 with all different characters.

L(0, 5)
/ \
/ \
L(1,5) L(0,4)
/ \ / \
/ \ / \
L(2,5) L(1,4) L(1,4) L(0,3)

In the above partial recursion tree, L(1, 4) is being solved twice. If we draw the complete
recursion tree, then we can see that there are many subproblems which are solved again and
again. Since same suproblems are called again, this problem has Overlapping Subprolems
property. So LPS problem has both properties (see thisand this) of a dynamic programming
problem. Like other typical Dynamic Programming(DP) problems, recomputations of same
subproblems can be avoided by constructing a temporary array L[][] in bottom up manner.
Dynamic Programming Solution

C++

// A Dynamic Programming based C++ program for LPS problem


// Returns the length of the longest palindromic subsequence in seq
#include<stdio.h>
#include<string.h>
  
// A utility function to get max of two integers
int max (int x, int y) { return (x > y)? x : y; }
  
// Returns the length of the longest palindromic subsequence in seq
int lps(char *str)
{
   int n = strlen(str);
   int i, j, cl;
   int L[n][n];  // Create a table to store results of subproblems

152
Chapter 12. DP-12 | Longest Palindromic Subsequence

  
  
   // Strings of length 1 are palindrome of lentgh 1
   for (i = 0; i < n; i++)
      L[i][i] = 1;
  
    // Build the table. Note that the lower diagonal values of table are
    // useless and not filled in the process. The values are filled in a
    // manner similar to Matrix Chain Multiplication DP solution (See
    // https://www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/). cl is length of
    // substring
    for (cl=2; cl<=n; cl++)
    {
        for (i=0; i<n-cl+1; i++)
        {
            j = i+cl-1;
            if (str[i] == str[j] && cl == 2)
               L[i][j] = 2;
            else if (str[i] == str[j])
               L[i][j] = L[i+1][j-1] + 2;
            else
               L[i][j] = max(L[i][j-1], L[i+1][j]);
        }
    }
  
    return L[0][n-1];
}
  
/* Driver program to test above functions */
int main()
{
    char seq[] = "GEEKS FOR GEEKS";
    int n = strlen(seq);
    printf ("The lnegth of the LPS is %d", lps(seq));
    getchar();
    return 0;
}

Java

//A Dynamic Programming based Python Program for the Egg Dropping Puzzle
class LPS
{
  
    // A utility function to get max of two integers
    static int max (int x, int y) { return (x > y)? x : y; }
       
    // Returns the length of the longest palindromic subsequence in seq

153
Chapter 12. DP-12 | Longest Palindromic Subsequence

    static int lps(String seq)


    {
       int n = seq.length();
       int i, j, cl;
       int L[][] = new int[n][n];  // Create a table to store results of subproblems
       
       // Strings of length 1 are palindrome of lentgh 1
       for (i = 0; i < n; i++)
           L[i][i] = 1;
               
        // Build the table. Note that the lower diagonal values of table are
        // useless and not filled in the process. The values are filled in a
        // manner similar to Matrix Chain Multiplication DP solution (See
        // https://www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/). cl is length of
        // substring
        for (cl=2; cl<=n; cl++)
        {
            for (i=0; i<n-cl+1; i++)
            {
                j = i+cl-1;
                if (seq.charAt(i) == seq.charAt(j) && cl == 2)
                   L[i][j] = 2;
                else if (seq.charAt(i) == seq.charAt(j))
                   L[i][j] = L[i+1][j-1] + 2;
                else
                   L[i][j] = max(L[i][j-1], L[i+1][j]);
            }
        }
               
        return L[0][n-1];
    }
           
    /* Driver program to test above functions */
    public static void main(String args[])
    {
        String seq = "GEEKSFORGEEKS";
        int n = seq.length();
        System.out.println("The lnegth of the lps is "+ lps(seq));
    }
}
/* This code is contributed by Rajat Mishra */

Python

# A Dynamic Programming based Python program for LPS problem


# Returns the length of the longest palindromic subsequence in seq
def lps(str):
    n = len(str)

154
Chapter 12. DP-12 | Longest Palindromic Subsequence

  
    # Create a table to store results of subproblems
    L = [[0 for x in range(n)] for x in range(n)]
  
    # Strings of length 1 are palindrome of length 1
    for i in range(n):
        L[i][i] = 1
  
    # Build the table. Note that the lower diagonal values of table are
    # useless and not filled in the process. The values are filled in a
    # manner similar to Matrix Chain Multiplication DP solution (See
    # https://www.geeksforgeeks.org/dynamic-programming-set-8-matrix-chain-multiplication/
    # cl is length of substring
    for cl in range(2, n+1):
        for i in range(n-cl+1):
            j = i+cl-1
            if str[i] == str[j] and cl == 2:
                L[i][j] = 2
            elif str[i] == str[j]:
                L[i][j] = L[i+1][j-1] + 2
            else:
                L[i][j] = max(L[i][j-1], L[i+1][j]);
  
    return L[0][n-1]
  
# Driver program to test above functions
seq = "GEEKS FOR GEEKS"
n = len(seq)
print("The length of the LPS is " + str(lps(seq)))
  
# This code is contributed by Bhavya Jain

C#

// A Dynamic Programming based C# Program


// for the Egg Dropping Puzzle
using System;
  
class GFG {
  
    // A utility function to get max of
    // two integers
    static int max (int x, int y) 
    { 
        return (x > y)? x : y;
    }
      
    // Returns the length of the longest

155
Chapter 12. DP-12 | Longest Palindromic Subsequence

    // palindromic subsequence in seq


    static int lps(string seq)
    {
    int n = seq.Length;
    int i, j, cl;
      
    // Create a table to store results
    // of subproblems
    int [,]L = new int[n,n];
      
    // Strings of length 1 are 
    // palindrome of lentgh 1
    for (i = 0; i < n; i++)
        L[i,i] = 1;
              
        // Build the table. Note that the 
        // lower diagonal values of table
        // are useless and not filled in
        // the process. The values are 
        // filled in a manner similar to
        // Matrix Chain Multiplication DP
        // solution (See
        // https://www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/
        // cl is length of substring
        for (cl = 2; cl <= n; cl++)
        {
            for (i = 0; i < n-cl+1; i++)
            {
                j = i + cl - 1;
                  
                if (seq[i] == seq[j] &&
                                  cl == 2)
                    L[i,j] = 2;
                else if (seq[i] == seq[j])
                    L[i,j] = L[i+1,j-1] + 2;
                else
                    L[i,j] = 
                     max(L[i,j-1], L[i+1,j]);
            }
        }
              
        return L[0,n-1];
    }
          
    /* Driver program to test above 
    functions */
    public static void Main()
    {

156
Chapter 12. DP-12 | Longest Palindromic Subsequence

        string seq = "GEEKS FOR GEEKS";


        int n = seq.Length;
        Console.Write("The lnegth of the "
                  + "lps is "+ lps(seq));
    }
}
  
// This code is contributed by nitin mittal.

PHP

<?php
// A Dynamic Programming based 
// PHP program for LPS problem
// Returns the length of the 
// longest palindromic 
// subsequence in seq
  
// A utility function to get
// max of two integers
// function max( $x, $y)
// { return ($x > $y)? $x : $y; }
  
// Returns the length of the
// longest palindromic 
// subsequence in seq
function lps($str)
{
$n = strlen($str);
$i; $j; $cl;
  
// Create a table to store
// results of subproblems
$L[][] = array(array()); 
  
  
// Strings of length 1 are
// palindrome of lentgh 1
for ($i = 0; $i < $n; $i++)
    $L[$i][$i] = 1;
  
    // Build the table. Note that 
    // the lower diagonal values 
    // of table are useless and 
    // not filled in the process. 
    // The values are filled in a 
    // manner similar to Matrix 
    // Chain Multiplication DP 

157
Chapter 12. DP-12 | Longest Palindromic Subsequence

    // solution (See 


    // https://www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/).
    // cl is length of substring
    for ($cl = 2; $cl <= $n; $cl++)
    {
        for ($i = 0; $i < $n - $cl + 1; $i++)
        {
            $j = $i + $cl - 1;
            if ($str[$i] == $str[$j] && 
                            $cl == 2)
            $L[$i][$j] = 2;
            else if ($str[$i] == $str[$j])
            $L[$i][$j] = $L[$i + 1][$j - 1] + 2;
            else
            $L[$i][$j] = max($L[$i][$j - 1], 
                             $L[$i + 1][$j]);
        }
    }
  
    return $L[0][$n - 1];
}
  
// Driver Code
$seq = 'GEEKS FOR GEEKS';
$n = strlen($seq);
echo "The lnegth of the " . 
      "LPS is ", lps($seq);
  
// This code is contributed
// by shiv_bhakt.
?>

Output:

The lnegth of the LPS is 7

Time Complexity of the above implementation is O(n^2) which is much better than the
worst case time complexity of Naive Recursive implementation.
This problem is close to the Longest Common Subsequence (LCS) problem. In fact, we can
use LCS as a subroutine to solve this problem. Following is the two step solution that uses
LCS.
1) Reverse the given sequence and store the reverse in another array say rev[0..n-1]
2) LCS of the given sequence and rev[] will be the longest palindromic sequence.
This solution is also a O(n^2) solution.

Print Longest Palindromic Subsequence


Longest palindrome subsequence with O(n) space

158
Chapter 12. DP-12 | Longest Palindromic Subsequence

References:
http://users.eecs.northwestern.edu/~dda902/336/hw6-sol.pdf
Improved By : nitin mittal, shiv_bhakt

Source

https://www.geeksforgeeks.org/longest-palindromic-subsequence-dp-12/

159
Chapter 13

DP-13 | Cutting a Rod

Cutting a Rod | DP-13 - GeeksforGeeks


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

And if the prices are as following, then the maximum obtainable value is 24 (by cutting in
eight pieces of length 1)

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

A naive solution for this problem is to generate all configurations of different pieces and find
the highest priced configuration. This solution is exponential in term of time complexity.
Let us see how this problem possesses both important properties of a Dynamic Programming
(DP) Problem and can efficiently solved using Dynamic Programming.
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.

160
Chapter 13. DP-13 | Cutting a Rod

Let cutRod(n) be the required (best possible price) value for a rod of length 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
Following is simple recursive implementation of the Rod Cutting problem. The implemen-
tation simply follows the recursive structure mentioned above.

C++

// A Naive recursive solution for Rod cutting problem


#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 cutRod(int price[], int n)
{
   if (n <= 0)
     return 0;
   int max_val = INT_MIN;
  
   // Recursively cut the rod in different pieces and compare different 
   // configurations
   for (int i = 0; i<n; i++)
         max_val = max(max_val, price[i] + cutRod(price, n-i-1));
  
   return max_val;
}
  
/* Driver program to test above functions */
int main()
{
    int arr[] = {1, 5, 8, 9, 10, 17, 17, 20};
    int size = sizeof(arr)/sizeof(arr[0]);
    printf("Maximum Obtainable Value is %dn", cutRod(arr, size));
    getchar();
    return 0;
}

Java

// // A Naive recursive solution for Rod cutting problem


class RodCutting

161
Chapter 13. DP-13 | Cutting a Rod

{
    /* Returns the best obtainable price for a rod of length
       n and price[] as prices of different pieces */
    static int cutRod(int price[], int n)
    {
        if (n <= 0)
            return 0;
        int max_val = Integer.MIN_VALUE;
  
        // Recursively cut the rod in different pieces and
        // compare different configurations
        for (int i = 0; i<n; i++)
            max_val = Math.max(max_val,
                              price[i] + cutRod(price, n-i-1));
  
        return max_val;
    }
  
    /* Driver program to test above functions */
    public static void main(String args[])
    {
        int arr[] = new int[] {1, 5, 8, 9, 10, 17, 17, 20};
        int size = arr.length;
        System.out.println("Maximum Obtainable Value is "+
                            cutRod(arr, size));
  
    }
}
/* This code is contributed by Rajat Mishra */

Python

# A Naive recursive solution 


# for Rod cutting problem
import sys
  
# A utility function to get the
# maximum of two integers
def max(a, b):
    return a if (a > b) else b
      
# Returns the best obtainable price for a rod of length n 
# and price[] as prices of different pieces
def cutRod(price, n):
    if(n <= 0):
        return 0
    max_val = -sys.maxsize-1
      

162
Chapter 13. DP-13 | Cutting a Rod

    # Recursively cut the rod in different pieces  


    # and compare different configurations
    for i in range(0, n):
        max_val = max(max_val, price[i] + 
                      cutRod(price, n - i - 1))
    return max_val
  
# Driver code
arr = [1, 5, 8, 9, 10, 17, 17, 20]
size = len(arr)
print("Maximum Obtainable Value is", cutRod(arr, size))
  
# This code is contributed by 'Smitha Dinesh Semwal'

C#

// A Naive recursive solution for


// Rod cutting problem
using System;
class GFG {
      
    /* Returns the best obtainable 
       price for a rod of length
       n and price[] as prices of 
       different pieces */
    static int cutRod(int []price, int n)
    {
        if (n <= 0)
            return 0;
        int max_val = int.MinValue;
  
        // Recursively cut the rod in
        // different pieces and compare
        // different configurations
        for (int i = 0; i < n; i++)
            max_val = Math.Max(max_val, price[i] + 
                        cutRod(price, n - i - 1));
  
        return max_val;
    }
  
    // Driver Code
    public static void Main()
    {
        int []arr = new int[] {1, 5, 8, 9, 10, 17, 17, 20};
        int size = arr.Length;
        Console.WriteLine("Maximum Obtainable Value is "+
                                        cutRod(arr, size));

163
Chapter 13. DP-13 | Cutting a Rod

    }
}
  
// This code is contributed by Sam007

PHP

<?php
// A Naive recursive solution for 
// Rod cutting problem
  
/* Returns the best obtainable
   price for a rod of length n and 
   price[] as prices of different 
   pieces */
function cutRod( $price, $n)
{
  
    if ($n <= 0)
        return 0;
    $max_val = PHP_INT_MIN;
      
    // Recursively cut the rod in different
    // pieces and compare different 
    // configurations
    for ($i = 0; $i < $n; $i++)
            $max_val = max($max_val, $price[$i] + 
                    cutRod($price, $n - $i - 1));
      
    return $max_val;
}
  
    // Driver Code
    $arr = array(1, 5, 8, 9, 10, 17, 17, 20);
    $size =count($arr);
    echo "Maximum Obtainable Value is "
               , cutRod($arr, $size);
  
// This code is contributed anuj_67.
?>

Output:

Maximum Obtainable Value is 22

Considering the above implementation, following is recursion tree for a Rod of length 4.

164
Chapter 13. DP-13 | Cutting a Rod

cR() ---> cutRod()

cR(4)
/ /
/ /
cR(3) cR(2) cR(1) cR(0)
/ | / |
/ | / |
cR(2) cR(1) cR(0) cR(1) cR(0) cR(0)
/ | |
/ | |
cR(1) cR(0) cR(0) cR(0)
/
/
CR(0)

In the above partial recursion tree, cR(2) is being solved twice. We can see that there are
many subproblems which are solved again and again. Since same suproblems are called
again, this problem has Overlapping Subprolems property. So the Rod Cutting problem has
both properties (see thisand this) of a dynamic programming problem. Like other typical
Dynamic Programming(DP) problems, recomputations of same subproblems can be avoided
by constructing a temporary array val[] in bottom up manner.
C++

// A Dynamic Programming solution for Rod cutting problem


#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 cutRod(int price[], int n)
{
   int val[n+1];
   val[0] = 0;
   int i, j;
  
   // Build the table val[] in bottom up manner and return the last entry
   // from the table
   for (i = 1; i<=n; i++)
   {
       int max_val = INT_MIN;
       for (j = 0; j < i; j++)
         max_val = max(max_val, price[j] + val[i-j-1]);

165
Chapter 13. DP-13 | Cutting a Rod

       val[i] = max_val;
   }
  
   return val[n];
}
  
/* Driver program to test above functions */
int main()
{
    int arr[] = {1, 5, 8, 9, 10, 17, 17, 20};
    int size = sizeof(arr)/sizeof(arr[0]);
    printf("Maximum Obtainable Value is %dn", cutRod(arr, size));
    getchar();
    return 0;
}

Java

// A Dynamic Programming solution for Rod cutting problem


class RodCutting
{
    /* Returns the best obtainable price for a rod of
       length n and price[] as prices of different pieces */
    static int cutRod(int price[],int n)
    {
        int val[] = new int[n+1];
        val[0] = 0;
  
        // Build the table val[] in bottom up manner and return
        // the last entry from the table
        for (int i = 1; i<=n; i++)
        {
            int max_val = Integer.MIN_VALUE;
            for (int j = 0; j < i; j++)
                max_val = Math.max(max_val, 
                                   price[j] + val[i-j-1]);
            val[i] = max_val;
        }
  
        return val[n];
    }
  
    /* Driver program to test above functions */
    public static void main(String args[])
    {
        int arr[] = new int[] {1, 5, 8, 9, 10, 17, 17, 20};
        int size = arr.length;
        System.out.println("Maximum Obtainable Value is " +

166
Chapter 13. DP-13 | Cutting a Rod

                            cutRod(arr, size));
    }
}
/* This code is contributed by Rajat Mishra */

Python

# A Dynamic Programming solution for Rod cutting problem


INT_MIN = -32767
  
# Returns the best obtainable price for a rod of length n and
# price[] as prices of different pieces
def cutRod(price, n):
    val = [0 for x in range(n+1)]
    val[0] = 0
  
    # Build the table val[] in bottom up manner and return
    # the last entry from the table
    for i in range(1, n+1):
        max_val = INT_MIN
        for j in range(i):
             max_val = max(max_val, price[j] + val[i-j-1])
        val[i] = max_val
  
    return val[n]
  
# Driver program to test above functions
arr = [1, 5, 8, 9, 10, 17, 17, 20]
size = len(arr)
print("Maximum Obtainable Value is " + str(cutRod(arr, size)))
  
# This code is contributed by Bhavya Jain

C#

// A Dynamic Programming solution 


// for Rod cutting problem
using System;
class GFG {
  
    /* Returns the best obtainable 
       price for a rod of length n
       and price[] as prices of 
       different pieces */
    static int cutRod(int []price,int n)
    {
        int []val = new int[n + 1];

167
Chapter 13. DP-13 | Cutting a Rod

        val[0] = 0;
  
        // Build the table val[] in
        // bottom up manner and return
        // the last entry from the table
        for (int i = 1; i<=n; i++)
        {
            int max_val = int.MinValue;
            for (int j = 0; j < i; j++)
                max_val = Math.Max(max_val, 
                          price[j] + val[i - j - 1]);
            val[i] = max_val;
        }
  
        return val[n];
    }
      
    // Driver Code
    public static void Main()
    {
        int []arr = new int[] {1, 5, 8, 9, 10, 17, 17, 20};
        int size = arr.Length;
        Console.WriteLine("Maximum Obtainable Value is " +
                                        cutRod(arr, size));
          
    }
}
  
// This code is contributed by Sam007

PHP

<?php
// A Dynamic Programming solution for
// Rod cutting problem
  
/* Returns the best obtainable price 
for a rod of length n and price[] as
prices of different pieces */
function cutRod( $price, $n)
{
    $val = array();
    $val[0] = 0;
    $i; $j;
      
    // Build the table val[] in bottom 
    // up manner and return the last
    // entry from the table

168
Chapter 13. DP-13 | Cutting a Rod

    for ($i = 1; $i <= $n; $i++)


    {
        $max_val = PHP_INT_MIN;
          
        for ($j = 0; $j < $i; $j++)
            $max_val = max($max_val, 
             $price[$j] + $val[$i-$j-1]);
        $val[$i] = $max_val;
    }
      
    return $val[$n];
}
  
// Driver program to test above functions
$arr = array(1, 5, 8, 9, 10, 17, 17, 20);
$size = count($arr);
echo "Maximum Obtainable Value is ", 
                      cutRod($arr, $size);
      
// This code is contributed by anuj_67.
?>

Output:

Maximum Obtainable Value is 22

Time Complexity of the above implementation is O(n^2) which is much better than the
worst-case time complexity of Naive Recursive implementation.
Improved By : Sam007, vt_m, aniketmaurya

Source

https://www.geeksforgeeks.org/cutting-a-rod-dp-13/

169
Chapter 14

DP-14 | Maximum Sum


Increasing Subsequence

Maximum Sum Increasing Subsequence | DP-14 - GeeksforGeeks


Given an array of n positive integers. Write a program to find the sum of maximum sum
subsequence of the given array such that the intgers in the subsequence are sorted in in-
creasing order. For example, if input is {1, 101, 2, 3, 100, 4, 5}, then output should be 106
(1 + 2 + 3 + 100), if the input array is {3, 4, 5, 10}, then output should be 22 (3 + 4 + 5
+ 10) and if the input array is {10, 5, 4, 3}, then output should be 10

Solution
This problem is a variation of standard Longest Increasing Subsequence (LIS) problem. We
need a slight change in the Dynamic Programming solution of LIS problem. All we need to
change is to use sum as a criteria instead of length of increasing subsequence.
Following are the Dynamic Programming solution to the problem :
C/C++

/* Dynamic Programming implementation 


of Maximum Sum Increasing Subsequence 
(MSIS) problem */
#include<stdio.h>
  
/* maxSumIS() returns the maximum 
   sum of increasing subsequence
   in arr[] of size n */
int maxSumIS(int arr[], int n)
{
    int i, j, max = 0;
    int msis[n];
  

170
Chapter 14. DP-14 | Maximum Sum Increasing Subsequence

    /* Initialize msis values


       for all indexes */
    for ( i = 0; i < n; i++ )
        msis[i] = arr[i];
  
    /* Compute maximum sum values 
       in bottom up manner */
    for ( i = 1; i < n; i++ )
        for ( j = 0; j < i; j++ )
            if (arr[i] > arr[j] && 
                msis[i] < msis[j] + arr[i])
                msis[i] = msis[j] + arr[i];
  
    /* Pick maximum of
       all msis values */
    for ( i = 0; i < n; i++ )
        if ( max < msis[i] )
            max = msis[i];
  
    return max;
}
  
// Driver Code
int main()
{
    int arr[] = {1, 101, 2, 3, 100, 4, 5};
    int n = sizeof(arr)/sizeof(arr[0]);
    printf("Sum of maximum sum increasing " 
            "subsequence is %d\n",
              maxSumIS( arr, n ) );
    return 0;
}

Java

/* Dynamic Programming Java 


   implementation of Maximum Sum
   Increasing Subsequence (MSIS)
   problem */
class GFG
{
    /* maxSumIS() returns the 
    maximum sum of increasing
    subsequence in arr[] of size n */
    static int maxSumIS(int arr[], int n)
    {
        int i, j, max = 0;
        int msis[] = new int[n];

171
Chapter 14. DP-14 | Maximum Sum Increasing Subsequence

  
        /* Initialize msis values 
           for all indexes */
        for (i = 0; i < n; i++)
            msis[i] = arr[i];
  
        /* Compute maximum sum values
           in bottom up manner */
        for (i = 1; i < n; i++)
            for (j = 0; j < i; j++)
                if (arr[i] > arr[j] &&
                    msis[i] < msis[j] + arr[i])
                    msis[i] = msis[j] + arr[i];
  
        /* Pick maximum of all
           msis values */
        for (i = 0; i < n; i++)
            if (max < msis[i])
                max = msis[i];
  
        return max;
    }
  
    // Driver code
    public static void main(String args[])
    {
        int arr[] = new int[]{1, 101, 2, 3, 100, 4, 5};
        int n = arr.length;
        System.out.println("Sum of maximum sum "+
                            "increasing subsequence is "+
                              maxSumIS(arr, n));
    }
}
  
// This code is contributed 
// by Rajat Mishra 

Python

# Dynamic Programming bsed Python 


# implementation of Maximum Sum 
# Increasing Subsequence (MSIS)
# problem
  
# maxSumIS() returns the maximum 
# sum of increasing subsequence 
# in arr[] of size n
def maxSumIS(arr, n):

172
Chapter 14. DP-14 | Maximum Sum Increasing Subsequence

    max = 0
    msis = [0 for x in range(n)]
  
    # Initialize msis values
    # for all indexes
    for i in range(n):
        msis[i] = arr[i]
  
    # Compute maximum sum 
    # values in bottom up manner
    for i in range(1, n):
        for j in range(i):
            if (arr[i] > arr[j] and
                msis[i] < msis[j] + arr[i]):
                msis[i] = msis[j] + arr[i]
  
    # Pick maximum of
    # all msis values
    for i in range(n):
        if max < msis[i]:
            max = msis[i]
  
    return max
  
# Driver Code
arr = [1, 101, 2, 3, 100, 4, 5]
n = len(arr)
print("Sum of maximum sum increasing " + 
                     "subsequence is " +
                  str(maxSumIS(arr, n)))
  
# This code is contributed 
# by Bhavya Jain

C#

// Dynamic Programming C# implementation


// of Maximum Sum Increasing Subsequence
// (MSIS) problem 
using System;
class GFG {
      
    // maxSumIS() returns the 
    // maximum sum of increasing
    // subsequence in arr[] of size n 
    static int maxSumIS( int []arr, int n )
    {
        int i, j, max = 0;

173
Chapter 14. DP-14 | Maximum Sum Increasing Subsequence

        int []msis = new int[n];


  
        /* Initialize msis values
           for all indexes */
        for ( i = 0; i < n; i++ )
            msis[i] = arr[i];
  
        /* Compute maximum sum values
           in bottom up manner */
        for ( i = 1; i < n; i++ )
            for ( j = 0; j < i; j++ )
                if ( arr[i] > arr[j] &&
                    msis[i] < msis[j] + arr[i])
                    msis[i] = msis[j] + arr[i];
  
        /* Pick maximum of all 
           msis values */
        for ( i = 0; i < n; i++ )
            if ( max < msis[i] )
                max = msis[i];
  
        return max;
    }
      
    // Driver Code
    public static void Main()
    {
        int []arr = new int[]{1, 101, 2, 3, 100, 4, 5};
        int n = arr.Length;
        Console.WriteLine("Sum of maximum sum increasing "+
                                        " subsequence is "+
        maxSumIS(arr, n));
    }
}
  
// This code is contributed by Sam007

PHP

<?php
// Dynamic Programming implementation
// of Maximum Sum Increasing
// Subsequence (MSIS) problem 
  
// maxSumIS() returns the maximum 
// sum of increasing subsequence
// in arr[] of size n 
function maxSumIS($arr, $n)

174
Chapter 14. DP-14 | Maximum Sum Increasing Subsequence

{
    $max = 0;
    $msis= array($n);
  
    // Initialize msis values
    // for all indexes 
    for($i = 0; $i < $n; $i++ )
        $msis[$i] = $arr[$i];
  
    // Compute maximum sum values
    // in bottom up manner 
    for($i = 1; $i < $n; $i++)
        for($j = 0; $j < $i; $j++)
            if ($arr[$i] > $arr[$j] && 
                $msis[$i] < $msis[$j] + $arr[$i])
                $msis[$i] = $msis[$j] + $arr[$i];
  
    // Pick maximum of all msis values
    for($i = 0;$i < $n; $i++ )
        if ($max < $msis[$i] )
            $max = $msis[$i];
  
    return $max;
}
  
    // Driver Code
    $arr = array(1, 101, 2, 3, 100, 4, 5);
    $n = count($arr);
    echo "Sum of maximum sum increasing subsequence is " 
                                   .maxSumIS( $arr, $n );
          
// This code is contributed by Sam007
?>

Output :

Sum of maximum sum increasing subsequence is 106

Time Complexity: O(n^2)

Improved By : Sam007, ParulShandilya

175
Chapter 14. DP-14 | Maximum Sum Increasing Subsequence

Source

https://www.geeksforgeeks.org/maximum-sum-increasing-subsequence-dp-14/

176
Chapter 15

DP-15 | Longest Bitonic


Subsequence

Longest Bitonic Subsequence | DP-15 - GeeksforGeeks


Given an array arr[0 … n-1] containing n positive integers, a subsequenceof arr[] is called
Bitonic if it is first increasing, then decreasing. Write a function that takes an array as
argument and returns the length of the longest bitonic subsequence.
A sequence, sorted in increasing order is considered Bitonic with the decreasing part as
empty. Similarly, decreasing order sequence is considered Bitonic with the increasing part
as empty.
Examples:

Input arr[] = {1, 11, 2, 10, 4, 5, 2, 1};


Output: 6 (A Longest Bitonic Subsequence of length 6 is 1, 2, 10, 4, 2, 1)

Input arr[] = {12, 11, 40, 5, 3, 1}


Output: 5 (A Longest Bitonic Subsequence of length 5 is 12, 11, 5, 3, 1)

Input arr[] = {80, 60, 30, 40, 20, 10}


Output: 5 (A Longest Bitonic Subsequence of length 5 is 80, 60, 30, 20, 10)

Source: Microsoft Interview Question


Solution
This problem is a variation of standard Longest Increasing Subsequence (LIS) problem.
Let the input array be arr[] of length n. We need to construct two arrays lis[] and lds[]
using Dynamic Programming solution of LIS problem. lis[i] stores the length of the Longest
Increasing subsequence ending with arr[i]. lds[i] stores the length of the longest Decreasing
subsequence starting from arr[i]. Finally, we need to return the max value of lis[i] + lds[i] –
1 where i is from 0 to n-1.

177
Chapter 15. DP-15 | Longest Bitonic Subsequence

Following is C++ implementation of the above Dynamic Programming solution.

C++

/* Dynamic Programming implementation of longest bitonic subsequence problem */


#include<stdio.h>
#include<stdlib.h>
  
/* lbs() returns the length of the Longest Bitonic Subsequence in
    arr[] of size n. The function mainly creates two temporary arrays
    lis[] and lds[] and returns the maximum lis[i] + lds[i] - 1.
  
    lis[i] ==> Longest Increasing subsequence ending with arr[i]
    lds[i] ==> Longest decreasing subsequence starting with arr[i]
*/
int lbs( int arr[], int n )
{
   int i, j;
  
   /* Allocate memory for LIS[] and initialize LIS values as 1 for
      all indexes */
   int *lis = new int[n];
   for (i = 0; i < n; i++)
      lis[i] = 1;
  
   /* Compute LIS values from left to right */
   for (i = 1; i < n; i++)
      for (j = 0; j < i; j++)
         if (arr[i] > arr[j] && lis[i] < lis[j] + 1)
            lis[i] = lis[j] + 1;
  
   /* Allocate memory for lds and initialize LDS values for
      all indexes */
   int *lds = new int [n];
   for (i = 0; i < n; i++)
      lds[i] = 1;
  
   /* Compute LDS values from right to left */
   for (i = n-2; i >= 0; i--)
      for (j = n-1; j > i; j--)
         if (arr[i] > arr[j] && lds[i] < lds[j] + 1)
            lds[i] = lds[j] + 1;
  
  
   /* Return the maximum value of lis[i] + lds[i] - 1*/
   int max = lis[0] + lds[0] - 1;
   for (i = 1; i < n; i++)
     if (lis[i] + lds[i] - 1 > max)

178
Chapter 15. DP-15 | Longest Bitonic Subsequence

         max = lis[i] + lds[i] - 1;


   return max;
}
  
/* Driver program to test above function */
int main()
{
  int arr[] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5,
              13, 3, 11, 7, 15};
  int n = sizeof(arr)/sizeof(arr[0]);
  printf("Length of LBS is %d\n", lbs( arr, n ) );
  return 0;
}

Java

/* Dynamic Programming implementation in Java for longest bitonic


   subsequence problem */
import java.util.*;
import java.lang.*;
import java.io.*;
  
class LBS
{
    /* lbs() returns the length of the Longest Bitonic Subsequence in
    arr[] of size n. The function mainly creates two temporary arrays
    lis[] and lds[] and returns the maximum lis[i] + lds[i] - 1.
  
    lis[i] ==> Longest Increasing subsequence ending with arr[i]
    lds[i] ==> Longest decreasing subsequence starting with arr[i]
    */
    static int lbs( int arr[], int n )
    {
        int i, j;
  
        /* Allocate memory for LIS[] and initialize LIS values as 1 for
            all indexes */
        int[] lis = new int[n];
        for (i = 0; i < n; i++)
            lis[i] = 1;
  
        /* Compute LIS values from left to right */
        for (i = 1; i < n; i++)
            for (j = 0; j < i; j++)
                if (arr[i] > arr[j] && lis[i] < lis[j] + 1)
                    lis[i] = lis[j] + 1;
  
        /* Allocate memory for lds and initialize LDS values for

179
Chapter 15. DP-15 | Longest Bitonic Subsequence

            all indexes */
        int[] lds = new int [n];
        for (i = 0; i < n; i++)
            lds[i] = 1;
  
        /* Compute LDS values from right to left */
        for (i = n-2; i >= 0; i--)
            for (j = n-1; j > i; j--)
                if (arr[i] > arr[j] && lds[i] < lds[j] + 1)
                    lds[i] = lds[j] + 1;
  
  
        /* Return the maximum value of lis[i] + lds[i] - 1*/
        int max = lis[0] + lds[0] - 1;
        for (i = 1; i < n; i++)
            if (lis[i] + lds[i] - 1 > max)
                max = lis[i] + lds[i] - 1;
  
        return max;
    }
  
    public static void main (String[] args)
    {
        int arr[] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5,
                    13, 3, 11, 7, 15};
        int n = arr.length;
        System.out.println("Length of LBS is "+ lbs( arr, n ));
    }
}

Python

# Dynamic Programming implementation of longest bitonic subsequence problem


"""
lbs() returns the length of the Longest Bitonic Subsequence in
arr[] of size n. The function mainly creates two temporary arrays
lis[] and lds[] and returns the maximum lis[i] + lds[i] - 1.
  
lis[i] ==> Longest Increasing subsequence ending with arr[i]
lds[i] ==> Longest decreasing subsequence starting with arr[i]
"""
  
def lbs(arr):
    n = len(arr)
  
  
    # allocate memory for LIS[] and initialize LIS values as 1
    # for all indexes

180
Chapter 15. DP-15 | Longest Bitonic Subsequence

    lis = [1 for i in range(n+1)]


  
    # Compute LIS values from left to right
    for i in range(1 , n):
        for j in range(0 , i):
            if ((arr[i] > arr[j]) and (lis[i] < lis[j] +1)):
                lis[i] = lis[j] + 1
  
    # allocate memory for LDS and initialize LDS values for
    # all indexes
    lds = [1 for i in range(n+1)]
      
    # Compute LDS values from right to left
    for i in reversed(range(n-1)): #loop from n-2 downto 0
        for j in reversed(range(i-1 ,n)): #loop from n-1 downto i-1
            if(arr[i] > arr[j] and lds[i] < lds[j] + 1):
                lds[i] = lds[j] + 1 
  
  
    # Return the maximum value of (lis[i] + lds[i] - 1)
    maximum = lis[0] + lds[0] - 1
    for i in range(1 , n):
        maximum = max((lis[i] + lds[i]-1), maximum)
      
    return maximum
  
# Driver program to test the above function
arr =  [0 , 8 , 4, 12, 2, 10 , 6 , 14 , 1 , 9 , 5 , 13,
        3, 11 , 7 , 15]
print "Length of LBS is",lbs(arr)
  
# This code is contributed by Nikhil Kumar Singh(nickzuck_007)

C#

/* Dynamic Programming implementation in 


   C# for longest bitonic subsequence problem */
using System;
  
class LBS {
      
    /* lbs() returns the length of the Longest Bitonic Subsequence in
    arr[] of size n. The function mainly creates two temporary arrays
    lis[] and lds[] and returns the maximum lis[i] + lds[i] - 1.
  
    lis[i] ==> Longest Increasing subsequence ending with arr[i]
    lds[i] ==> Longest decreasing subsequence starting with arr[i]
    */

181
Chapter 15. DP-15 | Longest Bitonic Subsequence

    static int lbs(int[] arr, int n)


    {
        int i, j;
  
        /* Allocate memory for LIS[] and initialize 
           LIS values as 1 for all indexes */
        int[] lis = new int[n];
        for (i = 0; i < n; i++)
            lis[i] = 1;
  
        /* Compute LIS values from left to right */
        for (i = 1; i < n; i++)
            for (j = 0; j < i; j++)
                if (arr[i] > arr[j] && lis[i] < lis[j] + 1)
                    lis[i] = lis[j] + 1;
  
        /* Allocate memory for lds and initialize LDS values for
            all indexes */
        int[] lds = new int[n];
        for (i = 0; i < n; i++)
            lds[i] = 1;
  
        /* Compute LDS values from right to left */
        for (i = n - 2; i >= 0; i--)
            for (j = n - 1; j > i; j--)
                if (arr[i] > arr[j] && lds[i] < lds[j] + 1)
                    lds[i] = lds[j] + 1;
  
        /* Return the maximum value of lis[i] + lds[i] - 1*/
        int max = lis[0] + lds[0] - 1;
        for (i = 1; i < n; i++)
            if (lis[i] + lds[i] - 1 > max)
                max = lis[i] + lds[i] - 1;
  
        return max;
    }
      
    // Driver code
    public static void Main()
    {
        int[] arr = { 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5,
                                      13, 3, 11, 7, 15 };
        int n = arr.Length;
        Console.WriteLine("Length of LBS is " + lbs(arr, n));
    }
}
  
// This code is contributed by vt_m.

182
Chapter 15. DP-15 | Longest Bitonic Subsequence

Output:

Length of LBS is 7

Time Complexity: O(n^2)


Auxiliary Space: O(n)

Source

https://www.geeksforgeeks.org/longest-bitonic-subsequence-dp-15/

183
Chapter 16

DP-16 | Floyd Warshall


Algorithm

Floyd Warshall Algorithm | DP-16 - GeeksforGeeks


The Floyd Warshall Algorithm is for solving the All Pairs Shortest Path problem. The
problem is to find shortest distances between every pair of vertices in a given edge weighted
directed Graph.
Example:

Input:
graph[][] = { {0, 5, INF, 10},
{INF, 0, 3, INF},
{INF, INF, 0, 1},
{INF, INF, INF, 0} }
which represents the following graph
10
(0)------->(3)
| /|\
5 | |
| | 1
\|/ |
(1)------->(2)
3
Note that the value of graph[i][j] is 0 if i is equal to j
And graph[i][j] is INF (infinite) if there is no edge from vertex i to j.

Output:
Shortest distance matrix
0 5 8 9
INF 0 3 4

184
Chapter 16. DP-16 | Floyd Warshall Algorithm

INF INF 0 1
INF INF INF 0

Floyd Warshall Algorithm


We initialize the solution matrix same as the input graph matrix as a first step. Then we
update the solution matrix by considering all vertices as an intermediate vertex. The idea
is to one by one pick all vertices and updates all shortest paths which include the picked
vertex as an intermediate vertex in the shortest path. When we pick vertex number k as
an intermediate vertex, we already have considered vertices {0, 1, 2, .. k-1} as intermediate
vertices. For every pair (i, j) of the source and destination vertices respectively, there are
two possible cases.
1) k is not an intermediate vertex in shortest path from i to j. We keep the value of dist[i][j]
as it is.
2) k is an intermediate vertex in shortest path from i to j. We update the value of dist[i][j]
as dist[i][k] + dist[k][j].
The following figure shows the above optimal substructure property in the all-pairs shortest
path problem.

Following is implementations of the Floyd Warshall algorithm.

C/C++

// C Program for Floyd Warshall Algorithm


#include<stdio.h>
  
// Number of vertices in the graph
#define V 4
  
/* Define Infinite as a large enough value. This value will be used
  for vertices not connected to each other */
#define INF 99999
  
// A function to print the solution matrix
void printSolution(int dist[][V]);
  
// Solves the all-pairs shortest path problem using Floyd Warshall algorithm
void floydWarshall (int graph[][V])
{
    /* dist[][] will be the output matrix that will finally have the shortest 
      distances between every pair of vertices */
    int dist[V][V], i, j, k;

185
Chapter 16. DP-16 | Floyd Warshall Algorithm

  
    /* Initialize the solution matrix same as input graph matrix. Or 
       we can say the initial values of shortest distances are based
       on shortest paths considering no intermediate vertex. */
    for (i = 0; i < V; i++)
        for (j = 0; j < V; j++)
            dist[i][j] = graph[i][j];
  
    /* Add all vertices one by one to the set of intermediate vertices.
      ---> Before start of an iteration, we have shortest distances between all
      pairs of vertices such that the shortest distances consider only the
      vertices in set {0, 1, 2, .. k-1} as intermediate vertices.
      ----> After the end of an iteration, vertex no. k is added to the set of
      intermediate vertices and the set becomes {0, 1, 2, .. k} */
    for (k = 0; k < V; k++)
    {
        // Pick all vertices as source one by one
        for (i = 0; i < V; i++)
        {
            // Pick all vertices as destination for the
            // above picked source
            for (j = 0; j < V; j++)
            {
                // If vertex k is on the shortest path from
                // i to j, then update the value of dist[i][j]
                if (dist[i][k] + dist[k][j] < dist[i][j])
                    dist[i][j] = dist[i][k] + dist[k][j];
            }
        }
    }
  
    // Print the shortest distance matrix
    printSolution(dist);
}
  
/* A utility function to print solution */
void printSolution(int dist[][V])
{
    printf ("The following matrix shows the shortest distances"
            " between every pair of vertices \n");
    for (int i = 0; i < V; i++)
    {
        for (int j = 0; j < V; j++)
        {
            if (dist[i][j] == INF)
                printf("%7s", "INF");
            else
                printf ("%7d", dist[i][j]);

186
Chapter 16. DP-16 | Floyd Warshall Algorithm

        }
        printf("\n");
    }
}
  
// driver program to test above function
int main()
{
    /* Let us create the following weighted graph
            10
       (0)------->(3)
        |         /|\
      5 |          |
        |          | 1
       \|/         |
       (1)------->(2)
            3           */
    int graph[V][V] = { {0,   5,  INF, 10},
                        {INF, 0,   3, INF},
                        {INF, INF, 0,   1},
                        {INF, INF, INF, 0}
                      };
  
    // Print the solution
    floydWarshall(graph);
    return 0;
}

Java

// A Java program for Floyd Warshall All Pairs Shortest


// Path algorithm.
import java.util.*;
import java.lang.*;
import java.io.*;
  
  
class AllPairShortestPath
{
    final static int INF = 99999, V = 4;
  
    void floydWarshall(int graph[][])
    {
        int dist[][] = new int[V][V];
        int i, j, k;
  
        /* Initialize the solution matrix same as input graph matrix.
           Or we can say the initial values of shortest distances

187
Chapter 16. DP-16 | Floyd Warshall Algorithm

           are based on shortest paths considering no intermediate


           vertex. */
        for (i = 0; i < V; i++)
            for (j = 0; j < V; j++)
                dist[i][j] = graph[i][j];
  
        /* Add all vertices one by one to the set of intermediate
           vertices.
          ---> Before start of an iteration, we have shortest
               distances between all pairs of vertices such that
               the shortest distances consider only the vertices in
               set {0, 1, 2, .. k-1} as intermediate vertices.
          ----> After the end of an iteration, vertex no. k is added
                to the set of intermediate vertices and the set
                becomes {0, 1, 2, .. k} */
        for (k = 0; k < V; k++)
        {
            // Pick all vertices as source one by one
            for (i = 0; i < V; i++)
            {
                // Pick all vertices as destination for the
                // above picked source
                for (j = 0; j < V; j++)
                {
                    // If vertex k is on the shortest path from
                    // i to j, then update the value of dist[i][j]
                    if (dist[i][k] + dist[k][j] < dist[i][j])
                        dist[i][j] = dist[i][k] + dist[k][j];
                }
            }
        }
  
        // Print the shortest distance matrix
        printSolution(dist);
    }
  
    void printSolution(int dist[][])
    {
        System.out.println("The following matrix shows the shortest "+
                         "distances between every pair of vertices");
        for (int i=0; i<V; ++i)
        {
            for (int j=0; j<V; ++j)
            {
                if (dist[i][j]==INF)
                    System.out.print("INF ");
                else
                    System.out.print(dist[i][j]+"   ");

188
Chapter 16. DP-16 | Floyd Warshall Algorithm

            }
            System.out.println();
        }
    }
  
    // Driver program to test above function
    public static void main (String[] args)
    {
        /* Let us create the following weighted graph
           10
        (0)------->(3)
        |         /|\
        5 |          |
        |          | 1
        \|/         |
        (1)------->(2)
           3           */
        int graph[][] = { {0,   5,  INF, 10},
                          {INF, 0,   3, INF},
                          {INF, INF, 0,   1},
                          {INF, INF, INF, 0}
                        };
        AllPairShortestPath a = new AllPairShortestPath();
  
        // Print the solution
        a.floydWarshall(graph);
    }
}
  
// Contributed by Aakash Hasija

Python

# Python Program for Floyd Warshall Algorithm


  
# Number of vertices in the graph
V = 4 
  
# Define infinity as the large enough value. This value will be
# used for vertices not connected to each other
INF  = 99999
  
# Solves all pair shortest path via Floyd Warshall Algorithm
def floydWarshall(graph):
  
    """ dist[][] will be the output matrix that will finally
        have the shortest distances between every pair of vertices """
    """ initializing the solution matrix same as input graph matrix

189
Chapter 16. DP-16 | Floyd Warshall Algorithm

    OR we can say that the initial values of shortest distances


    are based on shortest paths considering no 
    intermediate vertices """
    dist = map(lambda i : map(lambda j : j , i) , graph)
      
    """ Add all vertices one by one to the set of intermediate
     vertices.
     ---> Before start of an iteration, we have shortest distances
     between all pairs of vertices such that the shortest
     distances consider only the vertices in the set 
    {0, 1, 2, .. k-1} as intermediate vertices.
      ----> After the end of a iteration, vertex no. k is
     added to the set of intermediate vertices and the 
    set becomes {0, 1, 2, .. k}
    """
    for k in range(V):
  
        # pick all vertices as source one by one
        for i in range(V):
  
            # Pick all vertices as destination for the
            # above picked source
            for j in range(V):
  
                # If vertex k is on the shortest path from 
                # i to j, then update the value of dist[i][j]
                dist[i][j] = min(dist[i][j] ,
                                  dist[i][k]+ dist[k][j]
                                )
    printSolution(dist)
  
  
# A utility function to print the solution
def printSolution(dist):
    print "Following matrix shows the shortest distances\
 between every pair of vertices"
    for i in range(V):
        for j in range(V):
            if(dist[i][j] == INF):
                print "%7s" %("INF"),
            else:
                print "%7d\t" %(dist[i][j]),
            if j == V-1:
                print ""
  
  
  
# Driver program to test the above program

190
Chapter 16. DP-16 | Floyd Warshall Algorithm

# Let us create the following weighted graph


"""
            10
       (0)------->(3)
        |         /|\
      5 |          |
        |          | 1
       \|/         |
       (1)------->(2)
            3           """
graph = [[0,5,INF,10],
             [INF,0,3,INF],
             [INF, INF, 0,   1],
             [INF, INF, INF, 0]
        ]
# Print the solution
floydWarshall(graph);
# This code is contributed by Nikhil Kumar Singh(nickzuck_007)

C#

// A C# program for Floyd Warshall All 


// Pairs Shortest Path algorithm.
  
using System;
  
public class AllPairShortestPath
{
    readonly static int INF = 99999, V = 4;
  
    void floydWarshall(int[,] graph)
    {
        int[,] dist = new int[V, V];
        int i, j, k;
  
        // Initialize the solution matrix 
        // same as input graph matrix
        // Or we can say the initial 
        // values of shortest distances
        // are based on shortest paths 
        // considering no intermediate
        // vertex
        for (i = 0; i < V; i++) {
            for (j = 0; j < V; j++) {
                dist[i, j] = graph[i, j];
            }
        }
  

191
Chapter 16. DP-16 | Floyd Warshall Algorithm

        /* Add all vertices one by one to 


        the set of intermediate vertices.
        ---> Before start of a iteration,
             we have shortest distances
             between all pairs of vertices
             such that the shortest distances
             consider only the vertices in
             set {0, 1, 2, .. k-1} as 
             intermediate vertices.
        ---> After the end of a iteration, 
             vertex no. k is added
             to the set of intermediate
             vertices and the set
             becomes {0, 1, 2, .. k} */
        for (k = 0; k < V; k++)
        {
            // Pick all vertices as source
            // one by one
            for (i = 0; i < V; i++)
            {
                // Pick all vertices as destination
                // for the above picked source
                for (j = 0; j < V; j++)
                {
                    // If vertex k is on the shortest
                    // path from i to j, then update
                    // the value of dist[i][j]
                    if (dist[i, k] + dist[k, j] < dist[i, j]) 
                    {
                        dist[i, j] = dist[i, k] + dist[k, j];
                    }
                }
            }
        }
  
        // Print the shortest distance matrix
        printSolution(dist);
    }
  
    void printSolution(int[,] dist)
    {
        Console.WriteLine("Following matrix shows the shortest "+
                        "distances between every pair of vertices");
        for (int i = 0; i < V; ++i)
        {
            for (int j = 0; j < V; ++j)
            {
                if (dist[i, j] == INF) {

192
Chapter 16. DP-16 | Floyd Warshall Algorithm

                    Console.Write("INF ");
                } else {
                    Console.Write(dist[i, j] + " ");
                }
            }
              
            Console.WriteLine();
        }
    }
  
    // Driver Code
    public static void Main(string[] args)
    {
        /* Let us create the following
           weighted graph
              10
        (0)------->(3)
        |         /|\
        5 |         |
        |         | 1
        \|/         |
        (1)------->(2)
             3             */
        int[,] graph = { {0, 5, INF, 10},
                        {INF, 0, 3, INF},
                        {INF, INF, 0, 1},
                        {INF, INF, INF, 0}
                        };
          
        AllPairShortestPath a = new AllPairShortestPath();
  
        // Print the solution
        a.floydWarshall(graph);
    }
}
  
// This article is contributed by 
// Abdul Mateen Mohammed

Output:

Following matrix shows the shortest distances between every pair of vertices
0 5 8 9
INF 0 3 4
INF INF 0 1
INF INF INF 0

193
Chapter 16. DP-16 | Floyd Warshall Algorithm

Time Complexity: O(V^3)


The above program only prints the shortest distances. We can modify the solution to print
the shortest paths also by storing the predecessor information in a separate 2D matrix.
Also, the value of INF can be taken as INT_MAX from limits.h to make sure that we
handle maximum possible value. When we take INF as INT_MAX, we need to change the
if condition in the above program to avoid arithmetic overflow.

#include

#define INF INT_MAX


..........................
if ( dist[i][k] != INF &&
dist[k][j] != INF &&
dist[i][k] + dist[k][j] < dist[i][j]
)
dist[i][j] = dist[i][k] + dist[k][j];
...........................

Improved By : Abdul Mateen Mohammed

Source

https://www.geeksforgeeks.org/floyd-warshall-algorithm-dp-16/

194
Chapter 17

DP-17 | Palindrome
Partitioning

Palindrome Partitioning | DP-17 - GeeksforGeeks


Given a string, a partitioning of the string is a palindrome partitioning if every substring of
the partition is a palindrome. For example, “aba|b|bbabb|a|b|aba” is a palindrome partition-
ing of “ababbbabbababa”. Determine the fewest cuts needed for palindrome partitioning of
a given string. For example, minimum 3 cuts are needed for “ababbbabbababa”. The three
cuts are “a|babbbab|b|ababa”. If a string is palindrome, then minimum 0 cuts are needed.
If a string of length n containing all different characters, then minimum n-1 cuts are needed.

This problem is a variation of Matrix Chain Multiplication problem. If the string is palin-
drome, then we simply return 0. Else, like the Matrix Chain Multiplication problem, we try
making cuts at all possible places, recursively calculate the cost for each cut and return the
minimum value.
Let the given string be str and minPalPartion() be the function that returns the fewest cuts
needed for palindrome partitioning. following is the optimal substructure property.

// i is the starting index and j is the ending index. i must be passed as 0 and j as n-1
minPalPartion(str, i, j) = 0 if i == j. // When string is of length 1.
minPalPartion(str, i, j) = 0 if str[i..j] is palindrome.

195
Chapter 17. DP-17 | Palindrome Partitioning

// If none of the above conditions is true, then minPalPartion(str, i, j) can be


// calculated recursively using the following formula.
minPalPartion(str, i, j) = Min { minPalPartion(str, i, k) + 1 +
minPalPartion(str, k+1, j) }
where k varies from i to j-1

Following is Dynamic Programming solution. It stores the solutions to subproblems in two


arrays P[][] and C[][], and reuses the calculated values.

C/C++

// Dynamic Programming Solution for Palindrome Partitioning Problem


#include <stdio.h>
#include <string.h>
#include <limits.h>
   
// A utility function to get minimum of two integers
int min (int a, int b) { return (a < b)? a : b; }
   
// Returns the minimum number of cuts needed to partition a string
// such that every part is a palindrome
int minPalPartion(char *str)
{
    // Get the length of the string
    int n = strlen(str);
   
    /* Create two arrays to build the solution in bottom up manner
       C[i][j] = Minimum number of cuts needed for palindrome partitioning
                 of substring str[i..j]
       P[i][j] = true if substring str[i..j] is palindrome, else false
       Note that C[i][j] is 0 if P[i][j] is true */
    int C[n][n];
    bool P[n][n];
   
    int i, j, k, L; // different looping variables
   
    // Every substring of length 1 is a palindrome
    for (i=0; i<n; i++)
    {
        P[i][i] = true;
        C[i][i] = 0;
    }
   
    /* L is substring length. Build the solution in bottom up manner by
       considering all substrings of length starting from 2 to n.
       The loop structure is same as Matrx Chain Multiplication problem (
       See https://www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/ )*/

196
Chapter 17. DP-17 | Palindrome Partitioning

    for (L=2; L<=n; L++)


    {
        // For substring of length L, set different possible starting indexes
        for (i=0; i<n-L+1; i++)
        {
            j = i+L-1; // Set ending index
   
            // If L is 2, then we just need to compare two characters. Else
            // need to check two corner characters and value of P[i+1][j-1]
            if (L == 2)
                P[i][j] = (str[i] == str[j]);
            else
                P[i][j] = (str[i] == str[j]) && P[i+1][j-1];
   
            // IF str[i..j] is palindrome, then C[i][j] is 0
            if (P[i][j] == true)
                C[i][j] = 0;
            else
            {
                // Make a cut at every possible location starting from i to j,
                // and get the minimum cost cut.
                C[i][j] = INT_MAX;
                for (k=i; k<=j-1; k++)
                    C[i][j] = min (C[i][j], C[i][k] + C[k+1][j]+1);
            }
        }
    }
   
    // Return the min cut value for complete string. i.e., str[0..n-1]
    return C[0][n-1];
}
   
// Driver program to test above function
int main()
{
   char str[] = "ababbbabbababa";
   printf("Min cuts needed for Palindrome Partitioning is %d",
           minPalPartion(str));
   return 0;
}

Java

// Java Code for Palindrome Partitioning 


// Problem
public class GFG 
{              
    // Returns the minimum number of cuts needed

197
Chapter 17. DP-17 | Palindrome Partitioning

    // to partition a string such that every 


    // part is a palindrome
    static int minPalPartion(String str)
    {
        // Get the length of the string
        int n = str.length();
        
        /* Create two arrays to build the solution
           in bottom up manner
           C[i][j] = Minimum number of cuts needed 
                     for palindrome partitioning
                     of substring str[i..j]
           P[i][j] = true if substring str[i..j] is
                     palindrome, else false
           Note that C[i][j] is 0 if P[i][j] is
           true */
        int[][] C = new int[n][n];
        boolean[][] P = new boolean[n][n];
        
        int i, j, k, L; // different looping variables
        
        // Every substring of length 1 is a palindrome
        for (i = 0; i < n; i++)
        {
            P[i][i] = true;
            C[i][i] = 0;
        }
        
        /* L is substring length. Build the solution in
         bottom up manner by considering all substrings
         of length starting from 2 to n. The loop 
         structure is same as Matrx Chain Multiplication
         problem (
        See https://www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/ )*/
        for (L = 2; L <= n; L++)
        {
            // For substring of length L, set different
            // possible starting indexes
            for (i = 0; i < n - L + 1; i++)
            {
                j = i + L - 1; // Set ending index
        
                // If L is 2, then we just need to 
                // compare two characters. Else need to
                // check two corner characters and value 
                // of P[i+1][j-1]
                if (L == 2)
                    P[i][j] = (str.charAt(i) == 

198
Chapter 17. DP-17 | Palindrome Partitioning

                                str.charAt(j));
                else
                    P[i][j] = (str.charAt(i) == 
                            str.charAt(j)) && P[i+1][j-1];
        
                // IF str[i..j] is palindrome, then 
                // C[i][j] is 0
                if (P[i][j] == true)
                    C[i][j] = 0;
                else
                {
                    // Make a cut at every possible
                    // localtion starting from i to j,
                    // and get the minimum cost cut.
                    C[i][j] = Integer.MAX_VALUE;
                    for (k = i; k <= j - 1; k++)
                        C[i][j] = Integer.min(C[i][j], 
                                C[i][k] + C[k+1][j] + 1);
                }
            }
        }
        
        // Return the min cut value for complete 
        // string. i.e., str[0..n-1]
        return C[0][n-1];
    }
        
    // Driver program to test above function
    public static void main(String args[])
    {
       String str = "ababbbabbababa";
       System.out.println("Min cuts needed for "+
                       "Palindrome Partitioning is "+
                          minPalPartion(str));
    }
}
// This code is contributed by Sumit Ghosh

C#

// C# Code for Palindrome Partitioning 


// Problem
using System;
  
class GFG
{
    // Returns the minimum number of cuts needed
    // to partition a string such that every 

199
Chapter 17. DP-17 | Palindrome Partitioning

    // part is a palindrome


    static int minPalPartion(String str)
    {
        // Get the length of the string
        int n = str.Length;
          
        /* Create two arrays to build the solution
        in bottom up manner
        C[i][j] = Minimum number of cuts needed 
                    for palindrome partitioning
                    of substring str[i..j]
        P[i][j] = true if substring str[i..j] is
                    palindrome, else false
        Note that C[i][j] is 0 if P[i][j] is
        true */
        int[,] C = new int[n, n];
        bool[,] P = new bool[n, n];
          
        int i, j, k, L; // different looping variables
          
        // Every substring of length 1 is a palindrome
        for (i = 0; i < n; i++)
        {
            P[i, i] = true;
            C[i, i] = 0;
        }
          
        /* L is substring length. Build the solution in
        bottom up manner by considering all substrings
        of length starting from 2 to n. The loop 
        structure is same as Matrx Chain Multiplication
        problem (
        See https://www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/ )*/
        for (L = 2; L <= n; L++)
        {
            // For substring of length L, set different
            // possible starting indexes
            for (i = 0; i < n - L + 1; i++)
            {
                j = i + L - 1; // Set ending index
          
                // If L is 2, then we just need to 
                // compare two characters. Else need to
                // check two corner characters and value 
                // of P[i+1][j-1]
                if (L == 2)
                    P[i,j] = (str[i] == str[j]);
                else

200
Chapter 17. DP-17 | Palindrome Partitioning

                    P[i,j] = (str[i] == str[j]) &&


                             P[i + 1, j - 1];
          
                // IF str[i..j] is palindrome, then 
                // C[i][j] is 0
                if (P[i, j] == true)
                    C[i, j] = 0;
                else
                {
                    // Make a cut at every possible
                    // localtion starting from i to j,
                    // and get the minimum cost cut.
                    C[i, j] = int.MaxValue;
                    for (k = i; k <= j - 1; k++)
                        C[i, j] = Math.Min(C[i, j], C[i, k] 
                                  + C[k + 1, j] + 1);
                }
            }
        }
          
        // Return the min cut value for complete 
        // string. i.e., str[0..n-1]
        return C[0, n - 1];
    }
          
    // Driver program 
    public static void Main()
    {
    String str = "ababbbabbababa";
    Console.Write("Min cuts needed for "+
                  "Palindrome Partitioning is "+
                  minPalPartion(str));
    }
}
  
// This code is contributed by Sam007

Output:

Min cuts needed for Palindrome Partitioning is 3

Time Complexity: O(n3 )


An optimization to above approach
In above approach, we can calculate minimum cut while finding all palindromic substring.
If we find all palindromic substring 1st and then we calculate minimum cut, time complexity
will reduce to O(n2 ).

201
Chapter 17. DP-17 | Palindrome Partitioning

Thanks for Vivek for suggesting this optimization.

C++

// Dynamic Programming Solution for Palindrome Partitioning Problem


#include <stdio.h>
#include <string.h>
#include <limits.h>
   
// A utility function to get minimum of two integers
int min (int a, int b) { return (a < b)? a : b; }
   
// Returns the minimum number of cuts needed to partition a string
// such that every part is a palindrome
int minPalPartion(char *str)
{
    // Get the length of the string
    int n = strlen(str);
   
    /* Create two arrays to build the solution in bottom up manner
       C[i] = Minimum number of cuts needed for palindrome partitioning
                 of substring str[0..i]
       P[i][j] = true if substring str[i..j] is palindrome, else false
       Note that C[i] is 0 if P[0][i] is true */
    int C[n];
    bool P[n][n];
   
    int i, j, k, L; // different looping variables
   
    // Every substring of length 1 is a palindrome
    for (i=0; i<n; i++)
    {
        P[i][i] = true;
    }
   
    /* L is substring length. Build the solution in bottom up manner by
       considering all substrings of length starting from 2 to n. */
    for (L=2; L<=n; L++)
    {
        // For substring of length L, set different possible starting indexes
        for (i=0; i<n-L+1; i++)
        {
            j = i+L-1; // Set ending index
   
            // If L is 2, then we just need to compare two characters. Else
            // need to check two corner characters and value of P[i+1][j-1]
            if (L == 2)
                P[i][j] = (str[i] == str[j]);

202
Chapter 17. DP-17 | Palindrome Partitioning

            else
                P[i][j] = (str[i] == str[j]) && P[i+1][j-1];
        }
    }
  
    for (i=0; i<n; i++)
    {
        if (P[0][i] == true)
            C[i] = 0;
        else
        {
            C[i] = INT_MAX;
            for(j=0;j<i;j++)
            {
                if(P[j+1][i] == true && 1+C[j]<C[i])
                    C[i]=1+C[j];
            }
        }
    }
   
    // Return the min cut value for complete string. i.e., str[0..n-1]
    return C[n-1];
}
   
// Driver program to test above function
int main()
{
   char str[] = "ababbbabbababa";
   printf("Min cuts needed for Palindrome Partitioning is %d",
           minPalPartion(str));
   return 0;
}

Java

// Java Code for Palindrome Partitioning 


// Problem
public class GFG 
{            
    // Returns the minimum number of cuts needed
    // to partition a string such that every part
    // is a palindrome
    static int minPalPartion(String str)
    {
        // Get the length of the string
        int n = str.length();
        
        /* Create two arrays to build the solution

203
Chapter 17. DP-17 | Palindrome Partitioning

        in bottom up manner


           C[i] = Minimum number of cuts needed for
           palindrome partitioning of substring
           str[0..i]
           P[i][j] = true if substring str[i..j] is 
           palindrome, else false
           Note that C[i] is 0 if P[0][i] is true */
        int[] C = new int[n];
        boolean[][] P = new boolean[n][n];
        
        int i, j, k, L; // different looping variables
        
        // Every substring of length 1 is a palindrome
        for (i = 0; i < n; i++)
        {
            P[i][i] = true;
        }
        
        /* L is substring length. Build the solution 
        in bottom up manner by considering all substrings 
        of length starting from 2 to n. */
        for (L = 2; L <= n; L++)
        {
            // For substring of length L, set different 
            // possible starting indexes
            for (i = 0; i < n - L + 1; i++)
            {
                j = i + L - 1; // Set ending index
        
                // If L is 2, then we just need to 
                // compare two characters. Else need to 
                // check two corner characters and value
                // of P[i+1][j-1]
                if (L == 2)
                    P[i][j] = (str.charAt(i) ==
                                 str.charAt(j));
                else
                    P[i][j] = (str.charAt(i) == 
                           str.charAt(j)) && P[i+1][j-1];
            }
        }
       
        for (i = 0; i < n; i++)
        {
            if (P[0][i] == true)
                C[i] = 0;
            else
            {

204
Chapter 17. DP-17 | Palindrome Partitioning

                C[i] = Integer.MAX_VALUE;
                for(j = 0; j < i; j++)
                {
                    if(P[j+1][i] == true && 1 +
                                 C[j] < C[i])
                        C[i] = 1 + C[j];
                }
            }
        }
        
        // Return the min cut value for complete
        // string. i.e., str[0..n-1]
        return C[n-1];
    }
      
    // Driver program to test above function
    public static void main(String args[])
    {
       String str = "ababbbabbababa";
       System.out.println("Min cuts needed for "+
                          "Palindrome Partitioning"+
                          " is "+ minPalPartion(str));
    }
}
// This code is contributed by Sumit Ghosh

C#

// C# Code for Palindrome Partitioning 


// Problem
using System;
  
class GFG
{
              
    // Returns the minimum number of cuts needed
    // to partition a string such that every part
    // is a palindrome
    static int minPalPartion(String str)
    {
        // Get the length of the string
        int n = str.Length;
          
        /* Create two arrays to build the solution
        in bottom up manner
        C[i] = Minimum number of cuts needed for
        palindrome partitioning of substring
        str[0..i]

205
Chapter 17. DP-17 | Palindrome Partitioning

        P[i][j] = true if substring str[i..j] is 


        palindrome, else false
        Note that C[i] is 0 if P[0][i] is true */
        int[] C = new int[n];
        bool[,] P = new bool[n,n];
          
        int i, j, L; // different looping variables
          
        // Every substring of length 1 is a palindrome
        for (i = 0; i < n; i++)
        {
            P[i,i] = true;
        }
          
        /* L is substring length. Build the solution 
        in bottom up manner by considering all substrings 
        of length starting from 2 to n. */
        for (L = 2; L <= n; L++)
        {
            // For substring of length L, set different 
            // possible starting indexes
            for (i = 0; i < n - L + 1; i++)
            {
                j = i + L - 1; // Set ending index
          
                // If L is 2, then we just need to 
                // compare two characters. Else need to 
                // check two corner characters and value
                // of P[i+1][j-1]
                if (L == 2)
                    P[i,j] = (str[i] == str[j]);
                else
                    P[i,j] = (str[i] == str[j]) && P[i+1,j-1];
            }
        }
      
        for (i = 0; i < n; i++)
        {
            if (P[0,i] == true)
                C[i] = 0;
            else
            {
                C[i] = int.MaxValue;
                for(j = 0; j < i; j++)
                {
                    if(P[j+1,i] == true && 1 + C[j] < C[i])
                        C[i] = 1 + C[j];
                }

206
Chapter 17. DP-17 | Palindrome Partitioning

            }
        }
          
        // Return the min cut value for complete
        // string. i.e., str[0..n-1]
        return C[n-1];
    }
      
    // Driver program 
    public static void Main()
    {
    String str = "ababbbabbababa";
    Console.Write("Min cuts needed for "+
                        "Palindrome Partitioning"+
                        " is "+ minPalPartion(str));
    }
}
  
// This code is contributed by Sam007

Output:

Min cuts needed for Palindrome Partitioning is 3

Time Complexity: O(n2 )

Source

https://www.geeksforgeeks.org/palindrome-partitioning-dp-17/

207
Chapter 18

DP-18 | Partition problem

Partition problem | DP-18 - GeeksforGeeks


Partition problem is to determine whether a given set can be partitioned into two subsets
such that the sum of elements in both subsets is same.
Examples

arr[] = {1, 5, 11, 5}


Output: true
The array can be partitioned as {1, 5, 5} and {11}

arr[] = {1, 5, 3}
Output: false
The array cannot be partitioned into equal sum sets.

Following are the two main steps to solve this problem:


1) Calculate sum of the array. If sum is odd, there can not be two subsets with equal sum,
so return false.
2) If sum of array elements is even, calculate sum/2 and find a subset of array with sum
equal to sum/2.
The first step is simple. The second step is crucial, it can be solved either using recursion
or Dynamic Programming.
Recursive Solution
Following is the recursive property of the second step mentioned above.

Let isSubsetSum(arr, n, sum/2) be the function that returns true if


there is a subset of arr[0..n-1] with sum equal to sum/2

The isSubsetSum problem can be divided into two subproblems

208
Chapter 18. DP-18 | Partition problem

a) isSubsetSum() without considering last element


(reducing n to n-1)
b) isSubsetSum considering the last element
(reducing sum/2 by arr[n-1] and n to n-1)
If any of the above the above subproblems return true, then return true.
isSubsetSum (arr, n, sum/2) = isSubsetSum (arr, n-1, sum/2) ||
isSubsetSum (arr, n-1, sum/2 - arr[n-1])

C/C++

// A  recursive C program for partition problem


#include <stdio.h>
  
// A utility function that returns true if there is 
// a subset of arr[] with sun equal to given sum
bool isSubsetSum (int arr[], int n, int sum)
{
   // Base Cases
   if (sum == 0)
     return true;
   if (n == 0 && sum != 0)
     return false;
  
   // If last element is greater than sum, then 
   // ignore it
   if (arr[n-1] > sum)
     return isSubsetSum (arr, n-1, sum);
  
   /* else, check if sum can be obtained by any of 
      the following
      (a) including the last element
      (b) excluding the last element
   */
   return isSubsetSum (arr, n-1, sum) || 
          isSubsetSum (arr, n-1, sum-arr[n-1]);
}
  
// Returns true if arr[] can be partitioned in two
//  subsets of equal sum, otherwise false
bool findPartiion (int arr[], int n)
{
    // Calculate sum of the elements in array
    int sum = 0;
    for (int i = 0; i < n; i++)
       sum += arr[i];
  
    // If sum is odd, there cannot be two subsets 
    // with equal sum

209
Chapter 18. DP-18 | Partition problem

    if (sum%2 != 0)
       return false;
  
    // Find if there is subset with sum equal to
    // half of total sum
    return isSubsetSum (arr, n, sum/2);
}
  
// Driver program to test above function
int main()
{
  int arr[] = {3, 1, 5, 9, 12};
  int n = sizeof(arr)/sizeof(arr[0]);
  if (findPartiion(arr, n) == true)
     printf("Can be divided into two subsets "
            "of equal sum");
  else
     printf("Can not be divided into two subsets"
            " of equal sum");
  return 0;
}

Java

// A recursive Java solution for partition problem


import java.io.*;
  
class Partition
{
    // A utility function that returns true if there is a
    // subset of arr[] with sun equal to given sum
    static boolean isSubsetSum (int arr[], int n, int sum)
    {
        // Base Cases
        if (sum == 0)
            return true;
        if (n == 0 && sum != 0)
            return false;
  
        // If last element is greater than sum, then ignore it
        if (arr[n-1] > sum)
            return isSubsetSum (arr, n-1, sum);
  
        /* else, check if sum can be obtained by any of
           the following
        (a) including the last element
        (b) excluding the last element
        */

210
Chapter 18. DP-18 | Partition problem

        return isSubsetSum (arr, n-1, sum) ||


               isSubsetSum (arr, n-1, sum-arr[n-1]);
    }
  
    // Returns true if arr[] can be partitioned in two
    // subsets of equal sum, otherwise false
    static boolean findPartition (int arr[], int n)
    {
        // Calculate sum of the elements in array
        int sum = 0;
        for (int i = 0; i < n; i++)
            sum += arr[i];
  
        // If sum is odd, there cannot be two subsets
        // with equal sum
        if (sum%2 != 0)
            return false;
  
        // Find if there is subset with sum equal to half
        // of total sum
        return isSubsetSum (arr, n, sum/2);
    }
  
    /*Driver function to check for above function*/
    public static void main (String[] args)
    {
  
        int arr[] = {3, 1, 5, 9, 12};
        int n = arr.length;
        if (findPartition(arr, n) == true)
            System.out.println("Can be divided into two "+
                                "subsets of equal sum");
        else
            System.out.println("Can not be divided into " +
                                "two subsets of equal sum");
    }
}
/* This code is contributed by Devesh Agrawal */

Python3

# A recursive Python3 program for 


# partition problem
  
# A utility function that returns 
# true if there is a subset of
# arr[] with sun equal to given sum
def isSubsetSum (arr, n, sum):

211
Chapter 18. DP-18 | Partition problem

    # Base Cases


    if sum == 0:
        return True
    if n == 0 and sum != 0:
        return False
  
    # If last element is greater than sum, then 
    # ignore it
    if arr[n-1] > sum:
        return isSubsetSum (arr, n-1, sum)
  
    ''' else, check if sum can be obtained by any of 
    the following
    (a) including the last element
    (b) excluding the last element'''
      
    return isSubsetSum (arr, n-1, sum) or isSubsetSum (arr, n-1, sum-arr[n-1])
  
# Returns true if arr[] can be partitioned in two
# subsets of equal sum, otherwise false
def findPartion (arr, n):
    # Calculate sum of the elements in array
    sum = 0
    for i in range(0, n):
        sum += arr[i]
    # If sum is odd, there cannot be two subsets 
    # with equal sum
    if sum % 2 != 0:
        return false
  
    # Find if there is subset with sum equal to
    # half of total sum
    return isSubsetSum (arr, n, sum // 2)
  
# Driver program to test above function
arr = [3, 1, 5, 9, 12]
n = len(arr)
if findPartion(arr, n) == True:
    print ("Can be divided into two subsets of equal sum")
else:
    print ("Can not be divided into two subsets of equal sum")
      
# This code is contributed by shreyanshi_arun.     

C#

// A recursive C# solution for partition problem


using System;

212
Chapter 18. DP-18 | Partition problem

  
class GFG
{
    // A utility function that returns true if there is a
    // subset of arr[] with sun equal to given sum
    static bool isSubsetSum (int []arr, int n, int sum)
    {
        // Base Cases
        if (sum == 0)
            return true;
        if (n == 0 && sum != 0)
            return false;
  
        // If last element is greater than sum, then ignore it
        if (arr[n-1] > sum)
            return isSubsetSum (arr, n-1, sum);
  
        /* else, check if sum can be obtained by any of
        the following
        (a) including the last element
        (b) excluding the last element
        */
        return isSubsetSum (arr, n-1, sum) ||
               isSubsetSum (arr, n-1, sum-arr[n-1]);
    }
  
    // Returns true if arr[] can be partitioned in two
    // subsets of equal sum, otherwise false
    static bool findPartition (int []arr, int n)
    {
        // Calculate sum of the elements in array
        int sum = 0;
        for (int i = 0; i < n; i++)
            sum += arr[i];
  
        // If sum is odd, there cannot be two subsets
        // with equal sum
        if (sum%2 != 0)
            return false;
  
        // Find if there is subset with sum equal to half
        // of total sum
        return isSubsetSum (arr, n, sum/2);
    }
  
    // Driver function 
    public static void Main ()
    {

213
Chapter 18. DP-18 | Partition problem

  
        int []arr = {3, 1, 5, 9, 12};
        int n = arr.Length;
        if (findPartition(arr, n) == true)
            Console.Write("Can be divided into two "+
                          "subsets of equal sum");
        else
            Console.Write("Can not be divided into " +
                          "two subsets of equal sum");
    }
}
  
// This code is contributed by Sam007

Output:

Can be divided into two subsets of equal sum

Time Complexity: O(2^n) In worst case, this solution tries two possibilities (whether to
include or exclude) for every element.
Dynamic Programming Solution
The problem can be solved using dynamic programming when the sum of the elements is
not too big. We can create a 2D array part[][] of size (sum/2)*(n+1). And we can construct
the solution in bottom up manner such that every filled entry has following property

part[i][j] = true if a subset of {arr[0], arr[1], ..arr[j-1]} has sum


equal to i, otherwise false

C/C++

// A Dynamic Programming based C program to partition problem


#include <stdio.h>
  
// Returns true if arr[] can be partitioned in two subsets of
// equal sum, otherwise false
bool findPartiion (int arr[], int n)
{
    int sum = 0;
    int i, j;
    
    // Caculcate sun of all elements
    for (i = 0; i < n; i++)
      sum += arr[i];

214
Chapter 18. DP-18 | Partition problem

      
    if (sum%2 != 0)  
       return false;
    
    bool part[sum/2+1][n+1];
      
    // initialize top row as true
    for (i = 0; i <= n; i++)
      part[0][i] = true;
        
    // initialize leftmost column, except part[0][0], as 0
    for (i = 1; i <= sum/2; i++)
      part[i][0] = false;     
       
     // Fill the partition table in botton up manner 
     for (i = 1; i <= sum/2; i++)  
     {
       for (j = 1; j <= n; j++)  
       {
         part[i][j] = part[i][j-1];
         if (i >= arr[j-1])
           part[i][j] = part[i][j] || part[i - arr[j-1]][j-1];
       }        
     }    
       
    /* // uncomment this part to print table 
     for (i = 0; i <= sum/2; i++)  
     {
       for (j = 0; j <= n; j++)  
          printf ("%4d", part[i][j]);
       printf("\n");
     } */ 
       
     return part[sum/2][n];
}     
  
// Driver program to test above funtion
int main()
{
  int arr[] = {3, 1, 1, 2, 2, 1};
  int n = sizeof(arr)/sizeof(arr[0]);
  if (findPartiion(arr, n) == true)
     printf("Can be divided into two subsets of equal sum");
  else
     printf("Can not be divided into two subsets of equal sum");
  getchar();
  return 0;
}

215
Chapter 18. DP-18 | Partition problem

Java

// A dynamic programming based Java program for partition problem


import java.io.*;
  
class Partition {
  
    // Returns true if arr[] can be partitioned in two subsets of
    // equal sum, otherwise false
    static boolean findPartition (int arr[], int n)
    {
        int sum = 0;
        int i, j;
  
        // Caculcate sun of all elements
        for (i = 0; i < n; i++)
            sum += arr[i];
  
        if (sum%2 != 0)
            return false;
  
        boolean part[][]=new boolean[sum/2+1][n+1];
  
        // initialize top row as true
        for (i = 0; i <= n; i++)
            part[0][i] = true;
  
        // initialize leftmost column, except part[0][0], as 0
        for (i = 1; i <= sum/2; i++)
            part[i][0] = false;
  
        // Fill the partition table in botton up manner
        for (i = 1; i <= sum/2; i++)
        {
            for (j = 1; j <= n; j++)
            {
                part[i][j] = part[i][j-1];
                if (i >= arr[j-1])
                    part[i][j] = part[i][j] ||
                                 part[i - arr[j-1]][j-1];
            }
        }
  
        /* // uncomment this part to print table
        for (i = 0; i <= sum/2; i++)
        {
            for (j = 0; j <= n; j++)
                printf ("%4d", part[i][j]);

216
Chapter 18. DP-18 | Partition problem

            printf("\n");
        } */
  
        return part[sum/2][n];
    }
  
    /*Driver function to check for above function*/
    public static void main (String[] args)
    {
        int arr[] = {3, 1, 1, 2, 2,1};
        int n = arr.length;
        if (findPartition(arr, n) == true)
            System.out.println("Can be divided into two "
                               "subsets of equal sum");
        else
            System.out.println("Can not be divided into"
                            " two subsets of equal sum");
  
    }
}
/* This code is contributed by Devesh Agrawal */

C#

// A dynamic programming based C# program 


// for partition problem
using System;
  
class GFG {
      
    // Returns true if arr[] can be partitioned 
    // in two subsets of equal sum, otherwise 
    // false
    static bool findPartition (int []arr, int n)
    {
          
        int sum = 0;
        int i, j;
  
        // Caculcate sun of all elements
        for (i = 0; i < n; i++)
            sum += arr[i];
  
        if (sum % 2 != 0)
            return false;
  
        bool [, ]part=new bool[sum / 2 + 1, n + 1];
  

217
Chapter 18. DP-18 | Partition problem

        // initialize top row as true


        for (i = 0; i <= n; i++)
            part[0, i] = true;
  
        // initialize leftmost column, except 
        // part[0][0], as 0
        for (i = 1; i <= sum/2; i++)
            part[i, 0] = false;
  
        // Fill the partition table in botton 
        // up manner
        for (i = 1; i <= sum/2; i++)
        {
            for (j = 1; j <= n; j++)
            {
                part[i, j] = part[i, j - 1];
                if (i >= arr[j - 1])
                    part[i, j] = part[i, j] ||
                    part[i - arr[j - 1],j - 1];
            }
        }
  
        /* // uncomment this part to print table
        for (i = 0; i <= sum/2; i++)
        {
            for (j = 0; j <= n; j++)
                printf ("%4d", part[i][j]);
            printf("\n");
        } */
  
        return part[sum / 2, n];
    }
  
    // Driver program to test above funtion
    public static void Main ()
    {
        int []arr = {3, 1, 1, 2, 2,1};
        int n = arr.Length;
          
        if (findPartition(arr, n) == true)
            Console.Write("Can be divided" 
                  + " into two subsets of"
                          + " equal sum");
        else
            Console.Write("Can not be " 
               + "divided into two subsets"
                      + " of equal sum");
  

218
Chapter 18. DP-18 | Partition problem

    }
}
  
// This code is contributed by Sam007.

Output:

Can be divided into two subsets of equal sum

Following diagram shows the values in partition table.

Time Complexity: O(sum*n)


Auxiliary Space: O(sum*n)
Please note that this solution will not be feasible for arrays with big sum.
References:
http://en.wikipedia.org/wiki/Partition_problem
Please write comments if you find anything incorrect, or you want to share more information
about the topic discussed above.

Source

https://www.geeksforgeeks.org/partition-problem-dp-18/

219
Chapter 19

DP-19 | Word Wrap Problem

Word Wrap Problem | DP-19 - GeeksforGeeks


Given a sequence of words, and a limit on the number of characters that can be put in one
line (line width). Put line breaks in the given sequence such that the lines are printed neatly.
Assume that the length of each word is smaller than the line width.
The word processors like MS Word do task of placing line breaks. The idea is to have
balanced lines. In other words, not have few lines with lots of extra spaces and some lines
with small amount of extra spaces.

The extra spaces includes spaces put at the end of every line except the last one.
The problem is to minimize the following total cost.
Cost of a line = (Number of extra spaces in the line)^3
Total Cost = Sum of costs for all lines

For example, consider the following string and line width M = 15


"Geeks for Geeks presents word wrap problem"

Following is the optimized arrangement of words in 3 lines


Geeks for Geeks
presents word
wrap problem

The total extra spaces in line 1, line 2 and line 3 are 0, 2 and 3 respectively.
So optimal value of total cost is 0 + 2*2 + 3*3 = 13

Please note that the total cost function is not sum of extra spaces, but sum of cubes (or
square is also used) of extra spaces. The idea behind this cost function is to balance the
spaces among lines. For example, consider the following two arrangement of same set of
words:

220
Chapter 19. DP-19 | Word Wrap Problem

1) There are 3 lines. One line has 3 extra spaces and all other lines have 0 extra spaces.
Total extra spaces = 3 + 0 + 0 = 3. Total cost = 3*3*3 + 0*0*0 + 0*0*0 = 27.
2) There are 3 lines. Each of the 3 lines has one extra space. Total extra spaces = 1 + 1 +
1 = 3. Total cost = 1*1*1 + 1*1*1 + 1*1*1 = 3.
Total extra spaces are 3 in both scenarios, but second arrangement should be preferred
because extra spaces are balanced in all three lines. The cost function with cubic sum
serves the purpose because the value of total cost in second scenario is less.
Method 1 (Greedy Solution)
The greedy solution is to place as many words as possible in the first line. Then do the
same thing for the second line and so on until all words are placed. This solution gives
optimal solution for many cases, but doesn’t give optimal solution in all cases. For example,
consider the following string “aaa bb cc ddddd” and line width as 6. Greedy method will
produce following output.

aaa bb
cc
ddddd

Extra spaces in the above 3 lines are 0, 4 and 1 respectively. So total cost is 0 + 64 + 1 =
65.
But the above solution is not the best solution. Following arrangement has more balanced
spaces. Therefore less value of total cost function.

aaa
bb cc
ddddd

Extra spaces in the above 3 lines are 3, 1 and 1 respectively. So total cost is 27 + 1 + 1 =
29.
Despite being sub-optimal in some cases, the greedy approach is used by many word pro-
cessors like MS Word and OpenOffice.org Writer.
Method 2 (Dynamic Programming)
The following Dynamic approach strictly follows the algorithm given in solution of Cormen
book. First we compute costs of all possible lines in a 2D table lc[][]. The value lc[i][j]
indicates the cost to put words from i to j in a single line where i and j are indexes of words
in the input sequences. If a sequence of words from i to j cannot fit in a single line, then
lc[i][j] is considered infinite (to avoid it from being a part of the solution). Once we have
the lc[][] table constructed, we can calculate total cost using following recursive formula. In
the following formula, C[j] is the optimized total cost for arranging words from 1 to j.

221
Chapter 19. DP-19 | Word Wrap Problem

The above recursion has overlapping subproblem property. For example, the solution of
subproblem c(2) is used by c(3), C(4) and so on. So Dynamic Programming is used to store
the results of subproblems. The array c[] can be computed from left to right, since each
value depends only on earlier values.
To print the output, we keep track of what words go on what lines, we can keep a parallel
p array that points to where each c value came from. The last line starts at word p[n] and
goes through word n. The previous line starts at word p[p[n]] and goes through word p[n?]
– 1, etc. The function printSolution() uses p[] to print the solution.
In the below program, input is an array l[] that represents lengths of words in a sequence.
The value l[i] indicates length of the ith word (i starts from 1) in theinput sequence.

C/C++

// A Dynamic programming solution for Word Wrap Problem


#include <limits.h>
#include <stdio.h>
#define INF INT_MAX
  
// A utility function to print the solution
int printSolution (int p[], int n);
  
// l[] represents lengths of different words in input sequence. For example, 
// l[] = {3, 2, 2, 5} is for a sentence like "aaa bb cc ddddd".  n is size of 
// l[] and M is line width (maximum no. of characters that can fit in a line)
void solveWordWrap (int l[], int n, int M)
{
    // For simplicity, 1 extra space is used in all below arrays 
  
    // extras[i][j] will have number of extra spaces if words from i 
    // to j are put in a single line
    int extras[n+1][n+1];  
  
    // lc[i][j] will have cost of a line which has words from 
    // i to j
    int lc[n+1][n+1];
   
    // c[i] will have total cost of optimal arrangement of words 
    // from 1 to i
    int c[n+1];
  

222
Chapter 19. DP-19 | Word Wrap Problem

    // p[] is used to print the solution.  


    int p[n+1];
  
    int i, j;
  
    // calculate extra spaces in a single line.  The value extra[i][j]
    // indicates extra spaces if words from word number i to j are
    // placed in a single line
    for (i = 1; i <= n; i++)
    {
        extras[i][i] = M - l[i-1];
        for (j = i+1; j <= n; j++)
            extras[i][j] = extras[i][j-1] - l[j-1] - 1;
    }
  
    // Calculate line cost corresponding to the above calculated extra
    // spaces. The value lc[i][j] indicates cost of putting words from
    // word number i to j in a single line
    for (i = 1; i <= n; i++)
    {
        for (j = i; j <= n; j++)
        {
            if (extras[i][j] < 0)
                lc[i][j] = INF;
            else if (j == n && extras[i][j] >= 0)
                lc[i][j] = 0;
            else
                lc[i][j] = extras[i][j]*extras[i][j];
        }
    }
  
    // Calculate minimum cost and find minimum cost arrangement.
    //  The value c[j] indicates optimized cost to arrange words
    // from word number 1 to j.
    c[0] = 0;
    for (j = 1; j <= n; j++)
    {
        c[j] = INF;
        for (i = 1; i <= j; i++)
        {
            if (c[i-1] != INF && lc[i][j] != INF && (c[i-1] + lc[i][j] < c[j]))
            {
                c[j] = c[i-1] + lc[i][j];
                p[j] = i;
            }
        }
    }
  

223
Chapter 19. DP-19 | Word Wrap Problem

    printSolution(p, n);
}
  
int printSolution (int p[], int n)
{
    int k;
    if (p[n] == 1)
        k = 1;
    else
        k = printSolution (p, p[n]-1) + 1;
    printf ("Line number %d: From word no. %d to %d \n", k, p[n], n);
    return k;
}
  
// Driver program to test above functions
int main()
{
    int l[] = {3, 2, 2, 5};
    int n = sizeof(l)/sizeof(l[0]);
    int M = 6;
    solveWordWrap (l, n, M);
    return 0;
}

Java

// A Dynamic programming solution for


// Word Wrap Problem in Java
public class WordWrap
{
  
    final int MAX = Integer.MAX_VALUE;
      
    // A utility function to print the solution
    int printSolution (int p[], int n)
    {
        int k;
        if (p[n] == 1)
        k = 1;
        else
        k = printSolution (p, p[n]-1) + 1;
        System.out.println("Line number" + " " + k + ": " + 
                    "From word no." +" "+ p[n] + " " + "to" + " " + n);
        return k;
    }
  
    // l[] represents lengths of different words in input sequence. For example,
    // l[] = {3, 2, 2, 5} is for a sentence like "aaa bb cc ddddd". n is size of

224
Chapter 19. DP-19 | Word Wrap Problem

    // l[] and M is line width (maximum no. of characters that can fit in a line)
    void solveWordWrap (int l[], int n, int M)
    {
        // For simplicity, 1 extra space is used in all below arrays
      
        // extras[i][j] will have number of extra spaces if words from i
        // to j are put in a single line
        int extras[][] = new int[n+1][n+1];
      
        // lc[i][j] will have cost of a line which has words from
        // i to j
        int lc[][]= new int[n+1][n+1];
      
        // c[i] will have total cost of optimal arrangement of words
        // from 1 to i
        int c[] = new int[n+1];
      
        // p[] is used to print the solution.
        int p[] =new int[n+1];
      
        // calculate extra spaces in a single line. The value extra[i][j]
        // indicates extra spaces if words from word number i to j are
        // placed in a single line
        for (int i = 1; i <= n; i++)
        {
            extras[i][i] = M - l[i-1];
            for (int j = i+1; j <= n; j++)
            extras[i][j] = extras[i][j-1] - l[j-1] - 1;
        }
          
        // Calculate line cost corresponding to the above calculated extra
        // spaces. The value lc[i][j] indicates cost of putting words from
        // word number i to j in a single line
        for (int i = 1; i <= n; i++)
        {
            for (int j = i; j <= n; j++)
            {
                if (extras[i][j] < 0)
                    lc[i][j] = MAX;
                else if (j == n && extras[i][j] >= 0)
                    lc[i][j] = 0;
                else
                    lc[i][j] = extras[i][j]*extras[i][j];
            }
        }
          
        // Calculate minimum cost and find minimum cost arrangement.
        // The value c[j] indicates optimized cost to arrange words

225
Chapter 19. DP-19 | Word Wrap Problem

        // from word number 1 to j.


        c[0] = 0;
        for (int j = 1; j <= n; j++)
        {
            c[j] = MAX;
            for (int i = 1; i <= j; i++)
            {
                if (c[i-1] != MAX && lc[i][j] != MAX && (c[i-1] + lc[i][j] < c[j]))
                {
                    c[j] = c[i-1] + lc[i][j];
                    p[j] = i;
                }
            }
        }
      
        printSolution(p, n);
    }
  
    public static void main(String args[])
    {
        WordWrap w = new WordWrap();
        int l[] = {3, 2, 2, 5};
        int n = l.length;
        int M = 6;
        w.solveWordWrap (l, n, M);
    }
}
  
// This code is contributed by Saket Kumar

C#

// A Dynamic programming solution for Word Wrap


// Problem in Java
using System;
  
public class GFG {
  
    static int MAX = int.MaxValue;
      
    // A utility function to print the solution
    static int printSolution (int []p, int n)
    {
        int k;
          
        if (p[n] == 1)
            k = 1;
        else

226
Chapter 19. DP-19 | Word Wrap Problem

            k = printSolution (p, p[n]-1) + 1;


              
        Console.WriteLine("Line number" + " "
                + k + ": From word no." + " "
                + p[n] + " " + "to" + " " + n);
        return k;
    }
  
    // l[] represents lengths of different 
    // words in input sequence. For example,
    // l[] = {3, 2, 2, 5} is for a sentence
    // like "aaa bb cc ddddd". n is size of
    // l[] and M is line width (maximum no. 
    // of characters that can fit in a line)
    static void solveWordWrap (int []l, int n, 
                                        int M)
    {
          
        // For simplicity, 1 extra space
        // is used in all below arrays
      
        // extras[i][j] will have number of
        // extra spaces if words from i
        // to j are put in a single line
        int [,]extras = new int[n+1,n+1];
      
        // lc[i][j] will have cost of a line 
        // which has words from i to j
        int [,]lc = new int[n+1,n+1];
      
        // c[i] will have total cost of
        // optimal arrangement of words 
        // from 1 to i
        int []c = new int[n+1];
      
        // p[] is used to print the solution.
        int []p = new int[n+1];
      
        // calculate extra spaces in a single 
        // line. The value extra[i][j] indicates
        // extra spaces if words from word number
        // i to j are placed in a single line
        for (int i = 1; i <= n; i++)
        {
            extras[i,i] = M - l[i-1];
              
            for (int j = i+1; j <= n; j++)
                extras[i,j] = extras[i,j-1]

227
Chapter 19. DP-19 | Word Wrap Problem

                                 - l[j-1] - 1;
        }
          
        // Calculate line cost corresponding to 
        // the above calculated extra spaces. The
        // value lc[i][j] indicates cost of 
        // putting words from word number i to 
        // j in a single line
        for (int i = 1; i <= n; i++)
        {
            for (int j = i; j <= n; j++)
            {
                if (extras[i,j] < 0)
                    lc[i,j] = MAX;
                else if (j == n && 
                              extras[i,j] >= 0)
                    lc[i,j] = 0;
                else
                    lc[i,j] = extras[i,j]
                                 * extras[i,j];
            }
        }
          
        // Calculate minimum cost and find 
        // minimum cost arrangement. The value
        // c[j] indicates optimized cost to
        // arrange words from word number
        // 1 to j.
        c[0] = 0;
        for (int j = 1; j <= n; j++)
        {
            c[j] = MAX;
            for (int i = 1; i <= j; i++)
            {
                if (c[i-1] != MAX && lc[i,j] 
                    != MAX && (c[i-1] + lc[i,j] 
                                       < c[j]))
                {
                    c[j] = c[i-1] + lc[i,j];
                    p[j] = i;
                }
            }
        }
      
        printSolution(p, n);
    }
  
    // Driver code

228
Chapter 19. DP-19 | Word Wrap Problem

    public static void Main()


    {
        int []l = {3, 2, 2, 5};
        int n = l.Length;
        int M = 6;
        solveWordWrap (l, n, M);
    }
}
  
// This code is contributed by nitin mittal.

Output:

Line number 1: From word no. 1 to 1


Line number 2: From word no. 2 to 3
Line number 3: From word no. 4 to 4

Time Complexity: O(n^2)


Auxiliary Space: O(n^2) The auxiliary space used in the above program cane be optimized
to O(n) (See the reference 2 for details)
Word Wrap problem ( Space optimized solution )
References:
http://en.wikipedia.org/wiki/Word_wrap
Improved By : nitin mittal

Source

https://www.geeksforgeeks.org/word-wrap-problem-dp-19/

229
Chapter 20

DP-20 | Maximum Length


Chain of Pairs

Maximum Length Chain of Pairs | DP-20 - GeeksforGeeks


You are given n pairs of numbers. In every pair, the first number is always smaller than the
second number. A pair (c, d) can follow another pair (a, b) if b < c. Chain of pairs can
be formed in this fashion. Find the longest chain which can be formed from a given set of
pairs.
Source: Amazon Interview | Set 2
For example, if the given pairs are {{5, 24}, {39, 60}, {15, 28}, {27, 40}, {50, 90} }, then
the longest chain that can be formed is of length 3, and the chain is {{5, 24}, {27, 40}, {50,
90}}
This problem is a variation of standard Longest Increasing Subsequence problem. Following
is a simple two step process.
1) Sort given pairs in increasing order of first (or smaller) element.
2) Now run a modified LIS process where we compare the second element of already finalized
LIS with the first element of new LIS being constructed.
The following code is a slight modification of method 2 of this post.

#include<stdio.h>
#include<stdlib.h>
  
// Structure for a pair
struct pair
{
  int a;
  int b;
};

230
Chapter 20. DP-20 | Maximum Length Chain of Pairs

  
// This function assumes that arr[] is sorted in increasing order
// according the first (or smaller) values in pairs.
int maxChainLength( struct pair arr[], int n)
{
   int i, j, max = 0;
   int *mcl = (int*) malloc ( sizeof( int ) * n );
  
   /* Initialize MCL (max chain length) values for all indexes */
   for ( i = 0; i < n; i++ )
      mcl[i] = 1;
  
   /* Compute optimized chain length values in bottom up manner */
   for ( i = 1; i < n; i++ )
      for ( j = 0; j < i; j++ )
         if ( arr[i].a > arr[j].b && mcl[i] < mcl[j] + 1)
            mcl[i] = mcl[j] + 1;
  
   // mcl[i] now stores the maximum chain length ending with pair i
  
   /* Pick maximum of all MCL values */
   for ( i = 0; i < n; i++ )
      if ( max < mcl[i] )
         max = mcl[i];
  
   /* Free memory to avoid memory leak */
   free( mcl );
  
   return max;
}
  
  
/* Driver program to test above function */
int main()
{
    struct pair arr[] = { {5, 24}, {15, 25},
                          {27, 40}, {50, 60} };
    int n = sizeof(arr)/sizeof(arr[0]);
    printf("Length of maximum size chain is %d\n",
           maxChainLength( arr, n ));
    return 0;
}

Java

class Pair{
    int a;
    int b;

231
Chapter 20. DP-20 | Maximum Length Chain of Pairs

      
    public Pair(int a, int b) {
        this.a = a;
        this.b = b;
    }
      
    // This function assumes that arr[] is sorted in increasing order
    // according the first (or smaller) values in pairs.
    static int maxChainLength(Pair arr[], int n)
    {
       int i, j, max = 0;
       int mcl[] = new int[n];
       
       /* Initialize MCL (max chain length) values for all indexes */
       for ( i = 0; i < n; i++ )
          mcl[i] = 1;
       
       /* Compute optimized chain length values in bottom up manner */
       for ( i = 1; i < n; i++ )
          for ( j = 0; j < i; j++ )
             if ( arr[i].a > arr[j].b && mcl[i] < mcl[j] + 1)
                mcl[i] = mcl[j] + 1;
       
       // mcl[i] now stores the maximum chain length ending with pair i
       
       /* Pick maximum of all MCL values */
       for ( i = 0; i < n; i++ )
          if ( max < mcl[i] )
             max = mcl[i];
       
       return max;
    }
  
    /* Driver program to test above function */
    public static void main(String[] args) 
    {
        Pair arr[] = new Pair[] {new Pair(5,24), new Pair(15, 25),
                                  new Pair (27, 40), new Pair(50, 60)};
        System.out.println("Length of maximum size chain is " + 
                                  maxChainLength(arr, arr.length));
    }
}

Python3

class Pair(object):
    def __init__(self, a, b):
        self.a = a

232
Chapter 20. DP-20 | Maximum Length Chain of Pairs

        self.b = b
  
# This function assumes that arr[] is sorted in increasing
# order according the first (or smaller) values in pairs.
def maxChainLength(arr, n):
      
    max = 0
  
    # Initialize MCL(max chain length) values for all indices
    mcl = [1 for i in range(n)]
  
    # Compute optimized chain length values in bottom up manner
    for i in range(1, n):
        for j in range(0, i):
            if (arr[i].a > arr[j].b and mcl[i] < mcl[j] + 1):
                mcl[i] = mcl[j] + 1
  
    # mcl[i] now stores the maximum
    # chain length ending with pair i
  
    # Pick maximum of all MCL values
    for i in range(n):
        if (max < mcl[i]):
            max = mcl[i]
  
    return max
  
# Driver program to test above function
arr = [Pair(5, 24), Pair(15, 25), Pair(27, 40), Pair(50, 60)]
  
print('Length of maximum size chain is',
      maxChainLength(arr, len(arr)))
  
# This code is contributed by Soumen Ghosh

C#

// Dynamic C# program to find 


// Maximum Length Chain of Pairs
using System;
  
class Pair {
    int a;
    int b;
      
    public Pair(int a, int b) 
    {
        this.a = a;

233
Chapter 20. DP-20 | Maximum Length Chain of Pairs

        this.b = b;
    }
      
    // This function assumes that arr[] 
    // is sorted in increasing order
    // according the first (or smaller) 
    // values in pairs.
    static int maxChainLength(Pair []arr, int n)
    {
        int i, j, max = 0;
        int []mcl = new int[n];
          
        // Initialize MCL (max chain length)
        // values for all indexes 
        for(i = 0; i < n; i++ )
            mcl[i] = 1;
          
        // Compute optimized chain length 
        // values in bottom up manner 
        for(i = 1; i < n; i++)
            for (j = 0; j < i; j++)
                if(arr[i].a > arr[j].b &&
                   mcl[i] < mcl[j] + 1)
                     
           // mcl[i] now stores the maximum 
          // chain length ending with pair i
          mcl[i] = mcl[j] + 1;
  
        // Pick maximum of all MCL values
        for ( i = 0; i < n; i++ )
            if (max < mcl[i] )
                max = mcl[i];
          
        return max;
    }
  
    // Driver Code
    public static void Main() 
    {
        Pair []arr = new Pair[] {new Pair(5,24), new Pair(15, 25),
                                 new Pair (27, 40), new Pair(50, 60)};
        Console.Write("Length of maximum size chain is " + 
                       maxChainLength(arr, arr.Length));
    }
}
  
// This code is contributed by nitin mittal.

234
Chapter 20. DP-20 | Maximum Length Chain of Pairs

Output:

Length of maximum size chain is 3

Time Complexity: O(n^2) where n is the number of pairs.


The given problem is also a variation of Activity Selection problemand can be solved in
(nLogn) time. To solve it as a activity selection problem, consider the first element of a
pair as start time in activity selection problem, and the second element of pair as end time.
Thanks to Palash for suggesting this approach.
Improved By : nitin mittal

Source

https://www.geeksforgeeks.org/maximum-length-chain-of-pairs-dp-20/

235
Chapter 21

DP-21 | Variations of LIS

Variations of LIS | DP-21 - GeeksforGeeks


We have discussed Dynamic Programming solution for Longest Increasing Subsequence prob-
lem in thispost and a O(nLogn) solution in thispost. Following are commonly asked varia-
tions of the standardLIS problem.
1. Building Bridges: Consider a 2-D map with a horizontal river passing through its
center. There are n cities on the southern bank with x-coordinates a(1) … a(n) and n
cities on the northern bank with x-coordinates b(1) … b(n). You want to connect as many
north-south pairs of cities as possible with bridges such that no two bridges cross. When
connecting cities, you can only connect city i on the northern bank to city i on the southern
bank.

8 1 4 3 5 2 6 7

--------------------------------------------

--------------------------------------------
1 2 3 4 5 6 7 8

Source:Dynamic Programming Practice Problems. The link also has well explained solution
for the problem.
2. Maximum Sum Increasing Subsequence: Given an array of n positive integers.
Write a program to find the maximum sum subsequence of the given array such that the
intgers in the subsequence are sorted in increasing order. For example, if input is {1, 101, 2,
3, 100, 4, 5}, then output should be {1, 2, 3, 100}. The solution to this problem has been
published here.
3. The Longest Chain You are given pairs of numbers. In a pair, the first number is
smaller with respect to the second number. Suppose you have two sets (a, b) and (c, d),

236
Chapter 21. DP-21 | Variations of LIS

the second set can follow the first set if b < c. So you can form a long chain in the similar
fashion. Find the longest chain which can be formed. The solution to this problem has been
published here.
4. Box Stacking You are given a set of n types of rectangular 3-D boxes, where the i^th
box has height h(i), width w(i) and depth d(i) (all real numbers). You want to create a
stack of boxes which is as tall as possible, but you can only stack a box on top of another
box if the dimensions of the 2-D base of the lower box are each strictly larger than those of
the 2-D base of the higher box. Of course, you can rotate a box so that any side functions
as its base. It is also allowable to use multiple instances of the same type of box.
Source:Dynamic Programming Practice Problems. The link also has well explained solution
for the problem.
Please write comments if you find anything incorrect, or you want to share more information
about the topic discussed above.

Source

https://www.geeksforgeeks.org/variations-of-lis-dp-21/

237
Chapter 22

DP-22 | Box Stacking Problem

Box Stacking Problem | DP-22 - GeeksforGeeks


You are given a set of n types of rectangular 3-D boxes, where the i^th box has height h(i),
width w(i) and depth d(i) (all real numbers). You want to create a stack of boxes which
is as tall as possible, but you can only stack a box on top of another box if the dimensions
of the 2-D base of the lower box are each strictly larger than those of the 2-D base of the
higher box. Of course, you can rotate a box so that any side functions as its base. It is also
allowable to use multiple instances of the same type of box.
Source: http://people.csail.mit.edu/bdean/6.046/dp/. The link also has video for expla-
nation of solution.

238
Chapter 22. DP-22 | Box Stacking Problem

The Box Stacking problem is a variation of LIS problem. We need to build a maximum
height stack.
Following are the key points to note in the problem statement:
1) A box can be placed on top of another box only if both width and depth of the upper
placed box are smaller than width and depth of the lower box respectively.
2) We can rotate boxes such that width is smaller than depth. For example, if there is a box
with dimensions {1x2x3} where 1 is height, 2×3 is base, then there can be three possibilities,
{1x2x3}, {2x1x3} and {3x1x2}
3) We can use multiple instances of boxes. What it means is, we can have two different
rotations of a box as part of our maximum height stack.

239
Chapter 22. DP-22 | Box Stacking Problem

Following is the solution based on DP solution of LIS problem.


1) Generate all 3 rotations of all boxes. The size of rotation array becomes 3 times the size
of original array. For simplicity, we consider depth as always smaller than or equal to width.
2) Sort the above generated 3n boxes in decreasing order of base area.
3) After sorting the boxes, the problem is same as LIS with following optimal substructure
property.
MSH(i) = Maximum possible Stack Height with box i at top of stack
MSH(i) = { Max ( MSH(j) ) + height(i) } where j < i and width(j) > width(i) and depth(j)
> depth(i).
If there is no such j then MSH(i) = height(i)
4) To get overall maximum height, we return max(MSH(i)) where 0 < i < n
Following is the implementation of the above solution.

C++

/* Dynamic Programming implementation of Box Stacking problem */


#include<stdio.h>
#include<stdlib.h>
  
/* Representation of a box */
struct Box
{
  // h --> height, w --> width, d --> depth
  int h, w, d;  // for simplicity of solution, always keep w <= d
};
  
// A utility function to get minimum of two intgers
int min (int x, int y)
{ return (x < y)? x : y; }
  
// A utility function to get maximum of two intgers
int max (int x, int y)
{ return (x > y)? x : y; }
  
/* Following function is needed for library function qsort(). We
   use qsort() to sort boxes in decreasing order of base area. 
   Refer following link for help of qsort() and compare()
   http://www.cplusplus.com/reference/clibrary/cstdlib/qsort/ */
int compare (const void *a, const void * b)
{
    return ( (*(Box *)b).d * (*(Box *)b).w ) -
           ( (*(Box *)a).d * (*(Box *)a).w );
}
  
/* Returns the height of the tallest stack that can be

240
Chapter 22. DP-22 | Box Stacking Problem

   formed with give type of boxes */


int maxStackHeight( Box arr[], int n )
{
   /* Create an array of all rotations of given boxes
      For example, for a box {1, 2, 3}, we consider three
      instances{{1, 2, 3}, {2, 1, 3}, {3, 1, 2}} */
   Box rot[3*n];
   int index = 0;
   for (int i = 0; i < n; i++)
   {
      // Copy the original box
      rot[index].h = arr[i].h;
      rot[index].d = max(arr[i].d, arr[i].w);
      rot[index].w = min(arr[i].d, arr[i].w);
      index++;
  
      // First rotation of box
      rot[index].h = arr[i].w;
      rot[index].d = max(arr[i].h, arr[i].d);
      rot[index].w = min(arr[i].h, arr[i].d);
      index++;
  
      // Second rotation of box
      rot[index].h = arr[i].d;
      rot[index].d = max(arr[i].h, arr[i].w);
      rot[index].w = min(arr[i].h, arr[i].w);
      index++;
   }
  
   // Now the number of boxes is 3n
   n = 3*n;
  
   /* Sort the array 'rot[]' in non-increasing order
      of base area */
   qsort (rot, n, sizeof(rot[0]), compare);
  
   // Uncomment following two lines to print all rotations
   // for (int i = 0; i < n; i++ )
   //    printf("%d x %d x %d\n", rot[i].h, rot[i].w, rot[i].d);
  
   /* Initialize msh values for all indexes 
      msh[i] --> Maximum possible Stack Height with box i on top */
   int msh[n];
   for (int i = 0; i < n; i++ )
      msh[i] = rot[i].h;
  
   /* Compute optimized msh values in bottom up manner */
   for (int i = 1; i < n; i++ )

241
Chapter 22. DP-22 | Box Stacking Problem

      for (int j = 0; j < i; j++ )


         if ( rot[i].w < rot[j].w &&
              rot[i].d < rot[j].d &&
              msh[i] < msh[j] + rot[i].h
            )
         {
              msh[i] = msh[j] + rot[i].h;
         }
  
  
   /* Pick maximum of all msh values */
   int max = -1;
   for ( int i = 0; i < n; i++ )
      if ( max < msh[i] )
         max = msh[i];
  
   return max;
}
  
/* Driver program to test above function */
int main()
{
  Box arr[] = { {4, 6, 7}, {1, 2, 3}, {4, 5, 6}, {10, 12, 32} };
  int n = sizeof(arr)/sizeof(arr[0]);
  
  printf("The maximum possible height of stack is %d\n",
         maxStackHeight (arr, n) );
  
  return 0;
}

Java

/* Dynamic Programming implementation 


of Box Stacking problem in Java*/
import java.util.*;
  
public class GFG {
      
    /* Representation of a box */
    static class Box implements Comparable<Box>{
      
        // h --> height, w --> width,
        // d --> depth
        int h, w, d, area;
          
        // for simplicity of solution,
        // always keep w <= d

242
Chapter 22. DP-22 | Box Stacking Problem

  
        /*Constructor to initialise object*/
        public Box(int h, int w, int d) {
            this.h = h;
            this.w = w;
            this.d = d;
        }
          
        /*To sort the box array on the basis
        of area in decreasing order of area */
        @Override
        public int compareTo(Box o) {
            return o.area-this.area;
        }
    }
  
    /* Returns the height of the tallest
    stack that can be formed with give 
    type of boxes */
    static int maxStackHeight( Box arr[], int n){
          
        Box[] rot = new Box[n*3];
          
        /* New Array of boxes is created - 
        considering all 3 possible rotations, 
        with width always greater than equal
        to width */
        for(int i = 0;i < n;i++){
            Box box = arr[i];
              
            /* Orignal Box*/
            rot[3*i] = new Box(box.h, Math.max(box.w,box.d), 
                                    Math.min(box.w,box.d));
              
            /* First rotation of box*/
            rot[3*i + 1] = new Box(box.w, Math.max(box.h,box.d), 
                                       Math.min(box.h,box.d));
              
            /* Second rotation of box*/
            rot[3*i + 2] = new Box(box.d, Math.max(box.w,box.h),
                                       Math.min(box.w,box.h));
        }
          
        /* Calculating base area of 
        each of the boxes.*/
        for(int i = 0; i < rot.length; i++)
            rot[i].area = rot[i].w * rot[i].d;
          

243
Chapter 22. DP-22 | Box Stacking Problem

        /* Sorting the Boxes on the bases 


        of Area in non Increasing order.*/
        Arrays.sort(rot);
          
        int count = 3 * n;
          
        /* Initialize msh values for all 
        indexes 
        msh[i] --> Maximum possible Stack Height
                   with box i on top */
        int[]msh = new int[count];
        for (int i = 0; i < count; i++ )
            msh[i] = rot[i].h;
          
        /* Computing optimized msh[] 
        values in bottom up manner */
        for(int i = 0; i < count; i++){
            msh[i] = 0;
            Box box = rot[i];
            int val = 0;
              
            for(int j = 0; j < i; j++){
                Box prevBox = rot[j];
                if(box.w < prevBox.w && box.d < prevBox.d){
                    val = Math.max(val, msh[j]);
                }
            }
            msh[i] = val + box.h;
        }
          
        int max = -1;
          
        /* Pick maximum of all msh values */
        for(int i = 0; i < count; i++){
            max = Math.max(max, msh[i]);
        }
          
        return max;
    }
      
    /* Driver program to test above function */
    public static void main(String[] args) {
          
        Box[] arr = new Box[4];
        arr[0] = new Box(4, 6, 7);
        arr[1] = new Box(1, 2, 3);
        arr[2] = new Box(4, 5, 6);
        arr[3] = new Box(10, 12, 32);

244
Chapter 22. DP-22 | Box Stacking Problem

          
        System.out.println("The maximum possible "+
                           "height of stack is " + 
                           maxStackHeight(arr,4));
    }
}
  
// This code is contributed by Divyam 

Output:

The maximum possible height of stack is 60

In the above program, given input boxes are {4, 6, 7}, {1, 2, 3}, {4, 5, 6}, {10, 12, 32}.
Following are all rotations of the boxes in decreasing order of base area.

10 x 12 x 32
12 x 10 x 32
32 x 10 x 12
4 x 6 x 7
4 x 5 x 6
6 x 4 x 7
5 x 4 x 6
7 x 4 x 6
6 x 4 x 5
1 x 2 x 3
2 x 1 x 3
3 x 1 x 2

The height 60 is obtained by boxes { {3, 1, 2}, {1, 2, 3}, {6, 4, 5}, {4, 5, 6}, {4, 6, 7}, {32,
10, 12}, {10, 12, 32}}
Time Complexity: O(n^2)
Auxiliary Space: O(n)

Source

https://www.geeksforgeeks.org/box-stacking-problem-dp-22/

245
Chapter 23

DP-23 | Bellman–Ford
Algorithm

Bellman–Ford Algorithm | DP-23 - GeeksforGeeks


Given a graph and a source vertex src in graph, find shortest paths from src to all vertices
in the given graph. The graph may contain negative weight edges.
We have discussed Dijkstra’s algorithm for this problem. Dijksra’s algorithm is a Greedy
algorithm and time complexity is O(VLogV) (with the use of Fibonacci heap). Dijkstra
doesn’t work for Graphs with negative weight edges, Bellman-Ford works for such graphs.
Bellman-Ford is also simpler than Dijkstra and suites well for distributed systems. But time
complexity of Bellman-Ford is O(VE), which is more than Dijkstra.
Algorithm
Following are the detailed steps.
Input: Graph and a source vertex src
Output: Shortest distance to all vertices from src. If there is a negative weight cycle, then
shortest distances are not calculated, negative weight cycle is reported.
1) This step initializes distances from source to all vertices as infinite and distance to source
itself as 0. Create an array dist[] of size |V| with all values as infinite except dist[src] where
src is source vertex.
2) This step calculates shortest distances. Do following |V|-1 times where |V| is the number
of vertices in given graph.
…..a) Do following for each edge u-v
………………If dist[v] > dist[u] + weight of edge uv, then update dist[v]
………………….dist[v] = dist[u] + weight of edge uv
3) This step reports if there is a negative weight cycle in graph. Do following for each edge
u-v
……If dist[v] > dist[u] + weight of edge uv, then “Graph contains negative weight cycle”
The idea of step 3 is, step 2 guarantees shortest distances if graph doesn’t contain negative
weight cycle. If we iterate through all edges one more time and get a shorter path for any
vertex, then there is a negative weight cycle

246
Chapter 23. DP-23 | Bellman–Ford Algorithm

How does this work? Like other Dynamic Programming Problems, the algorithm calcu-
late shortest paths in bottom-up manner. It first calculates the shortest distances which
have at-most one edge in the path. Then, it calculates shortest paths with at-most 2 edges,
and so on. After the i-th iteration of outer loop, the shortest paths with at most i edges
are calculated. There can be maximum |V| – 1 edges in any simple path, that is why the
outer loop runs |v| – 1 times. The idea is, assuming that there is no negative weight cycle,
if we have calculated shortest paths with at most i edges, then an iteration over all edges
guarantees to give shortest path with at-most (i+1) edges (Proof is simple, you can refer
this or MIT Video Lecture)
Example
Let us understand the algorithm with following example graph. The images are taken from
thissource.
Let the given source vertex be 0. Initialize all distances as infinite, except the distance to
source itself. Total number of vertices in the graph is 5, so all edges must be processed 4
times.

Let all edges are processed in following order: (B,E), (D,B), (B,D), (A,B), (A,C), (D,C),
(B,C), (E,D). We get following distances when all edges are processed first time. The first
row in shows initial distances. The second row shows distances when edges (B,E), (D,B),
(B,D) and (A,B) are processed. The third row shows distances when (A,C) is processed.
The fourth row shows when (D,C), (B,C) and (E,D) are processed.

247
Chapter 23. DP-23 | Bellman–Ford Algorithm

The first iteration guarantees to give all shortest paths which are at most 1 edge long. We
get following distances when all edges are processed second time (The last row shows final
values).

The second iteration guarantees to give all shortest paths which are at most 2 edges long.
The algorithm processes all edges 2 more times. The distances are minimized after the
second iteration, so third and fourth iterations don’t update the distances.
Implementation:

C++

248
Chapter 23. DP-23 | Bellman–Ford Algorithm

// A C++ program for Bellman-Ford's single source 


// shortest path algorithm.
#include <bits/stdc++.h>
  
// a structure to represent a weighted edge in graph
struct Edge
{
    int src, dest, weight;
};
  
// a structure to represent a connected, directed and 
// weighted graph
struct Graph
{
    // V-> Number of vertices, E-> Number of edges
    int V, E;
  
    // graph is represented as an array of edges.
    struct Edge* edge;
};
  
// Creates a graph with V vertices and E edges
struct Graph* createGraph(int V, int E)
{
    struct Graph* graph = new Graph;
    graph->V = V;
    graph->E = E;
    graph->edge = new Edge[E];
    return graph;
}
  
// A utility function used to print the solution
void printArr(int dist[], int n)
{
    printf("Vertex   Distance from Source\n");
    for (int i = 0; i < n; ++i)
        printf("%d \t\t %d\n", i, dist[i]);
}
  
// The main function that finds shortest distances from src to
// all other vertices using Bellman-Ford algorithm.  The function
// also detects negative weight cycle
void BellmanFord(struct Graph* graph, int src)
{
    int V = graph->V;
    int E = graph->E;
    int dist[V];
  

249
Chapter 23. DP-23 | Bellman–Ford Algorithm

    // Step 1: Initialize distances from src to all other vertices


    // as INFINITE
    for (int i = 0; i < V; i++)
        dist[i]   = INT_MAX;
    dist[src] = 0;
  
    // Step 2: Relax all edges |V| - 1 times. A simple shortest 
    // path from src to any other vertex can have at-most |V| - 1 
    // edges
    for (int i = 1; i <= V-1; i++)
    {
        for (int j = 0; j < E; j++)
        {
            int u = graph->edge[j].src;
            int v = graph->edge[j].dest;
            int weight = graph->edge[j].weight;
            if (dist[u] != INT_MAX && dist[u] + weight < dist[v])
                dist[v] = dist[u] + weight;
        }
    }
  
    // Step 3: check for negative-weight cycles.  The above step 
    // guarantees shortest distances if graph doesn't contain 
    // negative weight cycle.  If we get a shorter path, then there
    // is a cycle.
    for (int i = 0; i < E; i++)
    {
        int u = graph->edge[i].src;
        int v = graph->edge[i].dest;
        int weight = graph->edge[i].weight;
        if (dist[u] != INT_MAX && dist[u] + weight < dist[v])
            printf("Graph contains negative weight cycle");
    }
  
    printArr(dist, V);
  
    return;
}
  
// Driver program to test above functions
int main()
{
    /* Let us create the graph given in above example */
    int V = 5;  // Number of vertices in graph
    int E = 8;  // Number of edges in graph
    struct Graph* graph = createGraph(V, E);
  
    // add edge 0-1 (or A-B in above figure)

250
Chapter 23. DP-23 | Bellman–Ford Algorithm

    graph->edge[0].src = 0;
    graph->edge[0].dest = 1;
    graph->edge[0].weight = -1;
  
    // add edge 0-2 (or A-C in above figure)
    graph->edge[1].src = 0;
    graph->edge[1].dest = 2;
    graph->edge[1].weight = 4;
  
    // add edge 1-2 (or B-C in above figure)
    graph->edge[2].src = 1;
    graph->edge[2].dest = 2;
    graph->edge[2].weight = 3;
  
    // add edge 1-3 (or B-D in above figure)
    graph->edge[3].src = 1;
    graph->edge[3].dest = 3;
    graph->edge[3].weight = 2;
  
    // add edge 1-4 (or A-E in above figure)
    graph->edge[4].src = 1;
    graph->edge[4].dest = 4;
    graph->edge[4].weight = 2;
  
    // add edge 3-2 (or D-C in above figure)
    graph->edge[5].src = 3;
    graph->edge[5].dest = 2;
    graph->edge[5].weight = 5;
  
    // add edge 3-1 (or D-B in above figure)
    graph->edge[6].src = 3;
    graph->edge[6].dest = 1;
    graph->edge[6].weight = 1;
  
    // add edge 4-3 (or E-D in above figure)
    graph->edge[7].src = 4;
    graph->edge[7].dest = 3;
    graph->edge[7].weight = -3;
  
    BellmanFord(graph, 0);
  
    return 0;
}

Java

// A Java program for Bellman-Ford's single source shortest path


// algorithm.

251
Chapter 23. DP-23 | Bellman–Ford Algorithm

import java.util.*;
import java.lang.*;
import java.io.*;
  
// A class to represent a connected, directed and weighted graph
class Graph
{
    // A class to represent a weighted edge in graph
    class Edge {
        int src, dest, weight;
        Edge() {
            src = dest = weight = 0;
        }
    };
  
    int V, E;
    Edge edge[];
  
    // Creates a graph with V vertices and E edges
    Graph(int v, int e)
    {
        V = v;
        E = e;
        edge = new Edge[e];
        for (int i=0; i<e; ++i)
            edge[i] = new Edge();
    }
  
    // The main function that finds shortest distances from src
    // to all other vertices using Bellman-Ford algorithm.  The
    // function also detects negative weight cycle
    void BellmanFord(Graph graph,int src)
    {
        int V = graph.V, E = graph.E;
        int dist[] = new int[V];
  
        // Step 1: Initialize distances from src to all other
        // vertices as INFINITE
        for (int i=0; i<V; ++i)
            dist[i] = Integer.MAX_VALUE;
        dist[src] = 0;
  
        // Step 2: Relax all edges |V| - 1 times. A simple
        // shortest path from src to any other vertex can
        // have at-most |V| - 1 edges
        for (int i=1; i<V; ++i)
        {
            for (int j=0; j<E; ++j)

252
Chapter 23. DP-23 | Bellman–Ford Algorithm

            {
                int u = graph.edge[j].src;
                int v = graph.edge[j].dest;
                int weight = graph.edge[j].weight;
                if (dist[u]!=Integer.MAX_VALUE &&
                    dist[u]+weight<dist[v])
                    dist[v]=dist[u]+weight;
            }
        }
  
        // Step 3: check for negative-weight cycles.  The above
        // step guarantees shortest distances if graph doesn't
        // contain negative weight cycle. If we get a shorter
        //  path, then there is a cycle.
        for (int j=0; j<E; ++j)
        {
            int u = graph.edge[j].src;
            int v = graph.edge[j].dest;
            int weight = graph.edge[j].weight;
            if (dist[u] != Integer.MAX_VALUE &&
                dist[u]+weight < dist[v])
              System.out.println("Graph contains negative weight cycle");
        }
        printArr(dist, V);
    }
  
    // A utility function used to print the solution
    void printArr(int dist[], int V)
    {
        System.out.println("Vertex   Distance from Source");
        for (int i=0; i<V; ++i)
            System.out.println(i+"\t\t"+dist[i]);
    }
  
    // Driver method to test above function
    public static void main(String[] args)
    {
        int V = 5;  // Number of vertices in graph
        int E = 8;  // Number of edges in graph
  
        Graph graph = new Graph(V, E);
  
        // add edge 0-1 (or A-B in above figure)
        graph.edge[0].src = 0;
        graph.edge[0].dest = 1;
        graph.edge[0].weight = -1;
  
        // add edge 0-2 (or A-C in above figure)

253
Chapter 23. DP-23 | Bellman–Ford Algorithm

        graph.edge[1].src = 0;
        graph.edge[1].dest = 2;
        graph.edge[1].weight = 4;
  
        // add edge 1-2 (or B-C in above figure)
        graph.edge[2].src = 1;
        graph.edge[2].dest = 2;
        graph.edge[2].weight = 3;
  
        // add edge 1-3 (or B-D in above figure)
        graph.edge[3].src = 1;
        graph.edge[3].dest = 3;
        graph.edge[3].weight = 2;
  
        // add edge 1-4 (or A-E in above figure)
        graph.edge[4].src = 1;
        graph.edge[4].dest = 4;
        graph.edge[4].weight = 2;
  
        // add edge 3-2 (or D-C in above figure)
        graph.edge[5].src = 3;
        graph.edge[5].dest = 2;
        graph.edge[5].weight = 5;
  
        // add edge 3-1 (or D-B in above figure)
        graph.edge[6].src = 3;
        graph.edge[6].dest = 1;
        graph.edge[6].weight = 1;
  
        // add edge 4-3 (or E-D in above figure)
        graph.edge[7].src = 4;
        graph.edge[7].dest = 3;
        graph.edge[7].weight = -3;
  
        graph.BellmanFord(graph, 0);
    }
}
// Contributed by Aakash Hasija

Python

# Python program for Bellman-Ford's single source 


# shortest path algorithm.
  
from collections import defaultdict
  
#Class to represent a graph
class Graph:

254
Chapter 23. DP-23 | Bellman–Ford Algorithm

  
    def __init__(self,vertices):
        self.V= vertices #No. of vertices
        self.graph = [] # default dictionary to store graph
   
    # function to add an edge to graph
    def addEdge(self,u,v,w):
        self.graph.append([u, v, w])
          
    # utility function used to print the solution
    def printArr(self, dist):
        print("Vertex   Distance from Source")
        for i in range(self.V):
            print("%d \t\t %d" % (i, dist[i]))
      
    # The main function that finds shortest distances from src to
    # all other vertices using Bellman-Ford algorithm.  The function
    # also detects negative weight cycle
    def BellmanFord(self, src):
  
        # Step 1: Initialize distances from src to all other vertices
        # as INFINITE
        dist = [float("Inf")] * self.V
        dist[src] = 0 
  
  
        # Step 2: Relax all edges |V| - 1 times. A simple shortest 
        # path from src to any other vertex can have at-most |V| - 1 
        # edges
        for i in range(self.V - 1):
            # Update dist value and parent index of the adjacent vertices of
            # the picked vertex. Consider only those vertices which are still in
            # queue
            for u, v, w in self.graph:
                if dist[u] != float("Inf") and dist[u] + w < dist[v]:
                        dist[v] = dist[u] + w
  
        # Step 3: check for negative-weight cycles.  The above step 
        # guarantees shortest distances if graph doesn't contain 
        # negative weight cycle.  If we get a shorter path, then there
        # is a cycle.
  
        for u, v, w in self.graph:
                if dist[u] != float("Inf") and dist[u] + w < dist[v]:
                        print "Graph contains negative weight cycle"
                        return
                          
        # print all distance

255
Chapter 23. DP-23 | Bellman–Ford Algorithm

        self.printArr(dist)
  
g = Graph(5)
g.addEdge(0, 1, -1)
g.addEdge(0, 2, 4)
g.addEdge(1, 2, 3)
g.addEdge(1, 3, 2)
g.addEdge(1, 4, 2)
g.addEdge(3, 2, 5)
g.addEdge(3, 1, 1)
g.addEdge(4, 3, -3)
  
#Print the solution
g.BellmanFord(0)
  
#This code is contributed by Neelam Yadav

Output:

Vertex Distance from Source


0 0
1 -1
2 2
3 -2
4 1

Notes
1) Negative weights are found in various applications of graphs. For example, instead of
paying cost for a path, we may get some advantage if we follow the path.
2) Bellman-Ford works better (better than Dijksra’s) for distributed systems. Unlike Di-
jksra’s where we need to find minimum value of all vertices, in Bellman-Ford, edges are
considered one by one.
Exercise
1) The standard Bellman-Ford algorithm reports shortest path only if there is no negative
weight cycles. Modify it so that it reports minimum distances even if there is a negative
weight cycle.
2) Can we use Dijksra’s algorithm for shortest paths for graphs with negative weights – one
idea can be, calculate the minimum weight value, add a positive value (equal to absolute
value of minimum weight value) to all weights and run the Dijksra’s algorithm for the
modified graph. Will this algorithm work?
References:
http://www.youtube.com/watch?v=Ttezuzs39nk
http://en.wikipedia.org/wiki/Bellman%E2%80%93Ford_algorithm
http://www.cs.arizona.edu/classes/cs445/spring07/ShortestPath2.prn.pdf

256
Chapter 23. DP-23 | Bellman–Ford Algorithm

Source

https://www.geeksforgeeks.org/bellman-ford-algorithm-dp-23/

257
Chapter 24

DP-24 | Optimal Binary Search


Tree

Optimal Binary Search Tree | DP-24 - GeeksforGeeks


Given a sorted array keys[0.. n-1] of search keys and an array freq[0.. n-1] of frequency
counts, where freq[i] is the number of searches to keys[i]. Construct a binary search tree of
all keys such that the total cost of all the searches is as small as possible.
Let us first define the cost of a BST. The cost of a BST node is level of that node multiplied
by its frequency. Level of root is 1.

Example 1
Input: keys[] = {10, 12}, freq[] = {34, 50}
There can be following two possible BSTs
10 12
\ /
12 10
I II
Frequency of searches of 10 and 12 are 34 and 50 respectively.
The cost of tree I is 34*1 + 50*2 = 134
The cost of tree II is 50*1 + 34*2 = 118

Example 2
Input: keys[] = {10, 12, 20}, freq[] = {34, 8, 50}
There can be following possible BSTs
10 12 20 10 20
\ / \ / \ /
12 10 20 12 20 10
\ / / \
20 10 12 12
I II III IV V

258
Chapter 24. DP-24 | Optimal Binary Search Tree

Among all possible BSTs, cost of the fifth BST is minimum.


Cost of the fifth BST is 1*50 + 2*34 + 3*8 = 142

1) Optimal Substructure:
The optimal cost for freq[i..j] can be recursively calculated using following formula.

We need to calculate optCost(0, n-1) to find the result.


The idea of above formula is simple, we one by one try all nodes as root (r varies from i to
j in second term). When we make rth node as root, we recursively calculate optimal cost
from i to r-1 and r+1 to j.
We add sum of frequencies from i to j (see first term in the above formula), this is added
because every search will go through root and one comparison will be done for every search.
2) Overlapping Subproblems
Following is recursive implementation that simply follows the recursive structure mentioned
above.

C/C++

// A naive recursive implementation of optimal binary 


// search tree problem
#include <stdio.h>
#include <limits.h>
  
// A utility function to get sum of array elements 
// freq[i] to freq[j]
int sum(int freq[], int i, int j);
  
// A recursive function to calculate cost of optimal 
// binary search tree
int optCost(int freq[], int i, int j)
{
   // Base cases
   if (j < i)      // no elements in this subarray
     return 0;
   if (j == i)     // one element in this subarray
     return freq[i];
  
   // Get sum of freq[i], freq[i+1], ... freq[j]
   int fsum = sum(freq, i, j);
  
   // Initialize minimum value
   int min = INT_MAX;
  
   // One by one consider all elements as root and

259
Chapter 24. DP-24 | Optimal Binary Search Tree

   // recursively find cost of the BST, compare the


   // cost with min and update min if needed
   for (int r = i; r <= j; ++r)
   {
       int cost = optCost(freq, i, r-1) + 
                  optCost(freq, r+1, j);
       if (cost < min)
          min = cost;
   }
  
   // Return minimum value
   return min + fsum;
}
  
// The main function that calculates minimum cost of
// a Binary Search Tree. It mainly uses optCost() to 
// find the optimal cost.
int optimalSearchTree(int keys[], int freq[], int n)
{
     // Here array keys[] is assumed to be sorted in 
     // increasing order. If keys[] is not sorted, then 
     // add code to sort keys, and rearrange freq[] 
     // accordingly.
     return optCost(freq, 0, n-1);
}
  
// A utility function to get sum of array elements 
// freq[i] to freq[j]
int sum(int freq[], int i, int j)
{
    int s = 0;
    for (int k = i; k <=j; k++)
       s += freq[k];
    return s;
}
  
// Driver program to test above functions
int main()
{
    int keys[] = {10, 12, 20};
    int freq[] = {34, 8, 50};
    int n = sizeof(keys)/sizeof(keys[0]);
    printf("Cost of Optimal BST is %d ", 
               optimalSearchTree(keys, freq, n));
    return 0;
}

Java

260
Chapter 24. DP-24 | Optimal Binary Search Tree

// A naive recursive implementation of optimal binary 


// search tree problem
public class GFG 
{
    // A recursive function to calculate cost of
        // optimal binary search tree
    static int optCost(int freq[], int i, int j)
    {
       // Base cases
       if (j < i)      // no elements in this subarray
         return 0;
       if (j == i)     // one element in this subarray
         return freq[i];
       
       // Get sum of freq[i], freq[i+1], ... freq[j]
       int fsum = sum(freq, i, j);
       
       // Initialize minimum value
       int min = Integer.MAX_VALUE;
       
       // One by one consider all elements as root and 
           // recursively find cost of the BST, compare the 
           // cost with min and update min if needed
       for (int r = i; r <= j; ++r)
       {
           int cost = optCost(freq, i, r-1) + 
                          optCost(freq, r+1, j);
           if (cost < min)
              min = cost;
       }
       
       // Return minimum value
       return min + fsum;
    }
      
    // The main function that calculates minimum cost of
        // a Binary Search Tree. It mainly uses optCost() to
        // find the optimal cost.
    static int optimalSearchTree(int keys[], int freq[], int n)
    {
         // Here array keys[] is assumed to be sorted in 
             // increasing order. If keys[] is not sorted, then
             // add code to sort keys, and rearrange freq[] 
             // accordingly.
         return optCost(freq, 0, n-1);
    }
      
    // A utility function to get sum of array elements 

261
Chapter 24. DP-24 | Optimal Binary Search Tree

        // freq[i] to freq[j]


    static int sum(int freq[], int i, int j)
    {
        int s = 0;
        for (int k = i; k <=j; k++)
           s += freq[k];
        return s;
    }
      
    // Driver code
    public static void main(String[] args) {
        int keys[] = {10, 12, 20};
        int freq[] = {34, 8, 50};
        int n = keys.length;
        System.out.println("Cost of Optimal BST is " +
                         optimalSearchTree(keys, freq, n));
    }
}
// This code is contributed by Sumit Ghosh

C#

// A naive recursive implementation of optimal binary 


// search tree problem
using System;
  
class GFG
{
    // A recursive function to calculate cost of
    // optimal binary search tree
    static int optCost(int []freq, int i, int j)
    {
          
    // Base cases
    // no elements in this subarray
    if (j < i)     
        return 0;
      
    // one element in this subarray    
    if (j == i)     
        return freq[i];
      
    // Get sum of freq[i], freq[i+1], ... freq[j]
    int fsum = sum(freq, i, j);
      
    // Initialize minimum value
    int min = int.MaxValue;
      

262
Chapter 24. DP-24 | Optimal Binary Search Tree

    // One by one consider all elements as root and 


    // recursively find cost of the BST, compare the 
    // cost with min and update min if needed
    for (int r = i; r <= j; ++r)
    {
        int cost = optCost(freq, i, r-1) + 
                        optCost(freq, r+1, j);
        if (cost < min)
            min = cost;
    }
      
    // Return minimum value
    return min + fsum;
    }
      
    // The main function that calculates minimum cost of
    // a Binary Search Tree. It mainly uses optCost() to
    // find the optimal cost.
    static int optimalSearchTree(int []keys, int []freq, int n)
    {
        // Here array keys[] is assumed to be sorted in 
        // increasing order. If keys[] is not sorted, then
        // add code to sort keys, and rearrange freq[] 
        // accordingly.
        return optCost(freq, 0, n-1);
    }
      
    // A utility function to get sum of array elements 
    // freq[i] to freq[j]
    static int sum(int []freq, int i, int j)
    {
        int s = 0;
        for (int k = i; k <=j; k++)
        s += freq[k];
        return s;
    }
      
    // Driver code
    public static void Main() 
    {
        int []keys = {10, 12, 20};
        int []freq = {34, 8, 50};
        int n = keys.Length;
        Console.Write("Cost of Optimal BST is " +
                        optimalSearchTree(keys, freq, n));
    }
}
  

263
Chapter 24. DP-24 | Optimal Binary Search Tree

// This code is contributed by Sam007

Output:

Cost of Optimal BST is 142

Time complexity of the above naive recursive approach is exponential. It should be noted
that the above function computes the same subproblems again and again. We can see many
subproblems being repeated in the following recursion tree for freq[1..4].

Since same suproblems are called again, this problem has Overlapping Subprolems property.
So optimal BST problem has both properties (see thisand this) of a dynamic programming
problem. Like other typical Dynamic Programming(DP) problems, recomputations of same
subproblems can be avoided by constructing a temporary array cost[][] in bottom up manner.
Dynamic Programming Solution
Following is C/C++ implementation for optimal BST problem using Dynamic Programming.
We use an auxiliary array cost[n][n] to store the solutions of subproblems. cost[0][n-1] will
hold the final result. The challenge in implementation is, all diagonal values must be filled
first, then the values which lie on the line just above the diagonal. In other words, we must
first fill all cost[i][i] values, then all cost[i][i+1] values, then all cost[i][i+2] values. So how to
fill the 2D array in such manner> The idea used in the implementation is same as Matrix
Chain Multiplication problem, we use a variable ‘L’ for chain length and increment ‘L’, one
by one. We calculate column number ‘j’ using the values of ‘i’ and ‘L’.
C/C++

// Dynamic Programming code for Optimal Binary Search 


// Tree Problem
#include <stdio.h>

264
Chapter 24. DP-24 | Optimal Binary Search Tree

#include <limits.h>
  
// A utility function to get sum of array elements 
// freq[i] to freq[j]
int sum(int freq[], int i, int j);
  
/* A Dynamic Programming based function that calculates
  minimum cost of a Binary Search Tree. */
int optimalSearchTree(int keys[], int freq[], int n)
{
    /* Create an auxiliary 2D matrix to store results 
      of subproblems */
    int cost[n][n];
  
    /* cost[i][j] = Optimal cost of binary search tree
       that can be  formed from keys[i] to keys[j].
       cost[0][n-1] will store the resultant cost */
  
    // For a single key, cost is equal to frequency of the key
    for (int i = 0; i < n; i++)
        cost[i][i] = freq[i];
  
    // Now we need to consider chains of length 2, 3, ... .
    // L is chain length.
    for (int L=2; L<=n; L++)
    {
        // i is row number in cost[][]
        for (int i=0; i<=n-L+1; i++)
        {
            // Get column number j from row number i and 
            // chain length L
            int j = i+L-1;
            cost[i][j] = INT_MAX;
  
            // Try making all keys in interval keys[i..j] as root
            for (int r=i; r<=j; r++)
            {
               // c = cost when keys[r] becomes root of this subtree
               int c = ((r > i)? cost[i][r-1]:0) + 
                       ((r < j)? cost[r+1][j]:0) + 
                       sum(freq, i, j);
               if (c < cost[i][j])
                  cost[i][j] = c;
            }
        }
    }
    return cost[0][n-1];
}

265
Chapter 24. DP-24 | Optimal Binary Search Tree

  
// A utility function to get sum of array elements 
// freq[i] to freq[j]
int sum(int freq[], int i, int j)
{
    int s = 0;
    for (int k = i; k <=j; k++)
       s += freq[k];
    return s;
}
  
// Driver program to test above functions
int main()
{
    int keys[] = {10, 12, 20};
    int freq[] = {34, 8, 50};
    int n = sizeof(keys)/sizeof(keys[0]);
    printf("Cost of Optimal BST is %d ", 
                 optimalSearchTree(keys, freq, n));
    return 0;
}

Java

// Dynamic Programming Java code for Optimal Binary Search


// Tree Problem
public class Optimal_BST2 {
      
    /* A Dynamic Programming based function that calculates
        minimum cost of a Binary Search Tree.  */
    static int optimalSearchTree(int keys[], int freq[], int n) {
  
        /* Create an auxiliary 2D matrix to store results of 
           subproblems */
        int cost[][] = new int[n + 1][n + 1];
  
        /* cost[i][j] = Optimal cost of binary search tree that 
           can be formed from keys[i] to keys[j]. cost[0][n-1] 
           will store the resultant cost */
  
        // For a single key, cost is equal to frequency of the key
        for (int i = 0; i < n; i++)
            cost[i][i] = freq[i];
  
        // Now we need to consider chains of length 2, 3, ... .
        // L is chain length.
        for (int L = 2; L <= n; L++) {
  

266
Chapter 24. DP-24 | Optimal Binary Search Tree

            // i is row number in cost[][]


            for (int i = 0; i <= n - L + 1; i++) {
  
                // Get column number j from row number i and 
                // chain length L
                int j = i + L - 1;
                cost[i][j] = Integer.MAX_VALUE;
  
                // Try making all keys in interval keys[i..j] as root
                for (int r = i; r <= j; r++) {
  
                    // c = cost when keys[r] becomes root of this subtree
                    int c = ((r > i) ? cost[i][r - 1] : 0)
                            + ((r < j) ? cost[r + 1][j] : 0) + sum(freq, i, j);
                    if (c < cost[i][j])
                        cost[i][j] = c;
                }
            }
        }
        return cost[0][n - 1];
    }
  
    // A utility function to get sum of array elements 
    // freq[i] to freq[j]
    static int sum(int freq[], int i, int j) {
        int s = 0;
        for (int k = i; k <= j; k++) {
            if (k >= freq.length)
                continue;
            s += freq[k];
        }
        return s;
    }
  
    public static void main(String[] args) {
          
        int keys[] = { 10, 12, 20 };
        int freq[] = { 34, 8, 50 };
        int n = keys.length;
        System.out.println("Cost of Optimal BST is "
                + optimalSearchTree(keys, freq, n));
    }
  
}
//This code is contributed by Sumit Ghosh

C#

267
Chapter 24. DP-24 | Optimal Binary Search Tree

// Dynamic Programming C# code for Optimal Binary Search


// Tree Problem
using System;
  
class GFG
{
    /* A Dynamic Programming based function that calculates
    minimum cost of a Binary Search Tree. */
    static int optimalSearchTree(int []keys, int []freq, int n) {
  
        /* Create an auxiliary 2D matrix to store results of 
        subproblems */
        int [,]cost = new int[n + 1,n + 1];
  
        /* cost[i][j] = Optimal cost of binary search tree that 
        can be formed from keys[i] to keys[j]. cost[0][n-1] 
        will store the resultant cost */
  
        // For a single key, cost is equal to frequency of the key
        for (int i = 0; i < n; i++)
            cost[i,i] = freq[i];
  
        // Now we need to consider chains of length 2, 3, ... .
        // L is chain length.
        for (int L = 2; L <= n; L++) {
  
            // i is row number in cost[][]
            for (int i = 0; i <= n - L + 1; i++) {
  
                // Get column number j from row number i and 
                // chain length L
                int j = i + L - 1;
                cost[i,j] = int.MaxValue;
  
                // Try making all keys in interval keys[i..j] as root
                for (int r = i; r <= j; r++) {
  
                    // c = cost when keys[r] becomes root of this subtree
                    int c = ((r > i) ? cost[i,r - 1] : 0)
                            + ((r < j) ? cost[r + 1,j] : 0) + sum(freq, i, j);
                    if (c < cost[i,j])
                        cost[i,j] = c;
                }
            }
        }
        return cost[0,n - 1];
    }
  

268
Chapter 24. DP-24 | Optimal Binary Search Tree

    // A utility function to get sum of array elements 


    // freq[i] to freq[j]
    static int sum(int []freq, int i, int j) {
        int s = 0;
        for (int k = i; k <= j; k++) {
            if (k >= freq.Length)
                continue;
            s += freq[k];
        }
        return s;
    }
  
    public static void Main() {
          
        int []keys = { 10, 12, 20 };
        int []freq = { 34, 8, 50 };
        int n = keys.Length;
        Console.Write("Cost of Optimal BST is "
                + optimalSearchTree(keys, freq, n));
    }
}
// This code is contributed by Sam007

Output:

Cost of Optimal BST is 142

Notes
1) The time complexity of the above solution is O(n^4). The time complexity can be easily
reduced to O(n^3) by pre-calculating sum of frequencies instead of calling sum() again and
again.
2) In the above solutions, we have computed optimal cost only. The solutions can be easily
modified to store the structure of BSTs also. We can create another auxiliary array of size
n to store the structure of tree. All we need to do is, store the chosen ‘r’ in the innermost
loop.
Please write comments if you find anything incorrect, or you want to share more information
about the topic discussed above.
Improved By : aradhya95

Source

https://www.geeksforgeeks.org/optimal-binary-search-tree-dp-24/

269
Chapter 25

DP-25 | Subset Sum Problem

Dynamic Programming - Subset Sum Problem


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.
Example:

Input: 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

270
Chapter 25. DP-25 | Subset Sum Problem

Following is naive recursive implementation that simply follows the recursive structure
mentioned above.

// A recursive solution for subset sum problem


#include <stdio.h>
  
// Returns true if there is a subset of set[] with sun equal to given sum
bool isSubsetSum(int set[], int n, int sum)
{
   // Base Cases
   if (sum == 0)
     return true;
   if (n == 0 && sum != 0)
     return false;
  
   // If last element is greater than sum, then ignore it
   if (set[n-1] > sum)
     return isSubsetSum(set, n-1, sum);
  
   /* else, check if sum can be obtained by any of the following
      (a) including the last element
      (b) excluding the last element   */
   return isSubsetSum(set, n-1, sum) || 
                        isSubsetSum(set, n-1, sum-set[n-1]);
}
  
// Driver program to test above function
int main()
{
  int set[] = {3, 34, 4, 12, 5, 2};
  int sum = 9;
  int n = sizeof(set)/sizeof(set[0]);

271
Chapter 25. DP-25 | Subset Sum Problem

  if (isSubsetSum(set, n, sum) == true)


     printf("Found a subset with given sum");
  else
     printf("No subset with given sum");
  return 0;
}

Java

// A recursive solution for subset sum


// problem
class GFG {
      
    // Returns true if there is a subset
    // of set[] with sum equal to given sum
    static boolean isSubsetSum(int set[],
                            int n, int sum)
    {
        // Base Cases
        if (sum == 0)
            return true;
        if (n == 0 && sum != 0)
            return false;
          
        // If last element is greater than 
        // sum, then ignore it
        if (set[n-1] > sum)
            return isSubsetSum(set, n-1, sum);
          
        /* else, check if sum can be obtained 
        by any of the following
            (a) including the last element
            (b) excluding the last element */
        return isSubsetSum(set, n-1, sum) || 
            isSubsetSum(set, n-1, sum-set[n-1]);
    }
      
    /* Driver program to test above function */
    public static void main (String args[])
    {
        int set[] = {3, 34, 4, 12, 5, 2};
        int sum = 9;
        int n = set.length;
        if (isSubsetSum(set, n, sum) == true)
            System.out.println("Found a subset"
                          + " with given sum");
        else
            System.out.println("No subset with"

272
Chapter 25. DP-25 | Subset Sum Problem

                               + " given sum");


    }
}
  
/* This code is contributed by Rajat Mishra */

Python3

# A recursive solution for subset sum


# problem
  
# Returns true if there is a subset 
# of set[] with sun equal to given sum
def isSubsetSum(set,n, sum) :
    
    # Base Cases
    if (sum == 0) :
        return True
    if (n == 0 and sum != 0) :
        return False
   
    # If last element is greater than
    # sum, then ignore it
    if (set[n - 1] > sum) :
        return isSubsetSum(set, n - 1, sum);
   
    # else, check if sum can be obtained
    # by any of the following
    # (a) including the last element
    # (b) excluding the last element   
    return isSubsetSum(set, n-1, sum) or isSubsetSum(set, n-1, sum-set[n-1])
      
      
# Driver program to test above function
set = [3, 34, 4, 12, 5, 2]
sum = 9
n = len(set)
if (isSubsetSum(set, n, sum) == True) :
    print("Found a subset with given sum")
else :
    print("No subset with given sum")
      
# This code is contributed by Nikita Tiwari.

C#

// A recursive solution for subset sum problem

273
Chapter 25. DP-25 | Subset Sum Problem

using System;
  
class GFG
{
    // Returns true if there is a subset of set[] with sum
    // equal to given sum
    static bool isSubsetSum(int []set, int n, int sum)
    {
        // Base Cases
        if (sum == 0)
            return true;
        if (n == 0 && sum != 0)
            return false;
          
        // If last element is greater than sum, 
        // then ignore it
        if (set[n-1] > sum)
            return isSubsetSum(set, n-1, sum);
          
        /* else, check if sum can be obtained 
        by any of the following
        (a) including the last element
        (b) excluding the last element */
        return isSubsetSum(set, n-1, sum) || 
                       isSubsetSum(set, n-1, sum-set[n-1]);
    }
      
    // Driver program 
    public static void Main ()
    {
        int []set = {3, 34, 4, 12, 5, 2};
        int sum = 9;
        int n = set.Length;
        if (isSubsetSum(set, n, sum) == true)
            Console.WriteLine("Found a subset with given sum");
        else
            Console.WriteLine("No subset with given sum");
    }
}
  
// This code is contributed by Sam007

PHP

<?php
// A recursive solution for subset sum problem
  
// Returns true if there is a subset of set

274
Chapter 25. DP-25 | Subset Sum Problem

// with sun equal to given sum


function isSubsetSum($set, $n, $sum)
{
    // Base Cases
    if ($sum == 0)
        return true;
    if ($n == 0 && $sum != 0)
        return false;
      
    // If last element is greater
    // than sum, then ignore it
    if ($set[$n - 1] > $sum)
        return isSubsetSum($set, $n - 1, $sum);
      
    /* else, check if sum can be 
       obtained by any of the following
        (a) including the last element
        (b) excluding the last element */
    return isSubsetSum($set, $n - 1, $sum) || 
        isSubsetSum($set, $n - 1, 
                    $sum - $set[$n - 1]);
}
  
// Driver Code
$set = array(3, 34, 4, 12, 5, 2);
$sum = 9;
$n = 6;
  
if (isSubsetSum($set, $n, $sum) == true)
    echo"Found a subset with given sum";
else
    echo "No subset with given sum";
      
// This code is contributed by Anuj_67 
?>

Output:

Found a subset with given sum

The above solution may try all subsets of given set in worst case. Therefore time complexity
of the above solution is exponential. The problem is in-fact NP-Complete (There is no
known polynomial time solution for this problem).
We can solve the problem in Pseudo-polynomial time using Dynamic program-
ming. 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

275
Chapter 25. DP-25 | Subset Sum Problem

false. Finally, we return subset[sum][n]

// A Dynamic Programming solution for subset sum problem


#include <stdio.h>
   
// Returns true if there is a subset of set[] with sun equal to given sum
bool isSubsetSum(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]];
       }
     }
   
     /*   // uncomment this code to print table
     for (int i = 0; i <= n; i++)
     {
       for (int j = 0; j <= sum; j++)
          printf ("%4d", subset[i][j]);
       printf("n");
     }*/
   
     return subset[n][sum];
}
   
// Driver program to test above function
int main()

276
Chapter 25. DP-25 | Subset Sum Problem

{
  int set[] = {3, 34, 4, 12, 5, 2};
  int sum = 9;
  int n = sizeof(set)/sizeof(set[0]);
  if (isSubsetSum(set, n, sum) == true)
     printf("Found a subset with given sum");
  else
     printf("No subset with given sum");
  return 0;
}
// This code is contributed by Arjun Tyagi.

Java

// A Dynamic Programming solution for subset


// sum problem
class GFG {
      
    // Returns true if there is a subset of 
    // set[] with sun equal to given sum
    static boolean isSubsetSum(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
        boolean subset[][] = 
                     new boolean[sum+1][n+1];
      
        // If sum is 0, then answer is true
        for (int i = 0; i <= n; i++)
            subset[0][i] = true;
      
        // If sum is not 0 and set is empty,
        // then answer is false
        for (int i = 1; i <= sum; i++)
            subset[i][0] = false;
      
        // Fill the subset table in botton
        // up manner
        for (int i = 1; i <= sum; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                subset[i][j] = subset[i][j-1];
                if (i >= set[j-1])
                subset[i][j] = subset[i][j] || 
                     subset[i - set[j-1]][j-1];

277
Chapter 25. DP-25 | Subset Sum Problem

            }
        }
      
        /* // uncomment this code to print table
        for (int i = 0; i <= sum; i++)
        {
        for (int j = 0; j <= n; j++)
            System.out.println (subset[i][j]);
        } */
      
        return subset[sum][n];
    }
  
    /* Driver program to test above function */
    public static void main (String args[])
    {
        int set[] = {3, 34, 4, 12, 5, 2};
        int sum = 9;
        int n = set.length;
        if (isSubsetSum(set, n, sum) == true)
            System.out.println("Found a subset"
                          + " with given sum");
        else
            System.out.println("No subset with"
                               + " given sum");
    }
}
  
/* This code is contributed by Rajat Mishra */

C#

// A Dynamic Programming solution for subset sum problem


using System;
  
class GFG
{
    // Returns true if there is a subset 
    // of set[] with sun equal to given sum
    static bool isSubsetSum(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 = new bool[sum+1,n+1];
      
        // If sum is 0, then answer is true
        for (int i = 0; i <= n; i++)
        subset[0, i] = true;

278
Chapter 25. DP-25 | Subset Sum Problem

      
        // If sum is not 0 and set is empty, then answer is false
        for (int i = 1; i <= sum; i++)
        subset[i, 0] = false;
      
        // Fill the subset table in botton up manner
        for (int i = 1; i <= sum; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                subset[i, j] = subset[i, j - 1];
                if (i >= set[j - 1])
                subset[i, j] = subset[i, j] || 
                               subset[i - set[j - 1], j - 1];
                                              
            }
        }
      
        return subset[sum,n];
    }
      
    // Driver program 
    public static void Main ()
    {
        int []set = {3, 34, 4, 12, 5, 2};
        int sum = 9;
        int n = set.Length;
        if (isSubsetSum(set, n, sum) == true)
            Console.WriteLine("Found a subset with given sum");
        else
            Console.WriteLine("No subset with given sum");
    }
}
// This code is contributed by Sam007

PHP

<?php
// A Dynamic Programming solution for 
// subset sum problem
  
// Returns true if there is a subset of
// set[] with sun equal to given sum
function isSubsetSum( $set, $n, $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

279
Chapter 25. DP-25 | Subset Sum Problem

    $subset = array(array());
  
    // If sum is 0, then answer is true
    for ( $i = 0; $i <= $n; $i++)
        $subset[$i][0] = true;
  
    // If sum is not 0 and set is empty,
    // then answer is false
    for ( $i = 1; $i <= $sum; $i++)
        $subset[0][$i] = false;
  
    // Fill the subset table in botton
    // up manner
    for ($i = 1; $i <= $n; $i++)
    {
        for ($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]];
        }
    }
  
    /* // uncomment this code to print table
    for (int i = 0; i <= n; i++)
    {
    for (int j = 0; j <= sum; j++)
        printf ("%4d", subset[i][j]);
    printf("n");
    }*/
  
    return $subset[$n][$sum];
}
  
// Driver program to test above function
$set = array(3, 34, 4, 12, 5, 2);
$sum = 9;
$n = count($set);
  
if (isSubsetSum($set, $n, $sum) == true)
    echo "Found a subset with given sum";
else
    echo "No subset with given sum";

280
Chapter 25. DP-25 | Subset Sum Problem

  
// This code is contributed by anuj_67.
?>

Output:

Found a subset with given sum

Time complexity of the above solution is O(sum*n).Subset Sum Problem in O(sum) space
Perfect Sum Problem (Print all subsets with given sum)
Improved By : vt_m

Source

https://www.geeksforgeeks.org/subset-sum-problem-dp-25/

281
Chapter 26

DP-26 | Largest Independent


Set Problem

Largest Independent Set Problem | DP-26 - GeeksforGeeks


Given a Binary Tree, find size of the Largest Independent Set(LIS) in it. A subset of all
tree nodes is an independent set if there is no edge between any two nodes of the subset.
For example, consider the following binary tree. The largest independent set(LIS) is {10,
40, 60, 70, 80} and size of the LIS is 5.

A Dynamic Programming solution solves a given problem using solutions of subproblems in


bottom up manner. Can the given problem be solved using solutions to subproblems? If
yes, then what are the subproblems? Can we find largest independent set size (LISS) for
a node X if we know LISS for all descendants of X? If a node is considered as part of LIS,
then its children cannot be part of LIS, but its grandchildren can be. Following is optimal
substructure property.
1) Optimal Substructure:
Let LISS(X) indicates size of largest independent set of a tree with root X.

282
Chapter 26. DP-26 | Largest Independent Set Problem

LISS(X) = MAX { (1 + sum of LISS for all grandchildren of X),


(sum of LISS for all children of X) }

The idea is simple, there are two possibilities for every node X, either X is a member of
the set or not a member. If X is a member, then the value of LISS(X) is 1 plus LISS of all
grandchildren. If X is not a member, then the value is sum of LISS of all children.
2) Overlapping Subproblems
Following is recursive implementation that simply follows the recursive structure mentioned
above.

// A naive recursive implementation of Largest Independent Set problem


#include <stdio.h>
#include <stdlib.h>
  
// A utility function to find max of two integers
int max(int x, int y) { return (x > y)? x: y; }
  
/* A binary tree node has data, pointer to left child and a pointer to 
   right child */
struct node
{
    int data;
    struct node *left, *right;
};
  
// The function returns size of the largest independent set in a given 
// binary tree
int LISS(struct node *root)
{
    if (root == NULL)
       return 0;
  
    // Caculate size excluding the current node
    int size_excl = LISS(root->left) + LISS(root->right);
  
    // Calculate size including the current node
    int size_incl = 1;
    if (root->left)
       size_incl += LISS(root->left->left) + LISS(root->left->right);
    if (root->right)
       size_incl += LISS(root->right->left) + LISS(root->right->right);
  
    // Return the maximum of two sizes
    return max(size_incl, size_excl);
}
  

283
Chapter 26. DP-26 | Largest Independent Set Problem

  
// A utility function to create a node
struct node* newNode( int data )
{
    struct node* temp = (struct node *) malloc( sizeof(struct node) );
    temp->data = data;
    temp->left = temp->right = NULL;
    return temp;
}
  
// Driver program to test above functions
int main()
{
    // Let us construct the tree given in the above diagram
    struct node *root         = newNode(20);
    root->left                = newNode(8);
    root->left->left          = newNode(4);
    root->left->right         = newNode(12);
    root->left->right->left   = newNode(10);
    root->left->right->right  = newNode(14);
    root->right               = newNode(22);
    root->right->right        = newNode(25);
  
    printf ("Size of the Largest Independent Set is %d ", LISS(root));
  
    return 0;
}

Output:

Size of the Largest Independent Set is 5

Time complexity of the above naive recursive approach is exponential. It should be noted
that the above function computes the same subproblems again and again. For example,
LISS of node with value 50 is evaluated for node with values 10 and 20 as 50 is grandchild
of 10 and child of 20.
Since same suproblems are called again, this problem has Overlapping Subprolems prop-
erty. So LISS problem has both properties (see thisand this) of a dynamic programming
problem. Like other typical Dynamic Programming(DP) problems, recomputations of same
subproblems can be avoided by storing the solutions to subproblems and solving problems
in bottom up manner.
Following is C implementation of Dynamic Programming based solution. In the following
solution, an additional field ‘liss’ is added to tree nodes. The initial value of ‘liss’ is set as
0 for all nodes. The recursive function LISS() calculates ‘liss’ for a node only if it is not
already set.
C

284
Chapter 26. DP-26 | Largest Independent Set Problem

/* Dynamic programming based program for Largest Independent Set problem */


#include <stdio.h>
#include <stdlib.h>
  
// A utility function to find max of two integers
int max(int x, int y) { return (x > y)? x: y; }
  
/* A binary tree node has data, pointer to left child and a pointer to 
   right child */
struct node
{
    int data;
    int liss;
    struct node *left, *right;
};
  
// A memoization function returns size of the largest independent set in
//  a given binary tree
int LISS(struct node *root)
{
    if (root == NULL)
        return 0;
  
    if (root->liss)
        return root->liss;
  
    if (root->left == NULL && root->right == NULL)
        return (root->liss = 1);
  
    // Calculate size excluding the current node
    int liss_excl = LISS(root->left) + LISS(root->right);
  
    // Calculate size including the current node
    int liss_incl = 1;
    if (root->left)
        liss_incl += LISS(root->left->left) + LISS(root->left->right);
    if (root->right)
        liss_incl += LISS(root->right->left) + LISS(root->right->right);
  
    // Maximum of two sizes is LISS, store it for future uses.
    root->liss = max(liss_incl, liss_excl);
  
    return root->liss;
}
  
// A utility function to create a node
struct node* newNode(int data)
{

285
Chapter 26. DP-26 | Largest Independent Set Problem

    struct node* temp = (struct node *) malloc( sizeof(struct node) );


    temp->data = data;
    temp->left = temp->right = NULL;
    temp->liss = 0;
    return temp;
}
  
// Driver program to test above functions
int main()
{
    // Let us construct the tree given in the above diagram
    struct node *root         = newNode(20);
    root->left                = newNode(8);
    root->left->left          = newNode(4);
    root->left->right         = newNode(12);
    root->left->right->left   = newNode(10);
    root->left->right->right  = newNode(14);
    root->right               = newNode(22);
    root->right->right        = newNode(25);
  
    printf ("Size of the Largest Independent Set is %d ", LISS(root));
  
    return 0;
}

Java

// Java program for calculating LISS 


// using dynamic programming
  
public class LisTree 
{
    /* A binary tree node has data, pointer 
       to left child and a pointer to right
       child */
    static class node 
    {
        int data, liss;
        node left, right;
  
        public node(int data) 
        {
            this.data = data;
            this.liss = 0;
        }
    }
  
    // A memoization function returns size 

286
Chapter 26. DP-26 | Largest Independent Set Problem

    // of the largest independent set in


    // a given binary tree
    static int liss(node root) 
    {
        if (root == null)
            return 0;
        if (root.liss != 0)
            return root.liss;
        if (root.left == null && root.right == null)
            return root.liss = 1;
          
        // Calculate size excluding the 
        // current node
        int liss_excl = liss(root.left) + liss(root.right);
          
        // Calculate size including the 
        // current node
        int liss_incl = 1;
        if (root.left != null) 
        {
            liss_incl += (liss(root.left.left) + liss(root.left.right));
        }
        if (root.right != null) 
        {
            liss_incl += (liss(root.right.left) + liss(root.right.right));
        }
          
        // Maximum of two sizes is LISS, 
        // store it for future uses.
        return root.liss = Math.max(liss_excl, liss_incl);
    }
  
    public static void main(String[] args) 
    {
        // Let us construct the tree given 
        // in the above diagram
          
        node root = new node(20);
        root.left = new node(8);
        root.left.left = new node(4);
        root.left.right = new node(12);
        root.left.right.left = new node(10);
        root.left.right.right = new node(14);
        root.right = new node(22);
        root.right.right = new node(25);
        System.out.println("Size of the Largest Independent Set is " + liss(root));
    }
}

287
Chapter 26. DP-26 | Largest Independent Set Problem

  
// This code is contributed by Rishabh Mahrsee

Output

Size of the Largest Independent Set is 5

Time Complexity: O(n) where n is the number of nodes in given Binary tree.
Following extensions to above solution can be tried as an exercise.
1) Extend the above solution for n-ary tree.
2) The above solution modifies the given tree structure by adding an additional field ‘liss’
to tree nodes. Extend the solution so that it doesn’t modify the tree structure.
3) The above solution only returns size of LIS, it doesn’t print elements of LIS. Extend the
solution to print all nodes that are part of LIS.

Source

https://www.geeksforgeeks.org/largest-independent-set-problem-dp-26/

288
Chapter 27

DP-27 | Maximum sum


rectangle in a 2D matrix

Maximum sum rectangle in a 2D matrix | DP-27 - GeeksforGeeks


Given a 2D array, find the maximum sum subarray in it. For example, in the following
2D array, the maximum sum subarray is highlighted with blue rectangle and sum of this
subarray is 29.

This problem is mainly an extension of Largest Sum Contiguous Subarray for 1D array.
The naive solution for this problem is to check every possible rectangle in given 2D array.
This solution requires 4 nested loops and time complexity of this solution would be O(n^4).
Kadane’s algorithm for 1D array can be used to reduce the time complexity to O(n^3).
The idea is to fix the left and right columns one by one and find the maximum sum
contiguous rows for every left and right column pair. We basically find top and bottom row
numbers (which have maximum sum) for every fixed left and right column pair. To find
the top and bottom row numbers, calculate sun of elements in every row from left to right
and store these sums in an array say temp[]. So temp[i] indicates sum of elements from left

289
Chapter 27. DP-27 | Maximum sum rectangle in a 2D matrix

to right in row i. If we apply Kadane’s 1D algorithm on temp[], and get the maximum sum
subarray of temp, this maximum sum would be the maximum possible sum with left and
right as boundary columns. To get the overall maximum sum, we compare this sum with
the maximum sum so far.

// Program to find maximum sum subarray in a given 2D array


#include <stdio.h>
#include <string.h>
#include <limits.h>
#define ROW 4
#define COL 5
  
// Implementation of Kadane's algorithm for 1D array. The function 
// returns the maximum sum and stores starting and ending indexes of the 
// maximum sum subarray at addresses pointed by start and finish pointers 
// respectively.
int kadane(int* arr, int* start, int* finish, int n)
{
    // initialize sum, maxSum and
    int sum = 0, maxSum = INT_MIN, i;
  
    // Just some initial value to check for all negative values case
    *finish = -1;
  
    // local variable
    int local_start = 0;
  
    for (i = 0; i < n; ++i)
    {
        sum += arr[i];
        if (sum < 0)
        {
            sum = 0;
            local_start = i+1;
        }
        else if (sum > maxSum)
        {
            maxSum = sum;
            *start = local_start;
            *finish = i;
        }
    }
  
     // There is at-least one non-negative number
    if (*finish != -1)
        return maxSum;

290
Chapter 27. DP-27 | Maximum sum rectangle in a 2D matrix

  
    // Special Case: When all numbers in arr[] are negative
    maxSum = arr[0];
    *start = *finish = 0;
  
    // Find the maximum element in array
    for (i = 1; i < n; i++)
    {
        if (arr[i] > maxSum)
        {
            maxSum = arr[i];
            *start = *finish = i;
        }
    }
    return maxSum;
}
  
// The main function that finds maximum sum rectangle in M[][]
void findMaxSum(int M[][COL])
{
    // Variables to store the final output
    int maxSum = INT_MIN, finalLeft, finalRight, finalTop, finalBottom;
  
    int left, right, i;
    int temp[ROW], sum, start, finish;
  
    // Set the left column
    for (left = 0; left < COL; ++left)
    {
        // Initialize all elements of temp as 0
        memset(temp, 0, sizeof(temp));
  
        // Set the right column for the left column set by outer loop
        for (right = left; right < COL; ++right)
        {
           // Calculate sum between current left and right for every row 'i'
            for (i = 0; i < ROW; ++i)
                temp[i] += M[i][right];
  
            // Find the maximum sum subarray in temp[]. The kadane() 
            // function also sets values of start and finish.  So 'sum' is 
            // sum of rectangle between (start, left) and (finish, right) 
            //  which is the maximum sum with boundary columns strictly as
            //  left and right.
            sum = kadane(temp, &start, &finish, ROW);
  
            // Compare sum with maximum sum so far. If sum is more, then 
            // update maxSum and other output values

291
Chapter 27. DP-27 | Maximum sum rectangle in a 2D matrix

            if (sum > maxSum)


            {
                maxSum = sum;
                finalLeft = left;
                finalRight = right;
                finalTop = start;
                finalBottom = finish;
            }
        }
    }
  
    // Print final values
    printf("(Top, Left) (%d, %d)\n", finalTop, finalLeft);
    printf("(Bottom, Right) (%d, %d)\n", finalBottom, finalRight);
    printf("Max sum is: %d\n", maxSum);
}
  
// Driver program to test above functions
int main()
{
    int M[ROW][COL] = {{1, 2, -1, -4, -20},
                       {-8, -3, 4, 2, 1},
                       {3, 8, 10, 1, 3},
                       {-4, -1, 1, 7, -6}
                      };
  
    findMaxSum(M);
  
    return 0;
}

Java

import java.util.*;
import java.lang.*;
import java.io.*;
  
/**
 * Given a 2D array, find the maximum sum subarray in it
 */
class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        findMaxSubMatrix(new int[][] {
                            {1, 2, -1, -4, -20},
                            {-8, -3, 4, 2, 1},
                            {3, 8, 10, 1, 3},

292
Chapter 27. DP-27 | Maximum sum rectangle in a 2D matrix

                            {-4, -1, 1, 7, -6}


                            });
    }
      
    /**
     * To find maxSum in 1d array
     * 
     * return {maxSum, left, right}
     */ 
    public static int[] kadane(int[] a) {
        //result[0] == maxSum, result[1] == start, result[2] == end;
        int[] result = new int[]{Integer.MIN_VALUE, 0, -1};
        int currentSum = 0;
        int localStart = 0;
      
        for (int i = 0; i < a.length; i++) {
            currentSum += a[i];
            if (currentSum < 0) {
                  currentSum = 0;
                localStart = i + 1;
              } else if (currentSum > result[0]) {
                result[0] = currentSum;
                result[1] = localStart;
                result[2] = i;
              }
        }
          
        //all numbers in a are negative
        if (result[2] == -1) {
            result[0] = 0;
            for (int i = 0; i < a.length; i++) {
                if (a[i] > result[0]) {
                    result[0] = a[i];
                    result[1] = i;
                    result[2] = i;
                }
            }
        }
          
        return result;
      }
  
    /**
     * To find and print maxSum, (left, top),(right, bottom)
     */
    public static void findMaxSubMatrix(int[][] a) {
        int cols = a[0].length;
        int rows = a.length;

293
Chapter 27. DP-27 | Maximum sum rectangle in a 2D matrix

        int[] currentResult;
        int maxSum = Integer.MIN_VALUE;
        int left = 0;
        int top = 0;
        int right = 0;
        int bottom = 0;
          
        for (int leftCol = 0; leftCol < cols; leftCol++) {
            int[] tmp = new int[rows];
      
              for (int rightCol = leftCol; rightCol < cols; rightCol++) {
          
                for (int i = 0; i < rows; i++) {
                      tmp[i] += a[i][rightCol];
                }
                currentResult = kadane(tmp);
                if (currentResult[0] > maxSum) {
                    maxSum = currentResult[0];
                    left = leftCol;
                    top = currentResult[1];
                    right = rightCol;
                    bottom = currentResult[2];
                }
            }
        }
              System.out.println("MaxSum: " + maxSum + 
                                ", range: [(" + left + ", " + top + 
                                  ")(" + right + ", " + bottom + ")]");
    }
}
// Thanks to Ilia Savin for contributing this code.

Output:

(Top, Left) (1, 1)


(Bottom, Right) (3, 3)
Max sum is: 29

Time Complexity: O(n^3)


This article is compiled byAashish Barnwal. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above.
Improved By : Gaurav Kumar 33

294
Chapter 27. DP-27 | Maximum sum rectangle in a 2D matrix

Source

https://www.geeksforgeeks.org/maximum-sum-rectangle-in-a-2d-matrix-dp-27/

295
Chapter 28

DP-28 | Minimum insertions to


form a palindrome

Minimum insertions to form a palindrome | DP-28 - GeeksforGeeks


Given a string, find the minimum number of characters to be inserted to convert it to
palindrome.
Before we go further, let us understand with few examples:

• ab: Number of insertions required is 1 i.e. bab


• aa: Number of insertions required is 0 i.e. aa
• abcd: Number of insertions required is 3 i.e. dcbabcd
• abcda: Number of insertions required is 2 i.e. adcbcda which is same as number of
insertions in the substring bcd(Why?).
• abcde: Number of insertions required is 4 i.e. edcbabcde

Let the input string be str[l……h]. The problem can be broken down into three parts:
1. Find the minimum number of insertions in the substring str[l+1,…….h].
2. Find the minimum number of insertions in the substring str[l…….h-1].
3. Find the minimum number of insertions in the substring str[l+1……h-1].
Recursive Solution
The minimum number of insertions in the string str[l…..h] can be given as:

• minInsertions(str[l+1…..h-1]) if str[l] is equal to str[h]


• min(minInsertions(str[l…..h-1]), minInsertions(str[l+1…..h])) + 1 otherwise

// A Naive recursive program to find minimum 


// number insertions needed to make a string

296
Chapter 28. DP-28 | Minimum insertions to form a palindrome

// palindrome
#include <stdio.h>
#include <limits.h>
#include <string.h>
  
// A utility function to find minimum of two numbers
int min(int a, int b)
{  return a < b ? a : b; }
  
// Recursive function to find minimum number of 
// insertions
int findMinInsertions(char str[], int l, int h)
{
    // Base Cases
    if (l > h) return INT_MAX;
    if (l == h) return 0;
    if (l == h - 1) return (str[l] == str[h])? 0 : 1;
  
    // Check if the first and last characters are
    // same. On the basis of the comparison result, 
    // decide which subrpoblem(s) to call
    return (str[l] == str[h])? 
                     findMinInsertions(str, l + 1, h - 1):
                     (min(findMinInsertions(str, l, h - 1),
                     findMinInsertions(str, l + 1, h)) + 1);
}
  
// Driver program to test above functions
int main()
{
    char str[] = "geeks";
    printf("%d", findMinInsertions(str, 0, strlen(str)-1));
    return 0;
}

Java

// A Naive recursive Java program to find minimum


// number insertions needed to make a string
// palindrome
class GFG {
  
    // Recursive function to find minimum number
    // of insertions
    static int findMinInsertions(char str[], int l,
                                             int h)
    {
        // Base Cases

297
Chapter 28. DP-28 | Minimum insertions to form a palindrome

        if (l > h) return Integer.MAX_VALUE;


        if (l == h) return 0;
        if (l == h - 1) return (str[l] == str[h])? 0 : 1;
  
        // Check if the first and last characters
        // are same. On the basis of the  comparison
        // result, decide which subrpoblem(s) to call
        return (str[l] == str[h])?
            findMinInsertions(str, l + 1, h - 1):
            (Integer.min(findMinInsertions(str, l, h - 1),
            findMinInsertions(str, l + 1, h)) + 1);
    }
  
    // Driver program to test above functions
    public static void main(String args[])
    {
        String str= "geeks";
        System.out.println(findMinInsertions(str.toCharArray(),
                                          0, str.length()-1));
    }
}
// This code is contributed by Sumit Ghosh

C#

// A Naive recursive C# program 


// to find minimum number 
// insertions needed to make 
// a string palindrom
using System;
  
class GFG
{
    // Recursive function to 
    // find minimum number of
    // insertions
    static int findMinInsertions(char []str, 
                                 int l, int h)
    {
        // Base Cases
        if (l > h) return int.MaxValue;
        if (l == h) return 0;
        if (l == h - 1) 
            return (str[l] == str[h])? 0 : 1;
  
        // Check if the first and 
        // last characters are same. 
        // On the basis of the 

298
Chapter 28. DP-28 | Minimum insertions to form a palindrome

        // comparison result, decide 


        // which subrpoblem(s) to call
        return (str[l] == str[h])?
                findMinInsertions(str, 
                                  l + 1, h - 1):
                (Math.Min(findMinInsertions(str, l, 
                                            h - 1),
                          findMinInsertions(str, l + 
                                        1, h)) + 1);
    } 
      
    // Driver Code
    public static void Main()
    {
        string str= "geeks";
        Console.WriteLine(findMinInsertions(str.ToCharArray(),
                                            0, str.Length - 1)); 
    }
}
  
// This code is contributed by Sam007

Output:

Dynamic Programming based Solution


If we observe the above approach carefully, we can find that it exhibits overlapping subprob-
lems.
Suppose we want to find the minimum number of insertions in string “abcde”:

abcde
/ | \
/ | \
bcde abcd bcd <- case 3 is discarded as str[l] != str[h]
/ | \ / | \
/ | \ / | \
cde bcd cd bcd abc bc
/ | \ / | \ /|\ / | \
de cd d cd bc c………………….

The substrings in bold show that the recursion to be terminated and the recursion tree cannot
originate from there. Substring in the same color indicates overlapping subproblems.
How to reuse solutions of subproblems?
We can create a table to store results of subproblems so that they can be used directly if
same subproblem is encountered again.
The below table represents the stored values for the string abcde.

299
Chapter 28. DP-28 | Minimum insertions to form a palindrome

a b c d e
----------
0 1 2 3 4
0 0 1 2 3
0 0 0 1 2
0 0 0 0 1
0 0 0 0 0

How to fill the table?


The table should be filled in diagonal fashion. For the string abcde, 0….4, the following
should be order in which the table is filled:

Gap = 1:
(0, 1) (1, 2) (2, 3) (3, 4)

Gap = 2:
(0, 2) (1, 3) (2, 4)

Gap = 3:
(0, 3) (1, 4)

Gap = 4:
(0, 4)

// A Dynamic Programming based program to find


// minimum number insertions needed to make a
// string palindrome
#include <stdio.h>
#include <string.h>
  
// A utility function to find minimum of two integers
int min(int a, int b)
{   return a < b ? a : b;  }
  
// A DP function to find minimum number of insertions
int findMinInsertionsDP(char str[], int n)
{
    // Create a table of size n*n. table[i][j]
    // will store minimum number of insertions 
    // needed to convert str[i..j] to a palindrome.
    int table[n][n], l, h, gap;
  
    // Initialize all table entries as 0
    memset(table, 0, sizeof(table));

300
Chapter 28. DP-28 | Minimum insertions to form a palindrome

  
    // Fill the table
    for (gap = 1; gap < n; ++gap)
        for (l = 0, h = gap; h < n; ++l, ++h)
            table[l][h] = (str[l] == str[h])?
                          table[l+1][h-1] :
                          (min(table[l][h-1], 
                           table[l+1][h]) + 1);
  
    // Return minimum number of insertions for
    // str[0..n-1]
    return table[0][n-1];
}
  
// Driver program to test above function.
int main()
{
    char str[] = "geeks";
    printf("%d", findMinInsertionsDP(str, strlen(str)));
    return 0;
}

Java

// A Java solution for Dynamic Programming


// based program to find minimum number
// insertions needed to make a string
// palindrome
import java.util.Arrays;
  
class GFG
{
    // A DP function to find minimum number
    // of insersions
    static int findMinInsertionsDP(char str[], int n)
    {
        // Create a table of size n*n. table[i][j]
        // will store minumum number of insertions
        // needed to convert str[i..j] to a palindrome.
        int table[][] = new int[n][n];
        int l, h, gap;
  
        // Fill the table
        for (gap = 1; gap < n; ++gap)
        for (l = 0, h = gap; h < n; ++l, ++h)
            table[l][h] = (str[l] == str[h])?
                           table[l+1][h-1] :
                          (Integer.min(table[l][h-1],

301
Chapter 28. DP-28 | Minimum insertions to form a palindrome

                                 table[l+1][h]) + 1);
  
        // Return minimum number of insertions
        // for str[0..n-1]
        return table[0][n-1];
    }
  
    // Driver program to test above function.
    public static void main(String args[])
    {
        String str = "geeks";
        System.out.println(
        findMinInsertionsDP(str.toCharArray(), str.length()));
    }
}
// This code is contributed by Sumit Ghosh

Output:

Time complexity: O(N^2)


Auxiliary Space: O(N^2)
Another Dynamic Programming Solution (Variation of Longest Common Sub-
sequence Problem)
The problem of finding minimum insertions can also be solved using Longest Common Sub-
sequence (LCS) Problem. If we find out LCS of string and its reverse, we know how many
maximum characters can form a palindrome. We need insert remaining characters. Follow-
ing are the steps.
1) Find the length of LCS of input string and its reverse. Let the length be ‘l’.
2) The minimum number insertions needed is length of input string minus ‘l’.
C

// An LCS based program to find minimum number


// insertions needed to make a string palindrome
#include<stdio.h>
#include <string.h>
  
/* Utility function to get max of 2 integers */
int max(int a, int b)
{   return (a > b)? a : b; }
  
/* Returns length of LCS for X[0..m-1], Y[0..n-1]. 
   See http://goo.gl/bHQVP for details of this 
   function */
int lcs( char *X, char *Y, int m, int n )

302
Chapter 28. DP-28 | Minimum insertions to form a palindrome

{
   int L[n+1][n+1];
   int i, j;
  
   /* Following steps build L[m+1][n+1] in bottom 
      up fashion. Note that L[i][j] contains length
      of LCS of X[0..i-1] and Y[0..j-1] */
   for (i=0; i<=m; i++)
   {
     for (j=0; j<=n; j++)
     {
       if (i == 0 || j == 0)
         L[i][j] = 0;
  
       else if (X[i-1] == Y[j-1])
         L[i][j] = L[i-1][j-1] + 1;
  
       else
         L[i][j] = max(L[i-1][j], L[i][j-1]);
     }
   }
  
   /* L[m][n] contains length of LCS for X[0..n-1]
     and Y[0..m-1] */
   return L[m][n];
}
  
// LCS based function to find minimum number of 
// insertions
int findMinInsertionsLCS(char str[], int n)
{
   // Creata another string to store reverse of 'str'
   char rev[n+1];
   strcpy(rev, str);
   strrev(rev);
  
   // The output is length of string minus length of lcs of
   // str and it reverse
   return (n - lcs(str, rev, n, n));
}
  
// Driver program to test above functions
int main()
{
    char str[] = "geeks";
    printf("%d", findMinInsertionsLCS(str, strlen(str)));
    return 0;
}

303
Chapter 28. DP-28 | Minimum insertions to form a palindrome

Java

// An LCS based Java program to find minimum


// number insertions needed to make a string
// palindrome
class GFG
{
    /* Returns length of LCS for X[0..m-1],
       Y[0..n-1]. See http://goo.gl/bHQVP for
       details of this function */
    static int lcs( String X, String Y, int m, int n )
    {
        int L[][] = new int[n+1][n+1];
        int i, j;
  
        /* Following steps build L[m+1][n+1] in
           bottom up fashion. Note that L[i][j]
           contains length of LCS of X[0..i-1]
           and Y[0..j-1] */
        for (i=0; i<=m; i++)
        {
            for (j=0; j<=n; j++)
            {
                if (i == 0 || j == 0)
                    L[i][j] = 0;
  
                else if (X.charAt(i-1) == Y.charAt(j-1))
                    L[i][j] = L[i-1][j-1] + 1;
  
                else
                    L[i][j] = Integer.max(L[i-1][j], L[i][j-1]);
            }
        }
  
        /* L[m][n] contains length of LCS for
           X[0..n-1] and Y[0..m-1] */
        return L[m][n];
    }
  
    // LCS based function to find minimum number
    // of insersions
    static int findMinInsertionsLCS(String str, int n)
    {
        // Using StringBuffer to reverse a String
        StringBuffer sb = new StringBuffer(str);
        sb.reverse();
        String revString = sb.toString();
  

304
Chapter 28. DP-28 | Minimum insertions to form a palindrome

        // The output is length of string minus


        // length of lcs of str and it reverse
        return (n - lcs(str, revString , n, n));
    }
  
    // Driver program to test above functions
    public static void main(String args[])
    {
        String str = "geeks";
        System.out.println(
        findMinInsertionsLCS(str, str.length()));
    }
}
// This code is contributed by Sumit Ghosh

Output:

Time complexity of this method is also O(n^2) and this method also requires O(n^2) extra
space.
Related Article :
Minimum number of Appends needed to make a string palindrome
This article is compiled by Aashish Barnwal. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above
Improved By : Sam007

Source

https://www.geeksforgeeks.org/minimum-insertions-to-form-a-palindrome-dp-28/

305
Chapter 29

DP-29 | Longest Common


Substring

Longest Common Substring | DP-29 - GeeksforGeeks


Given two strings ‘X’ and ‘Y’, find the length of the longest common substring.
Examples :

Input : X = "GeeksforGeeks", y = "GeeksQuiz"


Output : 5
The longest common substring is "Geeks" and is of
length 5.

Input : X = "abcdxyz", y = "xyzabcd"


Output : 4
The longest common substring is "abcd" and is of
length 4.

Input : X = "zxabcdezy", y = "yzabcdezx"


Output : 6
The longest common substring is "abcdez" and is of
length 6.

306
Chapter 29. DP-29 | Longest Common Substring

Let m and n be the lengths of first and second strings respectively.


A simple solution is to one by one consider all substrings of first string and for every
substring check if it is a substring in second string. Keep track of the maximum length
substring. There will be O(m^2) substrings and we can find whether a string is subsring on
another string in O(n) time (See this). So overall time complexity of this method would be
O(n * m2 )
Dynamic Programming can be used to find the longest common substring in O(m*n)
time. The idea is to find length of the longest common suffix for all substrings of both
strings and store these lengths in a table.

The longest common suffix has following optimal substructure property


LCSuff(X, Y, m, n) = LCSuff(X, Y, m-1, n-1) + 1 if X[m-1] = Y[n-1]
0 Otherwise (if X[m-1] != Y[n-1])

The maximum length Longest Common Suffix is the longest common substring.
LCSubStr(X, Y, m, n) = Max(LCSuff(X, Y, i, j)) where 1 <= i <= m
and 1 <= j <= n

Following is the implementation of the above solution.

C++

/* Dynamic Programming solution to find length of the 


   longest common substring */
#include<iostream>
#include<string.h>

307
Chapter 29. DP-29 | Longest Common Substring

using namespace std;


  
// A utility function to find maximum of two integers
int max(int a, int b)
{   return (a > b)? a : b; }
  
/* Returns length of longest common substring of X[0..m-1] 
   and Y[0..n-1] */
int LCSubStr(char *X, char *Y, int m, int n)
{
    // Create a table to store lengths of longest common suffixes of
    // substrings.   Notethat LCSuff[i][j] contains length of longest
    // common suffix of X[0..i-1] and Y[0..j-1]. The first row and
    // first column entries have no logical meaning, they are used only
    // for simplicity of program
    int LCSuff[m+1][n+1];
    int result = 0;  // To store length of the longest common substring
  
    /* Following steps build LCSuff[m+1][n+1] in bottom up fashion. */
    for (int i=0; i<=m; i++)
    {
        for (int j=0; j<=n; j++)
        {
            if (i == 0 || j == 0)
                LCSuff[i][j] = 0;
  
            else if (X[i-1] == Y[j-1])
            {
                LCSuff[i][j] = LCSuff[i-1][j-1] + 1;
                result = max(result, LCSuff[i][j]);
            }
            else LCSuff[i][j] = 0;
        }
    }
    return result;
}
  
/* Driver program to test above function */
int main()
{
    char X[] = "OldSite:GeeksforGeeks.org";
    char Y[] = "NewSite:GeeksQuiz.com";
  
    int m = strlen(X);
    int n = strlen(Y);
  
    cout << "Length of Longest Common Substring is " 
         << LCSubStr(X, Y, m, n);

308
Chapter 29. DP-29 | Longest Common Substring

    return 0;
}

Java

//  Java implementation of finding length of longest 


// Common substring using Dynamic Programming
public class LongestCommonSubSequence 
{
    /* 
       Returns length of longest common substring  
       of X[0..m-1] and Y[0..n-1] 
    */
    static int LCSubStr(char X[], char Y[], int m, int n) 
    {
        // Create a table to store lengths of longest common suffixes of
        // substrings. Note that LCSuff[i][j] contains length of longest
        // common suffix of X[0..i-1] and Y[0..j-1]. The first row and
        // first column entries have no logical meaning, they are used only
        // for simplicity of program
        int LCStuff[][] = new int[m + 1][n + 1];
        int result = 0;  // To store length of the longest common substring
          
        // Following steps build LCSuff[m+1][n+1] in bottom up fashion
        for (int i = 0; i <= m; i++) 
        {
            for (int j = 0; j <= n; j++) 
            {
                if (i == 0 || j == 0)
                    LCStuff[i][j] = 0;
                else if (X[i - 1] == Y[j - 1])
                {
                    LCStuff[i][j] = LCStuff[i - 1][j - 1] + 1;
                    result = Integer.max(result, LCStuff[i][j]);
                } 
                else
                    LCStuff[i][j] = 0;
            }
        }
        return result;
    }
      
    // Driver Program to test above function
    public static void main(String[] args) 
    {
        String X = "OldSite:GeeksforGeeks.org";
        String Y = "NewSite:GeeksQuiz.com";
  

309
Chapter 29. DP-29 | Longest Common Substring

        int m = X.length();
        int n = Y.length();
  
        System.out.println("Length of Longest Common Substring is "
                + LCSubStr(X.toCharArray(), Y.toCharArray(), m, n));
    }
}
  
// This code is contributed by Sumit Ghosh

Python3

# Python3 implementation of Finding 


# Length of Longest Common Substring 
  
# Returns length of longest common 
# substring of X[0..m-1] and Y[0..n-1] 
def LCSubStr(X, Y, m, n):
      
    # Create a table to store lengths of
    # longest common suffixes of substrings. 
    # Note that LCSuff[i][j] contains the 
    # length of longest common suffix of 
    # X[0...i-1] and Y[0...j-1]. The first
    # row and first column entries have no
    # logical meaning, they are used only
    # for simplicity of the program.
      
    # LCSuff is the table with zero 
    # value initially in each cell
    LCSuff = [[0 for k in range(n+1)] for l in range(m+1)]
      
    # To store the length of 
    # longest common substring
    result = 0 
  
    # Following steps to build
    # LCSuff[m+1][n+1] in bottom up fashion
    for i in range(m + 1):
        for j in range(n + 1):
            if (i == 0 or j == 0):
                LCSuff[i][j] = 0
            elif (X[i-1] == Y[j-1]):
                LCSuff[i][j] = LCSuff[i-1][j-1] + 1
                result = max(result, LCSuff[i][j])
            else:
                LCSuff[i][j] = 0
    return result

310
Chapter 29. DP-29 | Longest Common Substring

  
# Driver Program to test above function
X = 'OldSite:GeeksforGeeks.org'
Y = 'NewSite:GeeksQuiz.com'
  
m = len(X)
n = len(Y)
  
print('Length of Longest Common Substring is',
                      LCSubStr(X, Y, m, n))
  
# This code is contributed by Soumen Ghosh

C#

// C# implementation of finding length of longest


// Common substring using Dynamic Programming
using System;
  
class GFG {
       
    // Returns length of longest common 
    // substring of X[0..m-1] and Y[0..n-1] 
    static int LCSubStr(string X, string Y,
                                 int m, int n)
    {
          
        // Create a table to store lengths of 
        // longest common suffixes of substrings.
        // Note that LCSuff[i][j] contains length
        // of longest common suffix of X[0..i-1] 
        // and Y[0..j-1]. The first row and first
        // column entries have no logical meaning,
        // they are used only for simplicity of 
        // program
        int[, ] LCStuff = new int[m + 1, n + 1];
          
        // To store length of the longest common
        // substring
        int result = 0; 
  
        // Following steps build LCSuff[m+1][n+1] 
        // in bottom up fashion
        for (int i = 0; i <= m; i++) {
            for (int j = 0; j <= n; j++) {
                if (i == 0 || j == 0)
                    LCStuff[i, j] = 0;
                else if (X[i - 1] == Y[j - 1]) {

311
Chapter 29. DP-29 | Longest Common Substring

                    LCStuff[i, j] = 
                            LCStuff[i - 1, j - 1] + 1;
                              
                    result = Math.Max(result, 
                                      LCStuff[i, j]);
                }
                else
                    LCStuff[i, j] = 0;
            }
        }
          
        return result;
    }
  
    // Driver Program to test above function
    public static void Main()
    {
        String X = "OldSite:GeeksforGeeks.org";
        String Y = "NewSite:GeeksQuiz.com";
  
        int m = X.Length;
        int n = Y.Length;
  
        Console.Write("Length of Longest Common"
        + " Substring is " + LCSubStr(X, Y, m, n));
    }
  
}
  
// This code is contributed by Sam007.

Output:

Length of Longest Common Substring is 10

Time Complexity: O(m*n)


Auxiliary Space: O(m*n)
References: http://en.wikipedia.org/wiki/Longest_common_substring_problem
The longest substring can also be solved in O(n+m) time using Suffix Tree. We will be
covering Suffix Tree based solution in a separate post.
Exercise: The above solution prints only length of the longest common substring. Extend
the solution to print the substring also.

Source
https://www.geeksforgeeks.org/longest-common-substring-dp-29/

312
Chapter 30

DP-30 | Dice Throw

Dice Throw | DP-30 - GeeksforGeeks


Given n dice each with m faces, numbered from 1 to m, find the number of ways to get sum
X. X is the summation of values on each face when all the dice are thrown.
The Naive approach is to find all the possible combinations of values from n dice and keep
on counting the results that sum to X.
This problem can be efficiently solved using Dynamic Programming (DP).

Let the function to find X from n dice is: Sum(m, n, X)


The function can be represented as:
Sum(m, n, X) = Finding Sum (X - 1) from (n - 1) dice plus 1 from nth dice
+ Finding Sum (X - 2) from (n - 1) dice plus 2 from nth dice
+ Finding Sum (X - 3) from (n - 1) dice plus 3 from nth dice
...................................................
...................................................
...................................................
+ Finding Sum (X - m) from (n - 1) dice plus m from nth dice

So we can recursively write Sum(m, n, x) as following


Sum(m, n, X) = Sum(m, n - 1, X - 1) +
Sum(m, n - 1, X - 2) +
.................... +
Sum(m, n - 1, X - m)

Why DP approach?
The above problem exhibits overlapping subproblems. See the below diagram. Also, see
thisrecursive implementation. Let there be 3 dice, each with 6 faces and we need to find the
number of ways to get sum 8:

313
Chapter 30. DP-30 | Dice Throw

Sum(6, 3, 8) = Sum(6, 2, 7) + Sum(6, 2, 6) + Sum(6, 2, 5) +


Sum(6, 2, 4) + Sum(6, 2, 3) + Sum(6, 2, 2)

To evaluate Sum(6, 3, 8), we need to evaluate Sum(6, 2, 7) which can


recursively written as following:
Sum(6, 2, 7) = Sum(6, 1, 6) + Sum(6, 1, 5) + Sum(6, 1, 4) +
Sum(6, 1, 3) + Sum(6, 1, 2) + Sum(6, 1, 1)

We also need to evaluate Sum(6, 2, 6) which can recursively written


as following:
Sum(6, 2, 6) = Sum(6, 1, 5) + Sum(6, 1, 4) + Sum(6, 1, 3) +
Sum(6, 1, 2) + Sum(6, 1, 1)
..............................................
..............................................
Sum(6, 2, 2) = Sum(6, 1, 1)

Please take a closer look at the above recursion. The sub-problems in RED are solved
first time and sub-problems in BLUE are solved again (exhibit overlapping sub-problems).
Hence, storing the results of the solved sub-problems saves time.
Following is implementation of Dynamic Programming approach.

C++

// C++ program to find number of ways to get sum 'x' with 'n'
// dice where every dice has 'm' faces
#include <iostream>
#include <string.h>
using namespace std;
  
// The main function that returns number of ways to get sum 'x'
// with 'n' dice and 'm' with m faces.
int findWays(int m, int n, int x)
{

314
Chapter 30. DP-30 | Dice Throw

    // Create a table to store results of subproblems.  One extra 


    // row and column are used for simpilicity (Number of dice
    // is directly used as row index and sum is directly used
    // as column index).  The entries in 0th row and 0th column
    // are never used.
    int table[n + 1][x + 1];
    memset(table, 0, sizeof(table)); // Initialize all entries as 0
  
    // Table entries for only one dice
    for (int j = 1; j <= m && j <= x; j++)
        table[1][j] = 1;
  
    // Fill rest of the entries in table using recursive relation
    // i: number of dice, j: sum
    for (int i = 2; i <= n; i++)
        for (int j = 1; j <= x; j++)
            for (int k = 1; k <= m && k < j; k++)
                table[i][j] += table[i-1][j-k];
  
    /* Uncomment these lines to see content of table
    for (int i = 0; i <= n; i++)
    {
      for (int j = 0; j <= x; j++)
        cout << table[i][j] << " ";
      cout << endl;
    } */
    return table[n][x];
}
  
// Driver program to test above functions
int main()
{
    cout << findWays(4, 2, 1) << endl;
    cout << findWays(2, 2, 3) << endl;
    cout << findWays(6, 3, 8) << endl;
    cout << findWays(4, 2, 5) << endl;
    cout << findWays(4, 3, 5) << endl;
  
    return 0;
}

C#

// C# program to find number 


// of ways to get sum 'x' 
// with 'n' dice where every 
// dice has 'm' faces
using System;

315
Chapter 30. DP-30 | Dice Throw

  
class GFG
{
// The main function that returns 
// number of ways to get sum 'x'
// with 'n' dice and 'm' with m faces.
static int findWays(int m, 
                    int n, int x)
{
    // Create a table to store 
    // results of subproblems. 
    // row and column are used 
    // for simpilicity (Number 
    // of dice is directly used 
    // as row index and sum is 
    // directly used as column
    // index). The entries in 0th
    // row and 0th column are 
    // never used.
    int[,] table = new int[n + 1, 
                           x + 1];
                             
    // Initialize all 
    // entries as 0
    for (int i = 0; i <= n; i++)
    for (int j = 0; j <= x; j++)
    table[i, j] = 0;
      
    // Table entries for 
    // only one dice
    for (int j = 1; 
             j <= m && j <= x; j++)
        table[1, j] = 1;
  
    // Fill rest of the entries 
    // in table using recursive 
    // relation i: number of 
    // dice, j: sum
    for (int i = 2; i <= n; i++)
        for (int j = 1; j <= x; j++)
            for (int k = 1; 
                     k <= m && k < j; k++)
                table[i, j] += table[i - 1, 
                                     j - k];
  
    /* Uncomment these lines to
    see content of table
    for (int i = 0; i <= n; i++)

316
Chapter 30. DP-30 | Dice Throw

    {
    for (int j = 0; j <= x; j++)
        cout << table[i][j] << " ";
    cout << endl;
    } */
    return table[n, x];
}
  
// Driver Code
public static void Main()
{
    Console.WriteLine(findWays(4, 2, 1));
    Console.WriteLine(findWays(2, 2, 3));
    Console.WriteLine(findWays(6, 3, 8));
    Console.WriteLine(findWays(4, 2, 5));
    Console.WriteLine(findWays(4, 3, 5));
}
}
  
// This code is contributed by mits.

PHP

<?php
// PHP program to find number 
// of ways to get sum 'x' with
// 'n' dice where every dice
// has 'm' faces
  
// The main function that returns 
// number of ways to get sum 'x' 
// with 'n' dice and 'm' with m faces.
function findWays($m, $n, $x)
{
    // Create a table to store results  
    // of subproblems. One extra row 
    // and column are used for 
    // simpilicity (Number of dice is 
    // directly used as row index and 
    // sum is directly used as column 
    // index). The entries in 0th row 
    // and 0th column are never used.
    $table;
      
    // Initialize all entries as 0
        for ($i = 1; $i < $n + 1; $i++)
        for ($j = 1; $j < $x + 1; $j++)
        $table[$i][$j] = 0;

317
Chapter 30. DP-30 | Dice Throw

  
    // Table entries for
    // only one dice
    for ($j = 1; $j <= $m && 
                 $j <= $x; $j++)
        $table[1][$j] = 1;
  
    // Fill rest of the entries 
    // in table using recursive 
    // relation i: number of dice, 
    // j: sum
    for ($i = 2; $i <= $n; $i++)
        for ($j = 1; $j <= $x; $j++)
            for ($k = 1; $k <= $m && 
                         $k < $j; $k++)
                $table[$i][$j] += 
                        $table[$i - 1][$j - $k];
  
    return $table[$n][$x];
}
  
// Driver Code
echo findWays(4, 2, 1). "\n";
echo findWays(2, 2, 3). "\n";
echo findWays(6, 3, 8). "\n";
echo findWays(4, 2, 5). "\n";
echo findWays(4, 3, 5). "\n";
  
// This code is contributed by mits.
?>

Output :

0
2
21
4
6

Time Complexity: O(m * n * x) where m is number of faces, n is number of dice and x


is given sum.
We can add following two conditions at the beginning of findWays() to improve performance
of program for extreme cases (x is too high or x is too low)

// When x is so high that sum can not go beyond x even when we 
// get maximum value in every dice throw. 

318
Chapter 30. DP-30 | Dice Throw

if (m*n <= x)
    return (m*n == x);
 
// When x is too low
if (n >= x)
    return (n == x);

With above conditions added, time complexity becomes O(1) when x >= m*n or when x
<= n.
Exercise:
Extend the above algorithm to find the probability to get Sum > X.
This article is compiled by Aashish Barnwal. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above
Improved By : Mithun Kumar

Source

https://www.geeksforgeeks.org/dice-throw-dp-30/

319
Chapter 31

DP-31 | Optimal Strategy for a


Game

Optimal Strategy for a Game | DP-31 - GeeksforGeeks


Problem statement: Consider a row of n coins of values v1 . . . vn, where n is even. We
play a game against an opponent by alternating turns. In each turn, a player selects either
the first or last coin from the row, removes it from the row permanently, and receives the
value of the coin. Determine the maximum possible amount of money we can definitely win
if we move first.
Note: The opponent is as clever as the user.
Let us understand the problem with few examples:
1. 5, 3, 7, 10 : The user collects maximum value as 15(10 + 5)
2. 8, 15, 3, 7 : The user collects maximum value as 22(7 + 15)
Does choosing the best at each move give an optimal solution?
No. In the second example, this is how the game can finish:
1.
…….User chooses 8.
…….Opponent chooses 15.
…….User chooses 7.
…….Opponent chooses 3.
Total value collected by user is 15(8 + 7)
2.
…….User chooses 7.
…….Opponent chooses 8.
…….User chooses 15.
…….Opponent chooses 3.
Total value collected by user is 22(7 + 15)

320
Chapter 31. DP-31 | Optimal Strategy for a Game

So if the user follows the second game state, maximum value can be collected although the
first move is not the best.
There are two choices:
1. The user chooses the ith coin with value Vi: The opponent either chooses (i+1)th coin
or jth coin. The opponent intends to choose the coin which leaves the user with minimum
value.
i.e. The user can collect the value Vi + min(F(i+2, j), F(i+1, j-1) )

2. The user chooses the jth coin with value Vj: The opponent either chooses ith coin or
(j-1)th coin. The opponent intends to choose the coin which leaves the user with minimum
value.
i.e. The user can collect the value Vj + min(F(i+1, j-1), F(i, j-2) )

Following is recursive solution that is based on above two choices. We take the maximum
of two choices.

F(i, j) represents the maximum value the user can collect from
i'th coin to j'th coin.

F(i, j) = Max(Vi + min(F(i+2, j), F(i+1, j-1) ),


Vj + min(F(i+1, j-1), F(i, j-2) ))
Base Cases
F(i, j) = Vi If j == i
F(i, j) = max(Vi, Vj) If j == i+1

Why Dynamic Programming?


The above relation exhibits overlapping sub-problems. In the above relation, F(i+1, j-1) is

321
Chapter 31. DP-31 | Optimal Strategy for a Game

calculated twice.

C++

// C program to find out maximum value from a given sequence of coins


#include <limits.h>
#include <stdio.h>
  
// Utility functions to get maximum and minimum of two intgers
int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a < b ? a : b; }
  
// Returns optimal value possible that a player can collect from
// an array of coins of size n. Note than n must be even
int optimalStrategyOfGame(int* arr, int n)
{
    // Create a table to store solutions of subproblems
    int table[n][n], gap, i, j, x, y, z;
  
    // Fill table using above recursive formula. Note that the table
    // is filled in diagonal fashion (similar to http:// goo.gl/PQqoS),
    // from diagonal elements to table[0][n-1] which is the result.
    for (gap = 0; gap < n; ++gap) {
        for (i = 0, j = gap; j < n; ++i, ++j) {
            // Here x is value of F(i+2, j), y is F(i+1, j-1) and
            // z is F(i, j-2) in above recursive formula
            x = ((i + 2) <= j) ? table[i + 2][j] : 0;
            y = ((i + 1) <= (j - 1)) ? table[i + 1][j - 1] : 0;
            z = (i <= (j - 2)) ? table[i][j - 2] : 0;
  
            table[i][j] = max(arr[i] + min(x, y), arr[j] + min(y, z));
        }
    }
  
    return table[0][n - 1];
}
  
// Driver program to test above function
int main()
{
    int arr1[] = { 8, 15, 3, 7 };
    int n = sizeof(arr1) / sizeof(arr1[0]);
    printf("%dn", optimalStrategyOfGame(arr1, n));
  
    int arr2[] = { 2, 2, 2, 2 };
    n = sizeof(arr2) / sizeof(arr2[0]);
    printf("%dn", optimalStrategyOfGame(arr2, n));
  

322
Chapter 31. DP-31 | Optimal Strategy for a Game

    int arr3[] = { 20, 30, 2, 2, 2, 10 };


    n = sizeof(arr3) / sizeof(arr3[0]);
    printf("%dn", optimalStrategyOfGame(arr3, n));
  
    return 0;
}

Java

// Java program to find out maximum


// value from a given sequence of coins
import java.io.*;
  
class GFG {
    // Utility functions to get maximum
    // and minimum of two intgers
    int max(int a, int b) { return a > b ? a : b; }
    int min(int a, int b) { return a < b ? a : b; }
  
    // Returns optimal value possible that a player
    // can collect from an array of coins of size n.
    // Note than n must be even
    static int optimalStrategyOfGame(int arr[], int n)
    {
        // Create a table to store solutions of subproblems
        int table[][] = new int[n][n];
        int gap, i, j, x, y, z;
  
        // Fill table using above recursive formula.
        // Note that the tableis filled in diagonal
        // fashion (similar to http:// goo.gl/PQqoS),
        // from diagonal elements to table[0][n-1]
        // which is the result.
        for (gap = 0; gap < n; ++gap) {
            for (i = 0, j = gap; j < n; ++i, ++j) {
                // Here x is value of F(i+2, j),
                // y is F(i+1, j-1) and z is
                // F(i, j-2) in above recursive formula
                x = ((i + 2) <= j) ? table[i + 2][j] : 0;
                y = ((i + 1) <= (j - 1)) ? table[i + 1][j - 1] : 0;
                z = (i <= (j - 2)) ? table[i][j - 2] : 0;
  
                table[i][j] = Math.max(arr[i] + Math.min(x, y), arr[j] + Math.min(y, z));
            }
        }
  
        return table[0][n - 1];
    }

323
Chapter 31. DP-31 | Optimal Strategy for a Game

  
    // Driver program
    public static void main(String[] args)
    {
        int arr1[] = { 8, 15, 3, 7 };
        int n = arr1.length;
        System.out.println("" + optimalStrategyOfGame(arr1, n));
  
        int arr2[] = { 2, 2, 2, 2 };
        n = arr2.length;
        System.out.println("" + optimalStrategyOfGame(arr2, n));
  
        int arr3[] = { 20, 30, 2, 2, 2, 10 };
        n = arr3.length;
        System.out.println("" + optimalStrategyOfGame(arr3, n));
    }
}
  
// This code is contributed by vt_m

Output:

22
4
42

Exercise
Your thoughts on the strategy when the user wishes to only win instead of winning with the
maximum value. Like above problem, number of coins is even.
Can Greedy approach work quite well and give an optimal solution? Will your answer
change if number of coins is odd? Please see Coin game of two corners
This article is compiled by Aashish Barnwal. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above

Source

https://www.geeksforgeeks.org/optimal-strategy-for-a-game-dp-31/

324
Chapter 32

DP-32 | Word Break Problem

Word Break Problem | DP-32 - GeeksforGeeks


Given an input string and a dictionary of words, find out if the input string can be segmented
into a space-separated sequence of dictionary words. See following examples for more details.
This is a famous Google interview question, also being asked by many other companies now
a days.

Consider the following dictionary


{ i, like, sam, sung, samsung, mobile, ice,
cream, icecream, man, go, mango}

Input: ilike
Output: Yes
The string can be segmented as "i like".

Input: ilikesamsung
Output: Yes
The string can be segmented as "i like samsung"
or "i like sam sung".

Recursive implementation:
The idea is simple, we consider each prefix and search it in dictionary. If the prefix is present
in dictionary, we recur for rest of the string (or suffix). If the recursive call for suffix returns
true, we return true, otherwise we try next prefix. If we have tried all prefixes and none of
them resulted in a solution, we return false.
We strongly recommend to see substrfunction which is used extensively in following imple-
mentations.

// A recursive program to test whether a given 


// string can be segmented into space separated 

325
Chapter 32. DP-32 | Word Break Problem

// words in dictionary
#include <iostream>
using namespace std;
  
/* A utility function to check whether a word is 
  present in dictionary or not. An array of strings 
  is used for dictionary.  Using array of strings for
  dictionary is definitely not a good idea. We have 
  used for simplicity of the program*/
int dictionaryContains(string word)
{
    string dictionary[] = {"mobile","samsung","sam","sung",
                            "man","mango","icecream","and",
                             "go","i","like","ice","cream"};
    int size = sizeof(dictionary)/sizeof(dictionary[0]);
    for (int i = 0; i < size; i++)
        if (dictionary[i].compare(word) == 0)
           return true;
    return false;
}
  
// returns true if string can be segmented into space 
// separated words, otherwise returns false
bool wordBreak(string str)
{
    int size = str.size();
  
    // Base case
    if (size == 0)  return true;
  
    // Try all prefixes of lengths from 1 to size
    for (int i=1; i<=size; i++)
    {
        // The parameter for dictionaryContains is 
        // str.substr(0, i) which is prefix (of input 
        // string) of length 'i'. We first check whether 
        // current prefix is in  dictionary. Then we 
        // recursively check for remaining string
        // str.substr(i, size-i) which is suffix of  
        // length size-i
        if (dictionaryContains( str.substr(0, i) ) &&
            wordBreak( str.substr(i, size-i) ))
            return true;
    }
  
    // If we have tried all prefixes and 
    // none of them worked
    return false;

326
Chapter 32. DP-32 | Word Break Problem

}
  
// Driver program to test above functions
int main()
{
    wordBreak("ilikesamsung")? cout <<"Yes\n": cout << "No\n";
    wordBreak("iiiiiiii")? cout <<"Yes\n": cout << "No\n";
    wordBreak("")? cout <<"Yes\n": cout << "No\n";
    wordBreak("ilikelikeimangoiii")? cout <<"Yes\n": cout << "No\n";
    wordBreak("samsungandmango")? cout <<"Yes\n": cout << "No\n";
    wordBreak("samsungandmangok")? cout <<"Yes\n": cout << "No\n";
    return 0;
}

Output:

Yes
Yes
Yes
Yes
Yes
No

Dynamic Programming
Why Dynamic Programming? The above problem exhibits overlapping sub-problems. For
example, see the following partial recursion tree for string “abcde” in worst case.

// A Dynamic Programming based program to test whether a given string can


// be segmented into space separated words in dictionary

327
Chapter 32. DP-32 | Word Break Problem

#include <iostream>
#include <string.h>
using namespace std;
  
/* A utility function to check whether a word is present in dictionary or not.
  An array of strings is used for dictionary.  Using array of strings for
  dictionary is definitely not a good idea. We have used for simplicity of
  the program*/
int dictionaryContains(string word)
{
    string dictionary[] = {"mobile","samsung","sam","sung","man","mango",
                           "icecream","and","go","i","like","ice","cream"};
    int size = sizeof(dictionary)/sizeof(dictionary[0]);
    for (int i = 0; i < size; i++)
        if (dictionary[i].compare(word) == 0)
           return true;
    return false;
}
  
// Returns true if string can be segmented into space separated
// words, otherwise returns false
bool wordBreak(string str)
{
    int size = str.size();
    if (size == 0)   return true;
  
    // Create the DP table to store results of subroblems. The value wb[i]
    // will be true if str[0..i-1] can be segmented into dictionary words,
    // otherwise false.
    bool wb[size+1];
    memset(wb, 0, sizeof(wb)); // Initialize all values as false.
  
    for (int i=1; i<=size; i++)
    {
        // if wb[i] is false, then check if current prefix can make it true.
        // Current prefix is "str.substr(0, i)"
        if (wb[i] == false && dictionaryContains( str.substr(0, i) ))
            wb[i] = true;
  
        // wb[i] is true, then check for all substrings starting from
        // (i+1)th character and store their results.
        if (wb[i] == true)
        {
            // If we reached the last prefix
            if (i == size)
                return true;
  
            for (int j = i+1; j <= size; j++)

328
Chapter 32. DP-32 | Word Break Problem

            {
                // Update wb[j] if it is false and can be updated
                // Note the parameter passed to dictionaryContains() is
                // substring starting from index 'i' and length 'j-i'
                if (wb[j] == false && dictionaryContains( str.substr(i, j-i) ))
                    wb[j] = true;
  
                // If we reached the last character
                if (j == size && wb[j] == true)
                    return true;
            }
        }
    }
  
    /* Uncomment these lines to print DP table "wb[]"
     for (int i = 1; i <= size; i++)
        cout << " " << wb[i]; */
  
    // If we have tried all prefixes and none of them worked
    return false;
}
  
// Driver program to test above functions
int main()
{
    wordBreak("ilikesamsung")? cout <<"Yes\n": cout << "No\n";
    wordBreak("iiiiiiii")? cout <<"Yes\n": cout << "No\n";
    wordBreak("")? cout <<"Yes\n": cout << "No\n";
    wordBreak("ilikelikeimangoiii")? cout <<"Yes\n": cout << "No\n";
    wordBreak("samsungandmango")? cout <<"Yes\n": cout << "No\n";
    wordBreak("samsungandmangok")? cout <<"Yes\n": cout << "No\n";
    return 0;
}

Output:

Yes
Yes
Yes
Yes
Yes
No

Optimized Dynamic Programming:


In this approach, apart from the dp table, we also maintain all the indexes which have
matched earlier. Then we will check the substrings from those indexes to the current index.
If anyone of that matches then we can divide the string up to that index.

329
Chapter 32. DP-32 | Word Break Problem

In this program, we are using some extra space. However, its time complexity is O(n*s)
where s is the length of the largest string in the dictionary and n is the length of the given
string.

// A Dynamic Programming based program to test


// whether a given string can  be segmented into
// space separated words in dictionary
#include <bits/stdc++.h>
using namespace std;
  
/* A utility function to check whether a word
   is present in dictionary or not. An array of 
   strings is used for dictionary.  Using array
   of strings for dictionary is definitely not 
   a good idea. We have used for simplicity of
   the program*/
int dictionaryContains(string word)
{
    string dictionary[] = { "mobile", "samsung", "sam",
                            "sung", "man", "mango",
                            "icecream", "and", "go",
                            "i", "like", "ice", "cream" };
    int size = sizeof(dictionary) / sizeof(dictionary[0]);
    for (int i = 0; i < size; i++)
        if (dictionary[i].compare(word) == 0)
            return true;
    return false;
}
  
// Returns true if string can be segmented into space
// separated words, otherwise returns false
bool wordBreak(string s)
{
    int n = s.size();
    if (n == 0)
        return true;
  
    // Create the DP table to store results of subroblems.
    // The value dp[i] will be true if str[0..i] can be
    // segmented into dictionary words, otherwise false.
    vector<bool> dp(n + 1, 0); // Initialize all values
    // as false.
  
    // matched_index array represents the indexes for which
    // dp[i] is true. Initially only -1 element is present
    // in this array.
    vector<int> matched_index;
    matched_index.push_back(-1);

330
Chapter 32. DP-32 | Word Break Problem

  
    for (int i = 0; i < n; i++) {
        int msize = matched_index.size();
  
        // Flag value which tells that a substring matches
        // with given words or not.
        int f = 0;
  
        // Check all the substring from the indexes matched
        // earlier. If any of that substring matches than
        // make flag value = 1;
        for (int j = msize - 1; j >= 0; j--) {
  
            // sb is substring starting from matched_index[j]
            // + 1  and of length i - matched_index[j]
            string sb = s.substr(matched_index[j] + 1, i - matched_index[j]);
  
            if (dictionaryContains(sb)) {
                f = 1;
                break;
            }
        }
  
        // If substring matches than do dp[i] = 1 and
        // push that index in matched_index array.
        if (f == 1) {
            dp[i] = 1;
            matched_index.push_back(i);
        }
    }
    return dp[n - 1];
}
  
// Driver code
int main()
{
    wordBreak("ilikesamsung") ? cout << "Yes\n" : cout << "No\n";
    wordBreak("iiiiiiii") ? cout << "Yes\n" : cout << "No\n";
    wordBreak("") ? cout << "Yes\n" : cout << "No\n";
    wordBreak("ilikelikeimangoiii") ? cout << "Yes\n" : cout << "No\n";
    wordBreak("samsungandmango") ? cout << "Yes\n" : cout << "No\n";
    wordBreak("samsungandmangok") ? cout << "Yes\n" : cout << "No\n";
    return 0;
}

Output:

331
Chapter 32. DP-32 | Word Break Problem

Yes
Yes
Yes
Yes
Yes
No

Word Break Problem | (Trie solution)


Exercise:
The above solutions only finds out whether a given string can be segmented or not. Extend
the above Dynamic Programming solution to print all possible partitions of input string.
Examples:

Input: ilikeicecreamandmango
Output:
i like ice cream and man go
i like ice cream and mango
i like icecream and man go
i like icecream and mango

Input: ilikesamsungmobile
Output:
i like sam sung mobile
i like samsung mobile

Refer below post for solution of exercise.


Word Break Problem using Backtracking

Source

https://www.geeksforgeeks.org/word-break-problem-dp-32/

332
Chapter 33

DP-33 | Find if a string is


interleaved of two other strings

Find if a string is interleaved of two other strings | DP-33 - GeeksforGeeks


Given three strings A, B and C. Write a function that checks whether C is an interleaving
of A and B. C is said to be interleaving A and B, if it contains all characters of A and B
and order of all characters in individual strings is preserved.
We have discussed a simple solution of this problem here. The simple solution doesn’t work
if strings A and B have some common characters. For example A = “XXY”, string B
= “XXZ” and string C = “XXZXXXY”. To handle all cases, two possibilities need to be
considered.
a) If first character of C matches with first character of A, we move one character ahead in
A and C and recursively check.
b) If first character of C matches with first character of B, we move one character ahead in
B and C and recursively check.
If any of the above two cases is true, we return true, else false. Following is simple recursive
implementation of this approach (Thanks to Fredericfor suggesting this)

// A simple recursive function to check whether C is an interleaving of A and B


bool isInterleaved(char *A, char *B, char *C)
{
    // Base Case: If all strings are empty
    if (!(*A || *B || *C))
        return true;
  
    // If C is empty and any of the two strings is not empty
    if (*C == '\0')
        return false;
  
    // If any of the above mentioned two possibilities is true,

333
Chapter 33. DP-33 | Find if a string is interleaved of two other strings

    // then return true, otherwise false


    return ( (*C == *A) && isInterleaved(A+1, B, C+1))
           || ((*C == *B) && isInterleaved(A, B+1, C+1));
}

Dynamic Programming
The worst case time complexity of recursive solution is O(2n ). The above recursive solution
certainly has many overlapping subproblems. For example, if wee consider A = “XXX”, B
= “XXX” and C = “XXXXXX” and draw recursion tree, there will be many overlapping
subproblems.
Therefore, like other typical Dynamic Programming problems, we can solve it by creating a
table and store results of subproblems in bottom up manner. Thanks to Abhinav Ramana
for suggesting this method and implementation.

// A Dynamic Programming based program to check whether a string C is


// an interleaving of two other strings A and B.
#include <iostream>
#include <string.h>
using namespace std;
  
// The main function that returns true if C is
// an interleaving of A and B, otherwise false.
bool isInterleaved(char* A, char* B, char* C)
{
    // Find lengths of the two strings
    int M = strlen(A), N = strlen(B);
  
    // Let us create a 2D table to store solutions of
    // subproblems.  C[i][j] will be true if C[0..i+j-1]
    // is an interleaving of A[0..i-1] and B[0..j-1].
    bool IL[M+1][N+1];
  
    memset(IL, 0, sizeof(IL)); // Initialize all values as false.
  
    // C can be an interleaving of A and B only of sum
    // of lengths of A & B is equal to length of C.
    if ((M+N) != strlen(C))
       return false;
  
    // Process all characters of A and B
    for (int i=0; i<=M; ++i)
    {
        for (int j=0; j<=N; ++j)
        {
            // two empty strings have an empty string
            // as interleaving
            if (i==0 && j==0)
                IL[i][j] = true;

334
Chapter 33. DP-33 | Find if a string is interleaved of two other strings

  
            // A is empty
            else if (i==0 && B[j-1]==C[j-1])
                IL[i][j] = IL[i][j-1];
  
            // B is empty
            else if (j==0 && A[i-1]==C[i-1])
                IL[i][j] = IL[i-1][j];
  
            // Current character of C matches with current character of A,
            // but doesn't match with current character of B
            else if(A[i-1]==C[i+j-1] && B[j-1]!=C[i+j-1])
                IL[i][j] = IL[i-1][j];
  
            // Current character of C matches with current character of B,
            // but doesn't match with current character of A
            else if (A[i-1]!=C[i+j-1] && B[j-1]==C[i+j-1])
                IL[i][j] = IL[i][j-1];
  
            // Current character of C matches with that of both A and B
            else if (A[i-1]==C[i+j-1] && B[j-1]==C[i+j-1])
                IL[i][j]=(IL[i-1][j] || IL[i][j-1]) ;
        }
    }
  
    return IL[M][N];
}
  
// A function to run test cases
void test(char *A, char *B, char *C)
{
    if (isInterleaved(A, B, C))
        cout << C <<" is interleaved of " << A <<" and " << B << endl;
    else
        cout << C <<" is not interleaved of " << A <<" and " << B << endl;
}
  
  
// Driver program to test above functions
int main()
{
    test("XXY", "XXZ", "XXZXXXY");
    test("XY" ,"WZ" ,"WZXY");
    test ("XY", "X", "XXY");
    test ("YX", "X", "XXY");
    test ("XXY", "XXZ", "XXXXZY");
    return 0;
}

335
Chapter 33. DP-33 | Find if a string is interleaved of two other strings

Output:

XXZXXXY is not interleaved of XXY and XXZ


WZXY is interleaved of XY and WZ
XXY is interleaved of XY and X
XXY is not interleaved of YX and X
XXXXZY is interleaved of XXY and XXZ

See thisfor more test cases.


Time Complexity: O(MN)
Auxiliary Space: O(MN)

Source

https://www.geeksforgeeks.org/find-if-a-string-is-interleaved-of-two-other-strings-dp-33/

336
Chapter 34

DP-34 | Assembly Line


Scheduling

Assembly Line Scheduling | DP-34 - GeeksforGeeks


A car factory has two assembly lines, each with n stations. A station is denoted by Si,j
where i is either 1 or 2 and indicates the assembly line the station is on, and j indicates
the number of the station. The time taken per station is denoted by ai,j . Each station is
dedicated to some sort of work like engine fitting, body fitting, painting and so on. So, a
car chassis must pass through each of the n stations in order before exiting the factory. The
parallel stations of the two assembly lines perform the same task. After it passes through
station Si,j , it will continue to station Si,j+1 unless it decides to transfer to the other line.
Continuing on the same line incurs no extra cost, but transferring from line i at station j –
1 to station j on the other line takes time ti,j . Each assembly line takes an entry time ei and
exit time xi which may be different for the two lines. Give an algorithm for computing the
minimum time it will take to build a car chassis.
The below figure presents the problem in a clear picture:

The following information can be extracted from the problem statement to make it simpler:

337
Chapter 34. DP-34 | Assembly Line Scheduling

• Two assembly lines, 1 and 2, each with stations from 1 to n.


• A car chassis must pass through all stations from 1 to n in order(in any of the two
assembly lines). i.e. it cannot jump from station i to station j if they are not at one
move distance.
• The car chassis can move one station forward in the same line, or one station diagonally
in the other line. It incurs an extra cost ti, j to move to station j from line i. No cost
is incurred for movement in same line.
• The time taken in station j on line i is ai, j .
• Si, j represents a station j on line i.

Breaking the problem into smaller sub-problems:


We can easily find the ith factorial if (i-1)th factorial is known. Can we apply the similar
funda here?
If the minimum time taken by the chassis to leave station Si, j-1 is known, the minimum
time taken to leave station Si, j can be calculated quickly by combining ai, j and ti, j .
T1(j) indicates the minimum time taken by the car chassis to leave station j on assembly
line 1.
T2(j) indicates the minimum time taken by the car chassis to leave station j on assembly
line 2.
Base cases:
The entry time ei comes into picture only when the car chassis enters the car factory.
Time taken to leave first station in line 1 is given by:
T1(1) = Entry time in Line 1 + Time spent in station S1,1
T1(1) = e1 + a1,1
Similarly, time taken to leave first station in line 2 is given by:
T2(1) = e2 + a2,1
Recursive Relations:
If we look at the problem statement, it quickly boils down to the below observations:
The car chassis at station S1,j can come either from station S1, j-1 or station S2, j-1 .
Case #1: Its previous station is S1, j-1
The minimum time to leave station S1,j is given by:
T1(j) = Minimum time taken to leave station S1, j-1 + Time spent in station S1, j
T1(j) = T1(j-1) + a1, j
Case #2: Its previous station is S2, j-1
The minimum time to leave station S1, j is given by:
T1(j) = Minimum time taken to leave station S2, j-1 + Extra cost incurred to change the
assembly line + Time spent in station S1, j
T1(j) = T2(j-1) + t2, j + a1, j
The minimum time T1(j) is given by the minimum of the two obtained in cases #1 and #2.
T1(j) = min((T1(j-1) + a1, j ), (T2(j-1) + t2, j + a1, j ))
Similarly the minimum time to reach station S2, j is given by:
T2(j) = min((T2(j-1) + a2, j ), (T1(j-1) + t1, j + a2, j ))

338
Chapter 34. DP-34 | Assembly Line Scheduling

The total minimum time taken by the car chassis to come out of the factory is given by:
Tmin = min(Time taken to leave station Si,n + Time taken to exit the car factory)
Tmin = min(T1(n) + x1 , T2(n) + x2 )
Why dynamic programming?
The above recursion exhibits overlapping sub-problems. There are two ways to reach station
S1, j :

1. From station S1, j-1


2. From station S2, j-1

So, to find the minimum time to leave station S1, j the minimum time to leave the previous
two stations must be calculated(as explained in above recursion).
Similarly, there are two ways to reach station S2, j :

1. From station S2, j-1


2. From station S1, j-1

Please note that the minimum times to leave stations S1, j-1 and S2, j-1 have already been
calculated.
So, we need two tables to store the partial results calculated for each station in an assembly
line. The table will be filled in bottom-up fashion.
Note:
In this post, the word “leave” has been used in place of “reach” to avoid the confusion. Since
the car chassis must spend a fixed time in each station, the word leave suits better.
Implementation:
C

// A C program to find minimum possible time by the car chassis to complete


#include <stdio.h>
#define NUM_LINE 2
#define NUM_STATION 4
  
// Utility function to find minimum of two numbers
int min(int a, int b) { return a < b ? a : b; }
  
int carAssembly(int a[][NUM_STATION], int t[][NUM_STATION], int *e, int *x)
{
    int T1[NUM_STATION], T2[NUM_STATION], i;
  
    T1[0] = e[0] + a[0][0]; // time taken to leave first station in line 1
    T2[0] = e[1] + a[1][0]; // time taken to leave first station in line 2
  
    // Fill tables T1[] and T2[] using the above given recursive relations
    for (i = 1; i < NUM_STATION; ++i)

339
Chapter 34. DP-34 | Assembly Line Scheduling

    {
        T1[i] = min(T1[i-1] + a[0][i], T2[i-1] + t[1][i] + a[0][i]);
        T2[i] = min(T2[i-1] + a[1][i], T1[i-1] + t[0][i] + a[1][i]);
    }
  
    // Consider exit times and retutn minimum
    return min(T1[NUM_STATION-1] + x[0], T2[NUM_STATION-1] + x[1]);
}
  
int main()
{
    int a[][NUM_STATION] = {{4, 5, 3, 2},
                {2, 10, 1, 4}};
    int t[][NUM_STATION] = {{0, 7, 4, 5},
                {0, 9, 2, 8}};
    int e[] = {10, 12}, x[] = {18, 7};
  
    printf("%d", carAssembly(a, t, e, x));
  
    return 0;
}

Output:

35

Java

// A java program to find minimum possible


// time by the car chassis to complete
import java.io.*;
  
class GFG 
{
    static int NUM_LINE = 2;
    static int NUM_STATION = 4;
      
    // Utility function to find minimum of two numbers
    static int min(int a, int b) 
    { 
        return a < b ? a : b; 
          
    }
      
    static int carAssembly(int a[][], int t[][], int e[], int x[])
    {
        int T1[]= new int [NUM_STATION];

340
Chapter 34. DP-34 | Assembly Line Scheduling

        int T2[] =new int[NUM_STATION] ;


        int i;
      
        // time taken to leave first station in line 1
        T1[0] = e[0] + a[0][0]; 
          
        // time taken to leave first station in line 2
        T2[0] = e[1] + a[1][0];
      
        // Fill tables T1[] and T2[] using 
        // the above given recursive relations
        for (i = 1; i < NUM_STATION; ++i)
        {
            T1[i] = min(T1[i - 1] + a[0][i], 
                    T2[i - 1] + t[1][i] + a[0][i]);
            T2[i] = min(T2[i - 1] + a[1][i], 
                    T1[i - 1] + t[0][i] + a[1][i]);
        }
      
        // Consider exit times and retutn minimum
        return min(T1[NUM_STATION-1] + x[0], 
                    T2[NUM_STATION-1] + x[1]);
    }
      
      
    // Driver code
    public static void main (String[] args) 
    {
        int a[][] = {{4, 5, 3, 2},
                    {2, 10, 1, 4}};
        int t[][] = {{0, 7, 4, 5},
                    {0, 9, 2, 8}};
        int e[] = {10, 12}, x[] = {18, 7};
      
        System.out.println(carAssembly(a, t, e, x));    
      
    }
}
// This code is contributed by vt_m

Python3

# Python program to find minimum possible 


# time by the car chassis to complete
  
def carAssembly (a, t, e, x):
      
    NUM_STATION = len(a[0])

341
Chapter 34. DP-34 | Assembly Line Scheduling

    T1 = [0 for i in range(NUM_STATION)]


    T2 = [0 for i in range(NUM_STATION)]
      
    T1[0] = e[0] + a[0][0] # time taken to leave
                           # first station in line 1
    T2[0] = e[1] + a[1][0] # time taken to leave
                           # first station in line 2
  
    # Fill tables T1[] and T2[] using
    # above given recursive relations
    for i in range(1, NUM_STATION):
        T1[i] = min(T1[i-1] + a[0][i],
                    T2[i-1] + t[1][i] + a[0][i])
        T2[i] = min(T2[i-1] + a[1][i],
                    T1[i-1] + t[0][i] + a[1][i] )
  
    # consider exit times and return minimum
    return min(T1[NUM_STATION - 1] + x[0],
               T2[NUM_STATION - 1] + x[1])
  
a = [[4, 5, 3, 2],
     [2, 10, 1, 4]]
t = [[0, 7, 4, 5],
     [0, 9, 2, 8]]
e = [10, 12]
x = [18, 7]
  
print(carAssembly(a, t, e, x))
  
# This code is contributed by Soumen Ghosh

C#

// A C# program to find minimum possible


// time by the car chassis to complete
using System;
  
class GFG {
      
    static int NUM_STATION = 4;
      
    // Utility function to find minimum 
    // of two numbers
    static int min(int a, int b) 
    { 
        return a < b ? a : b; 
          
    }

342
Chapter 34. DP-34 | Assembly Line Scheduling

      
    static int carAssembly(int [,]a, int [,]t,
                             int []e, int []x)
    {
        int []T1= new int [NUM_STATION];
        int []T2 =new int[NUM_STATION] ;
        int i;
      
        // time taken to leave first station
        // in line 1
        T1[0] = e[0] + a[0,0]; 
          
        // time taken to leave first station
        // in line 2
        T2[0] = e[1] + a[1,0];
      
        // Fill tables T1[] and T2[] using 
        // the above given recursive relations
        for (i = 1; i < NUM_STATION; ++i)
        {
            T1[i] = min(T1[i - 1] + a[0,i], 
                  T2[i - 1] + t[1,i] + a[0,i]);
            T2[i] = min(T2[i - 1] + a[1,i], 
                  T1[i - 1] + t[0,i] + a[1,i]);
        }
      
        // Consider exit times and retutn
        // minimum
        return min(T1[NUM_STATION-1] + x[0], 
                    T2[NUM_STATION-1] + x[1]);
    }
      
    // Driver code
    public static void Main () 
    {
        int [,]a = { {4, 5, 3, 2},
                     {2, 10, 1, 4} };
                       
        int [,]t = { {0, 7, 4, 5},
                     {0, 9, 2, 8} };
                       
        int []e = {10, 12};
        int []x = {18, 7};
      
        Console.Write(carAssembly(a, t, e, x)); 
      
    }
}

343
Chapter 34. DP-34 | Assembly Line Scheduling

  
// This code is contributed by nitin mittal.

PHP

<?php
// A PHP program to find minimum
// possible time by the car chassis
// to complete
  
$NUM_LINE = 2;
$NUM_STATION = 4;
  
// Utility function to find 
// minimum of two numbers
function carAssembly($a, $t, 
                     $e, $x)
{
    global $NUM_LINE,
           $NUM_STATION;
    $T1 = array(); 
    $T2 = array();
    $i;
  
    $T1[0] = $e[0] + $a[0][0]; // time taken to leave 
                               // first station in line 1
    $T2[0] = $e[1] + $a[1][0]; // time taken to leave 
                               // first station in line 2
  
    // Fill tables T1[] and T2[] 
    // using the above given
    // recursive relations
    for ($i = 1; 
         $i < $NUM_STATION; ++$i)
    {
        $T1[$i] = min($T1[$i - 1] + $a[0][$i], 
                      $T2[$i - 1] + $t[1][$i] + 
                                    $a[0][$i]);
        $T2[$i] = min($T2[$i - 1] + $a[1][$i], 
                      $T1[$i - 1] + $t[0][$i] + 
                                    $a[1][$i]);
    }
  
    // Consider exit times 
    // and return minimum
    return min($T1[$NUM_STATION - 1] + $x[0], 
               $T2[$NUM_STATION - 1] + $x[1]);
}

344
Chapter 34. DP-34 | Assembly Line Scheduling

  
// Driver Code
$a = array(array(4, 5, 3, 2),
           array(2, 10, 1, 4));
$t = array(array(0, 7, 4, 5),
           array(0, 9, 2, 8));
$e = array(10, 12);
$x = array(18, 7);
  
echo carAssembly($a, $t, $e, $x);
  
// This code is contributed
// by anuj_67.
?>

Output:

35

The bold line shows the path covered by the car chassis for given input values.
Exercise:
Extend the above algorithm to print the path covered by the car chassis in the factory.
References:
Introduction to Algorithms 3rd Edition by Clifford Stein, Thomas H. Cormen, Charles E.
Leiserson, Ronald L. Rivest
This article is compiled by Aashish Barnwal. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above
Improved By : nitin mittal, vt_m

Source
https://www.geeksforgeeks.org/assembly-line-scheduling-dp-34/

345
Chapter 35

DP-35 | Longest Arithmetic


Progression

Longest Arithmetic Progression | DP-35 - GeeksforGeeks


Given a set of numbers, find the Length of the Longest Arithmetic Progression (LLAP) in
it.
Examples:

set[] = {1, 7, 10, 15, 27, 29}


output = 3
The longest arithmetic progression is {1, 15, 29}

set[] = {5, 10, 15, 20, 25, 30}


output = 6
The whole set is in AP

For simplicity, we have assumed that the given set is sorted. We can always add a pre-
processing step to first sort the set and then apply the below algorithms.
A simple solution is to one by one consider every pair as first two elements of AP and
check for the remaining elements in sorted set. To consider all pairs as first two elements,
we need to run a O(n^2) nested loop. Inside the nested loops, we need a third loop which
linearly looks for the more elements in Arithmetic Progression (AP). This process takes
O(n3 ) time.
We can solve this problem in O(n2 ) time using Dynamic Programming. To get idea of
the DP solution, let us first discuss solution of following simpler problem.
Given a sorted set, find if there exist three elements in Arithmetic Progression
or not
Please note that, the answer is true if there are 3 or more elements in AP, otherwise false.

346
Chapter 35. DP-35 | Longest Arithmetic Progression

To find the three elements, we first fix an element as middle element and search for other
two (one smaller and one greater). We start from the second element and fix every element
as middle element. For an element set[j] to be middle of AP, there must exist elements ‘set[i]’
and ‘set[k]’ such that set[i] + set[k] = 2*set[j] where 0 <= i < j and j < k <=n-1. How
to efficiently find i and k for a given j? We can find i and k in linear time using following
simple algorithm.

1. Initialize i as j-1 and k as j+1


2. • If set[i] + set[k] is equal to 2*set[j], then we are done.
• If set[i] + set[k] > 2*set[j], then decrement i (do i–).
• Else if set[i] + set[k] < 2*set[j], then increment k (do k++).

Following is C++ implementation of the above algorithm for the simpler problem.

// The function returns true if there exist three elements in AP


// Assumption: set[0..n-1] is sorted. 
// The code strictly implements the algorithm provided in the reference.
bool arithmeticThree(int set[], int n)
{
    // One by fix every element as middle element
    for (int j=1; j<n-1; j++)
    {
        // Initialize i and k for the current j
        int i = j-1, k = j+1;
  
        // Find if there exist i and k that form AP
        // with j as middle element
        while (i >= 0 && k <= n-1)
        {
            if (set[i] + set[k] == 2*set[j])
                return true;
            (set[i] + set[k] < 2*set[j])? k++ : i--;
        }
    }
  
    return false;
}

See thisfor a complete running program.


How to extend the above solution for the original problem?
The above function returns a boolean value. The required output of original problem is
Length of the Longest Arithmetic Progression (LLAP) which is an integer value. If the
given set has two or more elements, then the value of LLAP is at least 2 (Why?).
The idea is to create a 2D table L[n][n]. An entry L[i][j] in this table stores LLAP with set[i]
and set[j] as first two elements of AP and j > i. The last column of the table is always 2
(Why – see the meaning of L[i][j]). Rest of the table is filled from bottom right to top left.

347
Chapter 35. DP-35 | Longest Arithmetic Progression

To fill rest of the table, j (second element in AP) is first fixed. i and k are searched for a
fixed j. If i and k are found such that i, j, k form an AP, then the value of L[i][j] is set as
L[j][k] + 1. Note that the value of L[j][k] must have been filled before as the loop traverses
from right to left columns.
Following is the implementation of the Dynamic Programming algorithm.

C++

// C++ program to find Length of the Longest AP (llap) in a given sorted set.
// The code strictly implements the algorithm provided in the reference.
#include <iostream>
using namespace std;
  
// Returns length of the longest AP subset in a given set
int lenghtOfLongestAP(int set[], int n)
{
    if (n <= 2)  return n;
  
    // Create a table and initialize all values as 2. The value of
    // L[i][j] stores LLAP with set[i] and set[j] as first two
    // elements of AP. Only valid entries are the entries where j>i
    int L[n][n];
    int llap = 2;  // Initialize the result
  
    // Fill entries in last column as 2. There will always be
    // two elements in AP with last number of set as second
    // element in AP
    for (int i = 0; i < n; i++)
        L[i][n-1] = 2;
  
    // Consider every element as second element of AP
    for (int j=n-2; j>=1; j--)
    {
        // Search for i and k for j
        int i = j-1, k = j+1;
        while (i >= 0 && k <= n-1)
        {
           if (set[i] + set[k] < 2*set[j])
               k++;
  
           // Before changing i, set L[i][j] as 2
           else if (set[i] + set[k] > 2*set[j])
           {   L[i][j] = 2, i--;   }
  
           else
           {
               // Found i and k for j, LLAP with i and j as first two

348
Chapter 35. DP-35 | Longest Arithmetic Progression

               // elements is equal to LLAP with j and k as first two


               // elements plus 1. L[j][k] must have been filled
               // before as we run the loop from right side
               L[i][j] = L[j][k] + 1;
  
               // Update overall LLAP, if needed
               llap = max(llap, L[i][j]);
  
               // Change i and k to fill more L[i][j] values for
               // current j
               i--; k++;
           }
        }
  
        // If the loop was stopped due to k becoming more than
        // n-1, set the remaining entties in column j as 2
        while (i >= 0)
        {
            L[i][j] = 2;
            i--;
        }
    }
    return llap;
}
  
/* Drier program to test above function*/
int main()
{
    int set1[] = {1, 7, 10, 13, 14, 19};
    int n1 = sizeof(set1)/sizeof(set1[0]);
    cout <<   lenghtOfLongestAP(set1, n1) << endl;
  
    int set2[] = {1, 7, 10, 15, 27, 29};
    int n2 = sizeof(set2)/sizeof(set2[0]);
    cout <<   lenghtOfLongestAP(set2, n2) << endl;
  
    int set3[] = {2, 4, 6, 8, 10};
    int n3 = sizeof(set3)/sizeof(set3[0]);
    cout <<   lenghtOfLongestAP(set3, n3) << endl;
  
    return 0;
}

Java

// Java program to find Length of the


// Longest AP (llap) in a given sorted set.
// The code strictly implements the 

349
Chapter 35. DP-35 | Longest Arithmetic Progression

// algorithm provided in the reference.


import java.io.*;
  
class GFG 
{
    // Returns length of the longest 
    // AP subset in a given set
    static int lenghtOfLongestAP(int set[], int n)
    {
        if (n <= 2) return n;
      
        // Create a table and initialize all 
        // values as 2. The value ofL[i][j] stores 
        // LLAP with set[i] and set[j] as first two
        // elements of AP. Only valid entries are 
        // the entries where j>i
        int L[][] = new int[n][n];
          
         // Initialize the result
        int llap = 2;
      
        // Fill entries in last column as 2. 
        // There will always be two elements in 
        // AP with last number of set as second
        // element in AP
        for (int i = 0; i < n; i++)
            L[i][n - 1] = 2;
      
        // Consider every element as second element of AP
        for (int j = n - 2; j >= 1; j--)
        {
            // Search for i and k for j
            int i = j -1 , k = j + 1;
            while (i >= 0 && k <= n - 1)
            {
            if (set[i] + set[k] < 2 * set[j])
                k++;
      
            // Before changing i, set L[i][j] as 2
            else if (set[i] + set[k] > 2 * set[j])
            { 
                L[i][j] = 2; i--; 
                  
            }
      
            else
            {
                // Found i and k for j, LLAP with i and j as first two

350
Chapter 35. DP-35 | Longest Arithmetic Progression

                // elements is equal to LLAP with j and k as first two


                // elements plus 1. L[j][k] must have been filled
                // before as we run the loop from right side
                L[i][j] = L[j][k] + 1;
      
                // Update overall LLAP, if needed
                llap = Math.max(llap, L[i][j]);
      
                // Change i and k to fill 
                // more L[i][j] values for current j
                i--; k++;
            }
            }
      
            // If the loop was stopped due
            // to k becoming more than
            // n-1, set the remaining 
            // entties in column j as 2
            while (i >= 0)
            {
                L[i][j] = 2;
                i--;
            }
        }
        return llap;
    }
      
    // Driver program 
    public static void main (String[] args) 
    {
        int set1[] = {1, 7, 10, 13, 14, 19};
        int n1 = set1.length;
        System.out.println ( lenghtOfLongestAP(set1, n1));
      
        int set2[] = {1, 7, 10, 15, 27, 29};
        int n2 = set2.length;
        System.out.println(lenghtOfLongestAP(set2, n2));
      
        int set3[] = {2, 4, 6, 8, 10};
        int n3 = set3.length;
        System.out.println(lenghtOfLongestAP(set3, n3)) ;
      
      
    }
}
  
// This code is contributed by vt_m

351
Chapter 35. DP-35 | Longest Arithmetic Progression

Output:

4
3
5

Time Complexity: O(n2 )


Auxiliary Space: O(n2 )
References:
http://www.cs.uiuc.edu/~jeffe/pubs/pdf/arith.pdf

Source

https://www.geeksforgeeks.org/longest-arithmetic-progression-dp-35/

352
Chapter 36

DP-36 | Maximum Product


Cutting

Maximum Product Cutting | DP-36 - GeeksforGeeks


Given a rope of length n meters, cut the rope in different parts of integer lengths in a way
that maximizes product of lengths of all parts. You must make at least one cut. Assume
that the length of rope is more than 2 meters.
Examples:

Input: n = 2
Output: 1 (Maximum obtainable product is 1*1)

Input: n = 3
Output: 2 (Maximum obtainable product is 1*2)

Input: n = 4
Output: 4 (Maximum obtainable product is 2*2)

Input: n = 5
Output: 6 (Maximum obtainable product is 2*3)

Input: n = 10
Output: 36 (Maximum obtainable product is 3*3*4)

1) Optimal Substructure:
This problem is similar to Rod Cutting Problem. We can get the maximum product 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 maxProd(n) be the maximum product for a rope of length n. maxProd(n) can be
written as following.

353
Chapter 36. DP-36 | Maximum Product Cutting

maxProd(n) = max(i*(n-i), maxProdRec(n-i)*i) for all i in {1, 2, 3 .. n}


2) Overlapping Subproblems
Following is simple recursive implementation of the problem. The implementation simply
follows the recursive structure mentioned above.

C++

// A Naive Recursive method to find maxium product


#include <iostream>
using namespace std;
  
// Utility function to get the maximum of two and three integers
int max(int a, int b) { return (a > b)? a : b;}
int max(int a, int b, int c) { return max(a, max(b, c));}
  
// The main function that returns maximum product obtainable
// from a rope of length n
int maxProd(int n)
{
    // Base cases
    if (n == 0 || n == 1) return 0;
  
    // Make a cut at different places and take the maximum of all
    int max_val = 0;
    for (int i = 1; i < n; i++)
      max_val = max(max_val, i*(n-i), maxProd(n-i)*i);
  
    // Return the maximum of all values
    return max_val;
}
  
/* Driver program to test above functions */
int main()
{
    cout << "Maximum Product is " << maxProd(10);
    return 0;
}

Java

// Java program to find maxium product


import java.io.*;
  
class GFG {
  
    // The main function that returns 

354
Chapter 36. DP-36 | Maximum Product Cutting

    // maximum product obtainable from 


    // a rope of length n
    static int maxProd(int n)
    {
        // Base cases
        if (n == 0 || n == 1) return 0;
  
        // Make a cut at different places
        // and take the maximum of all
        int max_val = 0;
        for (int i = 1; i < n; i++)
        max_val = Math.max(max_val,
                  Math.max(i * (n - i),
                   maxProd(n - i) * i));
  
        // Return the maximum of all values
        return max_val;
    }   
  
    /* Driver program to test above functions */
    public static void main(String[] args)
    {
        System.out.println("Maximum Product is " 
                            + maxProd(10));
    }
}
// This code is contributed by Prerna Saini

Python3

# The main function that returns maximum


# product obtainable from a rope of length n
  
def maxProd(n):
      
    # Base cases
    if (n == 0 or n == 1):
        return 0
   
    # Make a cut at different places
    # and take the maximum of all
    max_val = 0
    for i in range(1, n - 1):
        max_val = max(max_val, max(i * (n - i), maxProd(n - i) * i))
   
    #Return the maximum of all values
    return max_val;
  

355
Chapter 36. DP-36 | Maximum Product Cutting

   
# Driver program to test above functions 
print("Maximum Product is ", maxProd(10));
      
# This cide is contributed
# by Sumit Sudhakar

C#

// C# program to find maxium product


using System;
  
class GFG {
      
    // The main function that returns  
    // the max possible product 
    static int maxProd(int n)
    {
  
        // n equals to 2 or 3 must 
        // be handled explicitly
        if (n == 2 || n == 3)
            return (n - 1);
  
        // Keep removing parts of size 
        // 3 while n is greater than 4
        int res = 1;
        while (n > 4) {
            n -= 3;
  
            // Keep multiplying 3 to res
            res *= 3;
        }
  
        // The last part multiplied 
        // by previous parts
        return (n * res);
    }
  
    // Driver code
    public static void Main()
    {
        Console.WriteLine("Maximum Product is "
                                + maxProd(10));
    }
}
  
// This code is contributed by Sam007

356
Chapter 36. DP-36 | Maximum Product Cutting

Output:

Maximum Product is 36

Considering the above implementation, following is recursion tree for a Rope of length 5.

In the above partial recursion tree, mP(3) is being solved twice. We can see that there
are many subproblems which are solved again and again. Since same suproblems are called
again, this problem has Overlapping Subprolems property. So the problem has both prop-
erties (see thisand this) of a dynamic programming problem. Like other typical Dynamic
Programming(DP) problems, recomputations of same subproblems can be avoided by con-
structing a temporary array val[] in bottom up manner.

// A Dynamic Programming solution for Max Product Problem


int maxProd(int n)
{
   int val[n+1];
   val[0] = val[1] = 0;
   
   // Build the table val[] in bottom up manner and return
   // the last entry from the table
   for (int i = 1; i <= n; i++)
   {
      int max_val = 0;
      for (int j = 1; j <= i/2; j++)
         max_val = max(max_val, (i-j)*j, j*val[i-j]);

357
Chapter 36. DP-36 | Maximum Product Cutting

      val[i] = max_val;
   }
   return val[n];
}

Time Complexity of the Dynamic Programming solution is O(n^2) and it requires O(n)
extra space.
A Tricky Solution:
If we see some examples of this problems, we can easily observe following pattern.
The maximum product can be obtained be repeatedly cutting parts of size 3 while size
is greater than 4, keeping the last part as size of 2 or 3 or 4. For example, n = 10, the
maximum product is obtained by 3, 3, 4. For n = 11, the maximum product is obtained
by 3, 3, 3, 2. Following is the implementation of this approach.

C++

#include <iostream>
using namespace std;
  
/* The main function that teturns the max possible product */
int maxProd(int n)
{
   // n equals to 2 or 3 must be handled explicitly
   if (n == 2 || n == 3) return (n-1);
  
   // Keep removing parts of size 3 while n is greater than 4
   int res = 1;
   while (n > 4)
   {
       n -= 3;
       res *= 3; // Keep multiplying 3 to res
   }
   return (n * res); // The last part multiplied by previous parts
}
  
/* Driver program to test above functions */
int main()
{
    cout << "Maximum Product is " << maxProd(10);
    return 0;
}

Java

// Java program to find maximum product


import java.io.*;

358
Chapter 36. DP-36 | Maximum Product Cutting

  
class GFG {
  
    /* The main function that returns the 
    max possible product */
    static int maxProd(int n)
    {
      
    // n equals to 2 or 3 must be handled
    // explicitly
    if (n == 2 || n == 3) return (n-1);
  
    // Keep removing parts of size 3 
    // while n is greater than 4
    int res = 1;
    while (n > 4)
    {
        n -= 3;
          
        // Keep multiplying 3 to res
        res *= 3; 
    }
      
    // The last part multiplied by 
    // previous parts
    return (n * res); 
    }
  
    /* Driver program to test above functions */
    public static void main(String[] args)
    {
        System.out.println("Maximum Product is "
                            + maxProd(10));
    }   
}
// This code is contributed by Prerna Saini

Python3

# The main function that returns the 


# max possible product
  
def maxProd(n):
      
    # n equals to 2 or 3 must
    # be handled explicitly
    if (n == 2 or n == 3):
        return (n - 1)

359
Chapter 36. DP-36 | Maximum Product Cutting

   
    # Keep removing parts of size 3 
    # while n is greater than 4
    res = 1
    while (n > 4):
        n -= 3;
           
        # Keep multiplying 3 to res
        res *= 3; 
      
    # The last part multiplied 
    # by previous parts
    return (n * res)
  
# Driver program to test above functions 
print("Maximum Product is ", maxProd(10));
      
# This code is contributed 
# by Sumit Sudhakar

C#

// C# program to find maxium product


using System;
  
class GFG {
  
    // The main function that returns
    // maximum product obtainable from
    // a rope of length n
    static int maxProd(int n)
    {
        // Base cases
        if (n == 0 || n == 1)
            return 0;
  
        // Make a cut at different places
        // and take the maximum of all
        int max_val = 0;
        for (int i = 1; i < n; i++)
            max_val = Math.Max(max_val,
                    Math.Max(i * (n - i),
                     maxProd(n - i) * i));
  
        // Return the maximum of all values
        return max_val;
    }
  

360
Chapter 36. DP-36 | Maximum Product Cutting

    // Driver code


    public static void Main()
     {
        Console.WriteLine("Maximum Product is "
                                + maxProd(10));
     }
}
  
// This code is contributed by Sam007

PHP

<?php
  
/* The main function that returns 
   the max possible product */
function maxProd($n)
{
      
// n equals to 2 or 3 must
// be handled explicitly
if ($n == 2 || $n == 3) 
    return ($n - 1);
  
// Keep removing parts of size 
// 3 while n is greater than 4
$res = 1;
while ($n > 4)
{
    $n = $n - 3;
      
    // Keep multiplying 3 to res
    $res = $res * 3; 
}
  
// The last part multiplied
// by previous parts
return ($n * $res); 
}
  
// Driver code
echo ("Maximum Product is ");
echo(maxProd(10));
  
// This code is contributed 
// by Shivi_Aggarwal 
?>

361
Chapter 36. DP-36 | Maximum Product Cutting

Output:

Maximum Product is 36

Improved By : Shivi_Aggarwal

Source

https://www.geeksforgeeks.org/maximum-product-cutting-dp-36/

362
Chapter 37

DP-37 | Boolean
Parenthesization Problem

Boolean Parenthesization Problem | DP-37 - GeeksforGeeks


Given a boolean expression with following symbols.

Symbols
'T' ---> true
'F' ---> false

And following operators filled between symbols

Operators
& ---> boolean AND
| ---> boolean OR
^ ---> boolean XOR

Count the number of ways we can parenthesize the expression so that the value of expression
evaluates to true.
Let the input be in form of two arrays one contains the symbols (T and F) in order and
other contains operators (&, | and ^}
Examples:

Input: symbol[] = {T, F, T}


operator[] = {^, &}
Output: 2

363
Chapter 37. DP-37 | Boolean Parenthesization Problem

The given expression is "T ^ F & T", it evaluates true


in two ways "((T ^ F) & T)" and "(T ^ (F & T))"

Input: symbol[] = {T, F, F}


operator[] = {^, |}
Output: 2
The given expression is "T ^ F | F", it evaluates true
in two ways "( (T ^ F) | F )" and "( T ^ (F | F) )".

Input: symbol[] = {T, T, F, T}


operator[] = {|, &, ^}
Output: 4
The given expression is "T | T & F ^ T", it evaluates true
in 4 ways ((T|T)&(F^T)), (T|(T&(F^T))), (((T|T)&F)^T)
and (T|((T&F)^T)).

Solution:
Let T(i, j) represents the number of ways to parenthesize the symbols between i and j
(both inclusive) such that the subexpression between i and j evaluates to true.

Let F(i, j) represents the number of ways to parenthesize the symbols between i and j (both
inclusive) such that the subexpression between i and j evaluates to false.

Base Cases:

T(i, i) = 1 if symbol[i] = 'T'


T(i, i) = 0 if symbol[i] = 'F'

F(i, i) = 1 if symbol[i] = 'F'


F(i, i) = 0 if symbol[i] = 'T'

364
Chapter 37. DP-37 | Boolean Parenthesization Problem

If we draw recursion tree of above recursive solution, we can observe that it many overlapping
subproblems. Like other dynamic programming problems, it can be solved by filling a table
in bottom up manner. Following is C++ implementation of dynamic programming solution.

#include<iostream>
#include<cstring>
using namespace std;
  
// Returns count of all possible parenthesizations that lead to
// result true for a boolean expression with symbols like true
// and false and operators like &, | and ^ filled between symbols
int countParenth(char symb[], char oper[], int n)
{
    int F[n][n], T[n][n];
  
    // Fill diaginal entries first
    // All diagonal entries in T[i][i] are 1 if symbol[i]
    // is T (true).  Similarly, all F[i][i] entries are 1 if
    // symbol[i] is F (False)
    for (int i = 0; i < n; i++)
    {
        F[i][i] = (symb[i] == 'F')? 1: 0;
        T[i][i] = (symb[i] == 'T')? 1: 0;
    }
  
    // Now fill T[i][i+1], T[i][i+2], T[i][i+3]... in order
    // And F[i][i+1], F[i][i+2], F[i][i+3]... in order
    for (int gap=1; gap<n; ++gap)
    {
        for (int i=0, j=gap; j<n; ++i, ++j)
        {
            T[i][j] = F[i][j] = 0;
            for (int g=0; g<gap; g++)
            {
                // Find place of parenthesization using current value
                // of gap
                int k = i + g;
  
                // Store Total[i][k] and Total[k+1][j]
                int tik = T[i][k] + F[i][k];
                int tkj = T[k+1][j] + F[k+1][j];
  
                // Follow the recursive formulas according to the current
                // operator
                if (oper[k] == '&')
                {
                    T[i][j] += T[i][k]*T[k+1][j];
                    F[i][j] += (tik*tkj - T[i][k]*T[k+1][j]);

365
Chapter 37. DP-37 | Boolean Parenthesization Problem

                }
                if (oper[k] == '|')
                {
                    F[i][j] += F[i][k]*F[k+1][j];
                    T[i][j] += (tik*tkj - F[i][k]*F[k+1][j]);
                }
                if (oper[k] == '^')
                {
                    T[i][j] += F[i][k]*T[k+1][j] + T[i][k]*F[k+1][j];
                    F[i][j] += T[i][k]*T[k+1][j] + F[i][k]*F[k+1][j];
                }
            }
        }
    }
    return T[0][n-1];
}
  
// Driver program to test above function
int main()
{
    char symbols[] = "TTFT";
    char operators[] = "|&^";
    int n = strlen(symbols);
  
    // There are 4 ways
    // ((T|T)&(F^T)), (T|(T&(F^T))), (((T|T)&F)^T) and (T|((T&F)^T))
    cout << countParenth(symbols, operators, n);
    return 0;
}

Output:

Time Complexity: O(n3 )


Auxiliary Space: O(n2 )
References:
http://people.cs.clemson.edu/~bcdean/dp_practice/dp_9.swf

Source

https://www.geeksforgeeks.org/boolean-parenthesization-problem-dp-37/

366
Chapter 38

A Space Optimized DP solution


for 0-1 Knapsack Problem

A Space Optimized DP solution for 0-1 Knapsack Problem - GeeksforGeeks


Given weights and values of n items, put these items in a knapsack of capacity W to get the
maximum total value in the knapsack. In other words, given two integer arrays val[0..n-1]
and wt[0..n-1] which represent values and weights associated with n items respectively. Also
given an integer W which represents knapsack capacity, find out the maximum value subset
of val[] such that sum of the weights of this subset is smaller than or equal to W. We cannot
break an item, either pick the complete item, or don’t pick it (0-1 property).
Here W <= 2000000 and n <= 500
Examples:

Input : W = 10, n = 3
val[] = {7, 8, 4}
wt[] = {3, 8, 6}
Output: 11
We get maximum value by picking items of 3 KG and 6 KG.

We have discussed a Dynamic Programming based solution here. In the previous solution, we
used a n * W matrix. We can reduce the used extra space. The idea behind the optimization
is, to compute mat[i][j], we only need solution of previous row. In 0-1 Knapsack Problem if
we are currently on mat[i][j] and we include ith element then we move j-wt[i] steps back in
previous row and if we exclude the current element we move on jth column in previous row.
So here we can observe that at a time we are working only with 2 consecutive rows.
In below solution, we create a matrix of size 2*W. If n is odd, then final answer will be at
mat[0][W] and if n is even then final answer will be at mat[1][W] because index starts from
0.

367
Chapter 38. A Space Optimized DP solution for 0-1 Knapsack Problem

// C++ program of a space optimized DP solution for


// 0-1 knapsack problem.
#include<bits/stdc++.h>
using namespace std;
  
// val[] is for storing maximum profit for each weight
// wt[] is for storing weights
// n number of item
// W maximum capacity of bag
// mat[2][W+1] to store final result
int KnapSack(int val[], int wt[], int n, int W)
{
    // matrix to store final result
    int mat[2][W+1];
    memset(mat, 0, sizeof(mat));
  
    // iterate through all items
    int i = 0;
    while (i < n) // one by one traverse each element
    {
        int j = 0; // traverse all wieghts j <= W
  
        // if i is odd that mean till now we have odd
        // number of elements so we store result in 1th
        // indexed row
        if (i%2!=0)
        {
            while (++j <= W) // check for each value
            {
                if (wt[i] <= j) // include element
                    mat[1][j] = max(val[i] + mat[0][j-wt[i]],
                                    mat[0][j] );
                else           // exclude element
                    mat[1][j] = mat[0][j];
            }
  
        }
  
        // if i is even that mean till now we have even number
        // of elements so we store result in 0th indexed row
        else
        {
            while(++j <= W)
            {
                if (wt[i] <= j)
                    mat[0][j] = max(val[i] + mat[1][j-wt[i]],
                                     mat[1][j]);
                else

368
Chapter 38. A Space Optimized DP solution for 0-1 Knapsack Problem

                    mat[0][j] = mat[1][j];
            }
        }
        i++;
    }
  
    // Return mat[0][W] if n is odd, else mat[1][W]
    return (n%2 != 0)? mat[0][W] : mat[1][W];
}
  
// Driver program to test the cases
int main()
{
    int val[] = {7, 8, 4}, wt[] = {3, 8, 6}, W = 10, n = 3;
    cout << KnapSack(val, wt, n, W) << endl;
    return 0;
}

Output:

11

Time Complexity : O(n * W)


Auxiliary Space : O(W)
Here is an optimized code contributed by Gaurav Mamgain

// C++ program of a space optimized DP solution for


// 0-1 knapsack problem.
#include<bits/stdc++.h>
using namespace std;
  
// val[] is for storing maximum profit for each weight
// wt[] is for storing weights
// n number of item
// W maximum capacity of bag
// dp[W+1] to store final result
int KnapSack(int val[], int wt[], int n, int W)
{
    // array to store final result
    //dp[i] stores the profit with KnapSack capacity "i"
    int dp[W+1];
      
    //initially profit with 0 to W KnapSack capacity is 0
    memset(dp, 0, sizeof(dp));
  
    // iterate through all items

369
Chapter 38. A Space Optimized DP solution for 0-1 Knapsack Problem

    for(int i=0; i < n; i++) 


        //traverse dp array from right to left
        for(int j=W; j>=wt[i]; j--)
            dp[j] = max(dp[j] , val[i] + dp[j-wt[i]]);
    /*above line finds out maximum of  dp[j](excluding ith element value)
      and val[i] + dp[j-wt[i]] (including ith element value and the
      profit with "KnapSack capacity - ith element weight") */  
    return dp[W];
}
  
// Driver program to test the cases
int main()
{
    int val[] = {7, 8, 4}, wt[] = {3, 8, 6}, W = 10, n = 3;
    cout << KnapSack(val, wt, n, W) << endl;
    return 0;
}
  
// This code is contributed by Gaurav Mamgain

Output:

11

This article is contributed by Shashank Mishra ( Gullu ). This article is reviwed by


team geeksforgeeks.
Please write comments if you find anything incorrect, or you want to share more information
about the topic discussed above.

Source

https://www.geeksforgeeks.org/space-optimized-dp-solution-0-1-knapsack-problem/

370
Chapter 39

A Space Optimized Solution of


LCS

A Space Optimized Solution of LCS - GeeksforGeeks


Given two strings, find the length of longest subsequence present in both of them.
Examples:
LCS for input Sequences “ABCDGH” and “AEDFHR” is “ADH” of length 3.
LCS for input Sequences “AGGTAB” and “GXTXAYB” is “GTAB” of length 4.
We have discussed typical dynamic programming based solution for LCS. We can optimize
space used by lcs problem. We know recurrence relation of LCS problem is

/* Returns length of LCS for X[0..m-1], Y[0..n-1] */


int lcs(string &X, string &Y)
{
    int m = X.length(), n = Y.length();
    int L[m+1][n+1];
  
    /* Following steps build L[m+1][n+1] in bottom up
       fashion. Note that L[i][j] contains length of
       LCS of X[0..i-1] and Y[0..j-1] */
    for (int i=0; i<=m; i++)
    {
        for (int j=0; j<=n; j++)
        {
            if (i == 0 || j == 0)
                L[i][j] = 0;
  
            else if (X[i-1] == Y[j-1])
                L[i][j] = L[i-1][j-1] + 1;
  
            else

371
Chapter 39. A Space Optimized Solution of LCS

                L[i][j] = max(L[i-1][j], L[i][j-1]);


        }
    }
  
    /* L[m][n] contains length of LCS for X[0..n-1] and
       Y[0..m-1] */
    return L[m][n];
}

How to find length of LCS in O(n) auxiliary space?

We strongly recommend that you click here and practice it, before moving on
to the solution.
One important observation in above simple implementation is, in each iteration of outer
loop we only, need values from all columns of previous row. So there is no need of
storing all rows in our DP matrix, we can just store two rows at a time and use them, in that
way used space will reduce from L[m+1][n+1] to L[2][n+1]. Below is the implementation
of above idea.

C++

// Space optimized C++ implementation


// of LCS problem 
#include<bits/stdc++.h>
using namespace std;
  
// Returns length of LCS 
// for X[0..m-1], Y[0..n-1] 
int lcs(string &X, string &Y)
{
      
    // Find lengths of two strings
    int m = X.length(), n = Y.length();
  
    int L[2][n + 1];
  
    // Binary index, used to
    // index current row and
    // previous row.
    bool bi;
  
    for (int i = 0; i <= m; i++)
    {
          
        // Compute current 
        // binary index

372
Chapter 39. A Space Optimized Solution of LCS

        bi = i & 1;
  
        for (int j = 0; j <= n; j++)
        {
            if (i == 0 || j == 0)
                L[bi][j] = 0;
  
            else if (X[i-1] == Y[j-1])
                 L[bi][j] = L[1 - bi][j - 1] + 1;
  
            else
                L[bi][j] = max(L[1 - bi][j], 
                               L[bi][j - 1]);
        }
    }
  
    // Last filled entry contains
    // length of LCS
    // for X[0..n-1] and Y[0..m-1] 
    return L[bi][n];
}
  
// Driver code
int main()
{
    string X = "AGGTAB";
    string Y = "GXTXAYB";
  
    printf("Length of LCS is %d\n", lcs(X, Y));
  
    return 0;
}

Java

// Java Code for A Space Optimized 


// Solution of LCS
  
class GFG {
      
    // Returns length of LCS 
    // for X[0..m - 1],
    // Y[0..n - 1] 
    public static int lcs(String X, 
                          String Y)
    {
          
        // Find lengths of two strings

373
Chapter 39. A Space Optimized Solution of LCS

        int m = X.length(), n = Y.length();


      
        int L[][] = new int[2][n+1];
      
        // Binary index, used to index 
        // current row and previous row.
        int bi=0;
      
        for (int i = 0; i <= m; i++)
        {
              
            // Compute current binary index
            bi = i & 1;
      
            for (int j = 0; j <= n; j++)
            {
                if (i == 0 || j == 0)
                    L[bi][j] = 0;
      
                else if (X.charAt(i - 1) == 
                         Y.charAt(j - 1))
                    L[bi][j] = L[1 - bi][j - 1] + 1;
      
                else
                    L[bi][j] = Math.max(L[1 - bi][j], 
                                        L[bi][j - 1]);
            }
        }
      
        // Last filled entry contains length of 
        // LCS for X[0..n-1] and Y[0..m-1] 
        return L[bi][n];
    }
      
      
    // Driver Code 
    public static void main(String[] args) 
    {
        String X = "AGGTAB";
        String Y = "GXTXAYB";
      
        System.out.println("Length of LCS is " +
                                    lcs(X, Y));
    }
}
  
// This code is contributed by Arnav Kr. Mandal.

374
Chapter 39. A Space Optimized Solution of LCS

Python3

# Space optimized Python


# implementation of LCS problem
  
# Returns length of LCS for 
# X[0..m-1], Y[0..n-1]
def lcs(X, Y):
      
    # Find lengths of two strings
    m = len(X)
    n = len(Y)
  
    L = [[0 for i in range(n+1)] for j in range(2)]
  
    # Binary index, used to index current row and
    # previous row.
    bi = bool
      
    for i in range(m):
        # Compute current binary index
        bi = i&1
  
        for j in range(n+1):
            if (i == 0 or j == 0):
                L[bi][j] = 0
  
            elif (X[i] == Y[j - 1]):
                L[bi][j] = L[1 - bi][j - 1] + 1
  
            else:
                L[bi][j] = max(L[1 - bi][j], 
                               L[bi][j - 1])
  
    # Last filled entry contains length of LCS
    # for X[0..n-1] and Y[0..m-1]
    return L[bi][n]
  
# Driver Code
X = "AGGTAB"
Y = "GXTXAYB"
  
print("Length of LCS is", lcs(X, Y))
  
# This code is contributed by Soumen Ghosh.

C#

375
Chapter 39. A Space Optimized Solution of LCS

// C# Code for A Space 


// Optimized Solution of LCS
using System;
  
class GFG
{
      
    // Returns length of LCS 
    // for X[0..m - 1],
    // Y[0..n - 1] 
    public static int lcs(string X,
                          string Y)
    {
          
        // Find lengths of
        // two strings
        int m = X.Length, n = Y.Length;
      
        int [,]L = new int[2, n + 1];
      
        // Binary index, used to 
        // index current row and 
        // previous row.
        int bi = 0;
      
        for (int i = 0; i <= m; i++)
        {
              
            // Compute current
            // binary index
            bi = i & 1;
      
            for (int j = 0; j <= n; j++)
            {
                if (i == 0 || j == 0)
                    L[bi, j] = 0;
       
                else if (X[i - 1] == Y[j - 1])
                    L[bi, j] = L[1 - bi, 
                                 j - 1] + 1;
      
                else
                    L[bi, j] = Math.Max(L[1 - bi, j], 
                                        L[bi, j - 1]);
            }
        }
      
        // Last filled entry contains

376
Chapter 39. A Space Optimized Solution of LCS

        // length of LCS for X[0..n-1]


        // and Y[0..m-1] 
        return L[bi, n];
    }
      
    // Driver Code 
    public static void Main() 
    {
        string X = "AGGTAB";
        string Y = "GXTXAYB";
      
        Console.Write("Length of LCS is " +
                                lcs(X, Y));
    }
}
  
// This code is contributed 
// by shiv_bhakt.

Output:

Length of LCS is 4

Time Complexity : O(m*n)


Auxiliary Space : O(n)
This article is contributed Shivam Mittal. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above
Improved By : shiv_bhakt

Source

https://www.geeksforgeeks.org/space-optimized-solution-lcs/

377
Chapter 40

All ways to add parenthesis for


evaluation

All ways to add parenthesis for evaluation - GeeksforGeeks


Given a string that represents an expression constituting numbers and binary operator +,
– and * only. We need to parenthesize the expression in all possible way and return all
evaluated values.

Input : expr = “3-2-1”


Output : {0, 2}
((3-2)-1) = 0
(3-(2-1)) = 2

Input : expr = "5*4-3*2"


Output : {-10, 10, 14, 10, 34}
(5*(4-(3*2))) = -10
(5*((4-3)*2)) = 10
((5*4)-(3*2)) = 14
((5*(4-3))*2) = 10
(((5*4)-3)*2) = 34

We can solve this problem by parenthesizing all possible valid substring of the expression
and then evaluating them, but as we can see that it will involve solving lots of repeating
subproblem, to save ourselves we can follow a dynamic programming approach.
We store the result for each substring in a map and if string in recursion is already solved,
we return result from map instead of solving that again.
Below code runs a loop in the string and if at any instant, character is operator then we
divide the input from there, recursively solve each part and then combine the result in all
possible ways.
See the use of c_str() function, this function converts the C++ string into C char array,

378
Chapter 40. All ways to add parenthesis for evaluation

this function is used in below code because atoi() function expects a character array as an
argument not the string. It converts character array to number.

//  C++ program to output all possible values of


// an expression by parenthesizing it.
#include <bits/stdc++.h>
using namespace std;
  
//  method checks, character is operator or not
bool isOperator(char op)
{
    return (op == '+' || op == '-' || op == '*');
}
  
//  Utility recursive method to get all possible
// result of input string
vector<int> possibleResultUtil(string input,
            map< string, vector<int> > memo)
{
    //  If already calculated, then return from memo
    if (memo.find(input) != memo.end())
        return memo[input];
  
    vector<int> res;
    for (int i = 0; i < input.size(); i++)
    {
        if (isOperator(input[i]))
        {
            // If character is operator then split and
            // calculate recursively
            vector<int> resPre =
              possibleResultUtil(input.substr(0, i), memo);
            vector<int> resSuf =
              possibleResultUtil(input.substr(i + 1), memo);
  
            //  Combine all possible combination
            for (int j = 0; j < resPre.size(); j++)
            {
                for (int k = 0; k < resSuf.size(); k++)
                {
                    if (input[i] == '+')
                        res.push_back(resPre[j] + resSuf[k]);
                    else if (input[i] == '-')
                        res.push_back(resPre[j] - resSuf[k]);
                    else if (input[i] == '*')
                        res.push_back(resPre[j] * resSuf[k]);
                }
            }

379
Chapter 40. All ways to add parenthesis for evaluation

        }
    }
  
    // if input contains only number then save that 
    // into res vector
    if (res.size() == 0)
        res.push_back(atoi(input.c_str()));
  
    // Store in memo so that input string is not 
    // processed repeatedly
    memo[input] = res;
    return res;
}
  
//  method to return all possible output 
// from input expression
vector<int> possibleResult(string input)
{
    map< string, vector<int> > memo;
    return possibleResultUtil(input, memo);
}
  
//  Driver code to test above methods
int main()
{
    string input = "5*4-3*2";
    vector<int> res = possibleResult(input);
  
    for (int i = 0; i < res.size(); i++)
        cout << res[i] << " ";
    return 0;
}

Output:

-10 10 14 10 34

Source

https://www.geeksforgeeks.org/all-ways-to-add-parenthesis-for-evaluation/

380
Chapter 41

Alternate Fibonacci Numbers

Alternate Fibonacci Numbers - GeeksforGeeks


Give a number N, print alternate fibonacci numbers till n-th Fibonacci.
Examples:

Input : N = 7
Output : 0 1 3 8

Input : N = 15
Output : 0 1 3 8 21 55 144 377

Read method 2 in the following article : fibonacci number


Approach:Using dynamic programming approach. Keep storing the previously calcu-
lated fibonacci numbers and using the previous two to store the next fibonacci number.

Source

https://www.geeksforgeeks.org/alternate-fibonacci-numbers/
C++

// Alternate Fibonacci Series using Dynamic Programming


#include <bits/stdc++.h>
using namespace std;
  
void alternateFib(int n)
{
    if (n < 0)
      return;

381
Chapter 41. Alternate Fibonacci Numbers

  
    /* 0th and 1st number of the series are 0 and 1*/
    int f1 = 0;
    int f2 = 1;
  
    cout << f1 << " ";
    for (int i = 2; i <= n; i++) {
         int f3 = f2 + f1;
            
         if (i % 2 == 0)
            cout << f3 << " ";
  
         f1 = f2;
         f2 = f3;
    }
}
  
int main()
{
    int N = 15;
    alternateFib(N);
    return 0;
}

Java

// Alternate Fibonacci Series 


// using Dynamic Programming
import java.io.*;
  
class GFG 
{
static void alternateFib(int n)
{
    if (n < 0)
    return;
  
    /* 0th and 1st number of the
       series are 0 and 1*/
    int f1 = 0;
    int f2 = 1;
  
    System.out.print(f1 + " ");
    for (int i = 2; i <= n; i++) 
    {
        int f3 = f2 + f1;
          
        if (i % 2 == 0)

382
Chapter 41. Alternate Fibonacci Numbers

            System.out.print(f3 + " ");


  
        f1 = f2;
        f2 = f3;
    }
}
  
// Driver Code
public static void main (String[] args) 
{
    int N = 15;
    alternateFib(N);
}
}
  
// This code is contributed
// by chandan_jnu.

C#
// Alternate Fibonacci Series
// using Dynamic Programming
using System;
class GFG
{
static void alternateFib(int n)
{
if (n < 0) return; /* 0th and 1st number of the series are 0 and 1*/ int f1 = 0; int f2 = 1;
Console.Write(f1 + ” ”); for (int i = 2; i <= n; i++) { int f3 = f2 + f1; if (i % 2 == 0)
Console.Write(f3 + ” ”); f1 = f2; f2 = f3; } } // Driver Code public static void Main () { int
N = 15; alternateFib(N); } } // This code is contributed // by chandan_jnu. [tabbyending]
Output:

0 1 3 8 21 55 144 377

Time Complexity : O(n)


Auxiliary Space : O(1)
Improved By : Chandan_Kumar

383
Chapter 42

Balanced expressions such that


given positions have opening
brackets

Balanced expressions such that given positions have opening brackets - GeeksforGeeks
Given an integer n and an array of positions ‘position[]’ (1 <= position[i] <= 2n), find the
number of ways of proper bracket expressions that can be formed of length 2n such that
given positions have opening bracket. Examples :

Input : n = 3, position[] = [2}


Output : 3
Explanation :
The proper bracket sequences of length 6 and
opening bracket at position 2 are:
[ [ ] ] [ ]
[ [ [ ] ] ]
[ [ ] [ ] ]

Input : n = 2, position[] = {1, 3}


Output : 1
Explanation: The only possibility is:
[ ] [ ]

Approach : This problem can be solved by Dynamic programming..


Let DPi, j be the number of valid ways of filling the first i positions such that there are
j more brackets of type ‘[‘ than of type ‘]’. Valid ways would mean that it is the prefix
of a matched bracket expression and that the locations at which enforced ‘[‘ brackets are
enforced, have been satisfied. It is easy to see that DP2N, 0 is the final answer.

384
Chapter 42. Balanced expressions such that given positions have opening brackets

The base case of the DP is, DP0, 0 =1. We need to fill the first position with a ‘[‘ bracket,
and there is only way to do this.
If the position has a opening bracket sequence which can be marked by a hash array,
then the recurrence occurs as :

if(j != 0) dpi, j = dpi-1, j-1


else dpi, j = 0;

If the position has no opening bracket sequence, then recurrence happens as :

if(j != 0) dpi, j = dpi - 1, j - 1 + dpi - 1, j + 1


else dpi, j = dpi - 1, j + 1

The answer will be DP2n, 0

Given below is the CPP implementation of the above approach :


C++

// CPP code to find number of ways of


// arranging bracket with proper expressions
#include <bits/stdc++.h>
using namespace std;
  
#define N 1000
  
// function to calculate the number
// of proper bracket sequence
long long arrangeBraces(int n, int pos[], int k)
{
  
    // hash array to mark the
    // positions of opening brackets
    bool h[N];
  
    // dp 2d array
    int dp[N][N];
  
    memset(h, 0, sizeof h);
    memset(dp, 0, sizeof dp);
  
    // mark positions in hash array
    for (int i = 0; i < k; i++)
        h[pos[i]] = 1;
  
    // first position marked as 1
    dp[0][0] = 1;

385
Chapter 42. Balanced expressions such that given positions have opening brackets

  
    // iterate and formulate the recurrences
    for (int i = 1; i <= 2 * n; i++) {
        for (int j = 0; j <= 2 * n; j++) {
  
            // if position has a opening bracket
            if (h[i]) {
                if (j != 0)
                    dp[i][j] = dp[i - 1][j - 1];
                else
                    dp[i][j] = 0;
            }
            else {
                if (j != 0)
                    dp[i][j] = dp[i - 1][j - 1] +
                               dp[i - 1][j + 1];
                else
                    dp[i][j] = dp[i - 1][j + 1];
            }
        }
    }
  
    // return answer
    return dp[2 * n][0];
}
  
// driver code
int main()
{
    int n = 3;
  
    // positions where opening braces
    // will be placed
    int pos[] = { 2 };
    int k = sizeof(pos)/sizeof(pos[0]);
  
    cout << arrangeBraces(n, pos, k);
    return 0;
}

Output :

Time Complexity: O(n^2)


Auxiliary Space: O(n^2)

386
Chapter 42. Balanced expressions such that given positions have opening brackets

Source

https://www.geeksforgeeks.org/balanced-expressions-such-that-given-positions-have-opening-brackets/

387
Chapter 43

Balanced expressions such that


given positions have opening
brackets | Set 2

Balanced expressions such that given positions have opening brackets | Set 2 - GeeksforGeeks
Given an integer n and an array of positions ‘position[]’ (1 <= length(position[]) <= 2n),
find the number of ways of proper bracket expressions that can be formed of length 2n such
that given positions have the opening bracket.

Note: position[] array is given in the form of (1-based indexing) [0, 1, 1, 0]. Here 1
denotes the positions at which open bracket should be placed. At positions with value 0,
either of opening and closing bracket can be placed.
Examples:

Input: n = 3, position[] = [0, 1, 0, 0, 0, 0]


Output: 3
The proper bracket sequences of length 6 and
opening bracket at position 2 are:
[[]][]
[[[]]]
[[][]]
Input: n = 2, position[] = [1, 0, 1, 0]
Output: 1
The only possibility is:
[][]

Dynamic Programming approach of this problem has been already discussed here. In this
post, recursive and recursion using memoization approach will be discussed.
Algorithm–

388
Chapter 43. Balanced expressions such that given positions have opening brackets | Set 2

1. Mark all the positions with open brackets in the given array adj as 1.
2. Run a recursive loop, such that –
• If count of total brackets(opening brackets subracted from closing brackets is less
than zero), return 0.
• If the index reaches till n and if the total brackets=0, then a solution is obtained
and return 1, otherwise return 0.
• If the index has 1 pre-assigned to it, return the function recursively with index+1
and increment the total brackets.
• Otherwise Return the function recursively by inserting open brackets at that
index and incrementing total brackets by 1 + inserting closed brackets at that
index and decrementing total brackets by 1 and move on to the next index till n.

Below is the Recursive solution for above algorithm:

// C++ implementation of above 


// approach using Recursion
#include <bits/stdc++.h>
using namespace std;
  
// Function to find Number of
// proper bracket expressions
int find(int index, int openbrk, int n, int adj[])
{
    // If open-closed brackets < 0
    if (openbrk < 0)
        return 0;
  
    // If index reaches the end of expression
    if (index == n) {
  
        // IF brackets are balanced
        if (openbrk == 0)
            return 1;
        else
            return 0;
    }
  
    // If the current index has assigned open bracket
    if (adj[index] == 1) {
  
        // Move forward increasing the
        // length of open brackets
        return find(index + 1, openbrk + 1, n, adj);
    }
  
    else {
  

389
Chapter 43. Balanced expressions such that given positions have opening brackets | Set 2

        // Move forward by inserting open as well


        // as closed brackets on that index
        return find(index + 1, openbrk + 1, n, adj)
               + find(index + 1, openbrk - 1, n, adj);
    }
}
// Driver Code
int main()
{
  
    int n = 2;
  
    // Open brackets at postion 1
    int adj[4] = { 1, 0, 0, 0 };
  
    // Calling the find function to calculate the answer
    cout << find(0, 0, 2 * n, adj) << endl;
  
  return 0;
}

Output:

Memoized Approach: Time complexity of the above algorithm can be optimized by using
Memorization. The only thing to be done is to use an array to store the results of previous
iterations so that there is no need to recursively call the same function more than once, if
the value is already calculated.
Below is the required implementation:

// C++ implemntation of above 


// approach using memoizaion
#include <bits/stdc++.h>
using namespace std;
  
#define N 1000
  
// Function to find Number
// of proper bracket expressions
int find(int index, int openbrk, int n,
         int dp[N][N], int adj[])
{
    // If open-closed brackets<0
    if (openbrk < 0)
        return 0;

390
Chapter 43. Balanced expressions such that given positions have opening brackets | Set 2

  
    // If index reaches the end of expression
    if (index == n) {
  
        // If brackets are balanced
        if (openbrk == 0)
            return 1;
  
        else
            return 0;
    }
  
    // If already stored in dp
    if (dp[index][openbrk] != -1)
        return dp[index][openbrk];
  
    // If the current index has assigned open bracket
    if (adj[index] == 1) {
  
        // Move forward increasing the
        // length of open brackets
        dp[index][openbrk] = find(index + 1,
                                  openbrk + 1, n, dp, adj);
    }
    else {
        // Move forward by inserting open as
        // well as closed brackets on that index
        dp[index][openbrk] = find(index + 1, openbrk + 1, n, dp, adj)
                             + find(index + 1, openbrk - 1, n, dp, adj);
    }
    // return the answer
    return dp[index][openbrk];
}
  
// Driver Code
int main()
{
    // DP array to precompute the answer
    int dp[N][N];
    int n = 2;
  
    memset(dp, -1, sizeof(dp));
  
    // Open brackets at postion 1
    int adj[4] = { 1, 0, 0, 0 };
  
    // Calling the find function to calculate the answer
    cout << find(0, 0, 2 * n, dp, adj) << endl;

391
Chapter 43. Balanced expressions such that given positions have opening brackets | Set 2

  
  return 0;
}

Output:

Time complexity: O(N2 )

Source

https://www.geeksforgeeks.org/balanced-expressions-such-that-given-positions-have-opening-brackets-set-2/

392
Chapter 44

Bell Numbers (Number of ways


to Partition a Set)

Bell Numbers (Number of ways to Partition a Set) - GeeksforGeeks


Given a set of n elements, find number of ways of partitioning it.
Examples:

Input: n = 2
Output: Number of ways = 2
Explanation: Let the set be {1, 2}
{ {1}, {2} }
{ {1, 2} }

Input: n = 3
Output: Number of ways = 5
Explanation: Let the set be {1, 2, 3}
{ {1}, {2}, {3} }
{ {1}, {2, 3} }
{ {2}, {1, 3} }
{ {3}, {1, 2} }
{ {1, 2, 3} }.

Solution to above questions is Bell Number.


What is a Bell Number?
Let S(n, k) be total number of partitions of n elements into k sets. The value of n’th Bell
Number is sum of S(n, k) for k = 1 to n.

Value of S(n, k) can be defined recursively as, S(n+1, k) = k*S(n, k) + S(n, k-1)

393
Chapter 44. Bell Numbers (Number of ways to Partition a Set)

How does above recursive formula work?


When we add a (n+1)’th element to k partitions, there are two possibilities.
1) It is added as a single element set to existing partitions, i.e, S(n, k-1)
2) It is added to all sets of every partition, i.e., k*S(n, k)
S(n, k) is called Stirling numbers of the second kind
First few Bell numbers are 1, 1, 2, 5, 15, 52, 203, ….
A Simple Method to compute n’th Bell Number is to one by one compute S(n, k) for k
= 1 to n and return sum of all computed values. Refer this for computation of S(n, k).
A Better Method is to use Bell Triangle. Below is a sample Bell Triangle for first few Bell
Numbers.

1
1 2
2 3 5
5 7 10 15
15 20 27 37 52

The triangle is constructed using below formula.

// If this is first column of current row 'i'


If j == 0
// Then copy last entry of previous row
// Note that i'th row has i entries
Bell(i, j) = Bell(i-1, i-1)

// If this is not first column of current row


Else
// Then this element is sum of previous element
// in current row and the element just above the
// previous element
Bell(i, j) = Bell(i-1, j-1) + Bell(i, j-1)

Interpretation
Then Bell(n, k) counts the number of partitions of the set {1, 2, …, n + 1} in which the
element k + 1 is the largest element that can be alone in its set.
For example, Bell(3, 2) is 3, it is count of number of partitions of {1, 2, 3, 4} in which 3 is
the largest singleton element. There are three such partitions:

{1}, {2, 4}, {3}


{1, 4}, {2}, {3}
{1, 2, 4}, {3}.

394
Chapter 44. Bell Numbers (Number of ways to Partition a Set)

Below is Dynamic Programming based implementation of above recursive formula.

C++

// A C++ program to find n'th Bell number


#include<iostream>
using namespace std;
  
int bellNumber(int n)
{
   int bell[n+1][n+1];
   bell[0][0] = 1;
   for (int i=1; i<=n; i++)
   {
      // Explicitly fill for j = 0
      bell[i][0] = bell[i-1][i-1];
  
      // Fill for remaining values of j
      for (int j=1; j<=i; j++)
         bell[i][j] = bell[i-1][j-1] + bell[i][j-1];
   }
   return bell[n][0];
}
  
// Driver program
int main()
{
   for (int n=0; n<=5; n++)
      cout << "Bell Number " << n << " is " 
           << bellNumber(n) << endl;
   return 0;
}

Java

// Java program to find n'th Bell number


import java.io.*;
  
class GFG 
{
    // Function to find n'th Bell Number
    static int bellNumber(int n)
    {
        int[][] bell = new int[n+1][n+1];
        bell[0][0] = 1;
          
        for (int i=1; i<=n; i++)

395
Chapter 44. Bell Numbers (Number of ways to Partition a Set)

        {
            // Explicitly fill for j = 0
            bell[i][0] = bell[i-1][i-1];
   
            // Fill for remaining values of j
            for (int j=1; j<=i; j++)
                bell[i][j] = bell[i-1][j-1] + bell[i][j-1];
        }
          
        return bell[n][0];
    }
      
    // Driver program
    public static void main (String[] args) 
    {
        for (int n=0; n<=5; n++)
            System.out.println("Bell Number "+ n +
                            " is "+bellNumber(n));
    }
}
  
// This code is contributed by Pramod Kumar

Python3

# A Python program to find n'th Bell number


  
def bellNumber(n):
  
    bell = [[0 for i in range(n+1)] for j in range(n+1)]
    bell[0][0] = 1
    for i in range(1, n+1):
  
        # Explicitly fill for j = 0
        bell[i][0] = bell[i-1][i-1]
  
        # Fill for remaining values of j
        for j in range(1, i+1):
            bell[i][j] = bell[i-1][j-1] + bell[i][j-1]
  
    return bell[n][0]
  
# Driver program
for n in range(6):
    print('Bell Number', n, 'is', bellNumber(n))
  
# This code is contributed by Soumen Ghosh

396
Chapter 44. Bell Numbers (Number of ways to Partition a Set)

C#

// C# program to find n'th Bell number


using System;
  
class GFG {
      
    // Function to find n'th 
    // Bell Number
    static int bellNumber(int n)
    {
        int[,] bell = new int[n + 1, 
                              n + 1];
        bell[0, 0] = 1;
          
        for (int i = 1; i <= n; i++)
        {
              
            // Explicitly fill for j = 0
            bell[i, 0] = bell[i - 1, i - 1];
  
            // Fill for remaining values of j
            for (int j = 1; j <= i; j++)
                bell[i, j] = bell[i - 1, j - 1] + 
                             bell[i, j - 1];
        }
          
        return bell[n, 0];
    }
      
    // Driver Code
    public static void Main () 
    {
        for (int n = 0; n <= 5; n++)
            Console.WriteLine("Bell Number "+ n +
                              " is "+bellNumber(n));
    }
}
  
// This code is contributed by nitin mittal.

PHP

<?php
// A PHP program to find
// n'th Bell number
  

397
Chapter 44. Bell Numbers (Number of ways to Partition a Set)

// function that returns 


// n'th bell number
function bellNumber($n)
{
  
    $bell[0][0] = 1;
    for ($i = 1; $i <= $n; $i++)
    {
          
        // Explicitly fill for j = 0
        $bell[$i][0] = $bell[$i - 1]
                            [$i - 1];
      
        // Fill for remaining 
        // values of j
        for ($j = 1; $j <= $i; $j++)
            $bell[$i][$j] = $bell[$i - 1][$j - 1] + 
                                $bell[$i][$j - 1];
    }
    return $bell[$n][0];
}
  
// Driver Code
for ($n = 0; $n <= 5; $n++)
echo("Bell Number " . $n . " is "
      . bellNumber($n) . "\n");
  
// This code is contributed by Ajit.
?>

Output:

Bell Number 0 is 1
Bell Number 1 is 1
Bell Number 2 is 2
Bell Number 3 is 5
Bell Number 4 is 15
Bell Number 5 is 52

Time Complexity of above solution is O(n2 ). We will soon be discussing other more efficient
methods of computing Bell Numbers.
Another problem that can be solved by Bell Numbers.
A number is squarefree if it is not divisible by a perfect square other than 1. For example,
6 is a square free number but 12 is not as it is divisible by 4.
Given a squarefree number x, find the number of different multiplicative partitions of x. The
number of multiplicative partitions is Bell(n) where n is number of prime factors of x. For

398
Chapter 44. Bell Numbers (Number of ways to Partition a Set)

example x = 30, there are 3 prime factors of 2, 3 and 5. So the answer is Bell(3) which is 5.
The 5 partitions are 1 x 30, 2 x15, 3 x 10, 5 x 6 and 2 x 3 x 5.
Exercise:
The above implementation causes arithmetic overflow for slightly larger values of n. Ex-
tend the above program so that results are computed under modulo 1000000007 to avoid
overflows.
Reference:
https://en.wikipedia.org/wiki/Bell_number
https://en.wikipedia.org/wiki/Bell_triangle
This article is contributed by Rajeev Agrawal. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above.
Improved By : nitin mittal, jit_t

Source

https://www.geeksforgeeks.org/bell-numbers-number-of-ways-to-partition-a-set/

399
Chapter 45

Bitmasking and Dynamic


Programming | Set 1 (Count
ways to assign unique cap to
every person)

Bitmasking and Dynamic Programming | Set 1 (Count ways to assign unique cap to every
person) - GeeksforGeeks
Consider the below problems statement.
There are 100 different types of caps each having a unique id from 1 to 100. Also, there
are ‘n’ persons each having a collection of a variable number of caps. One day all of these
persons decide to go in a party wearing a cap but to look unique they decided that none of
them will wear the same type of cap. So, count the total number of arrangements or ways
such that none of them is wearing the same type of cap.
Constraints: 1 <= n <= 10 Example:

The first line contains the value of n, next n lines contain collections
of all the n persons.
Input:
3
5 100 1 // Collection of the first person.
2 // Collection of the second person.
5 100 // Collection of the third person.

Output:
4
Explanation: All valid possible ways are (5, 2, 100), (100, 2, 5),
(1, 2, 5) and (1, 2, 100)

400
Chapter 45. Bitmasking and Dynamic Programming | Set 1 (Count ways to assign unique
cap to every person)

Since, number of ways could be large, so output modulo 1000000007


We strongly recommend you to minimize your browser and try this yourself
first.
A Simple Solution is to try all possible combinations. Start by picking the first element
from the first set, marking it as visited and recur for remaining sets. It is basically a
Backtracking based solution.
A better solution is to use Bitmasking and DP. Let us first introduce Bitmasking.
What is Bitmasking?
Suppose we have a collection of elements which are numbered from 1 to N. If we want to
represent a subset of this set then it can be encoded by a sequence of N bits (we usually call
this sequence a “mask”). In our chosen subset the i-th element belongs to it if and only if
the i-th bit of the mask is set i.e., it equals to 1. For example, the mask 10000101 means
that the subset of the set [1… 8] consists of elements 1, 3 and 8. We know that for a set
of N elements there are total 2N subsets thus 2N masks are possible, one representing each
subset. Each mask is, in fact, an integer number written in binary notation.
Our main methodology is to assign a value to each mask (and, therefore, to each subset)
and thus calculate the values for new masks using values of the already computed masks.
Usually our main target is to calculate value/solution for the complete set i.e., for mask
11111111. Normally, to find the value for a subset X we remove an element in every possible
way and use values for obtained subsets X’1 , X’2 … ,X’k to compute the value/solution for X.
This means that the values for X’i must have been computed already, so we need to establish
an ordering in which masks will be considered. It’s easy to see that the natural ordering will
do: go over masks in increasing order of corresponding numbers. Also, We sometimes, start
with the empty subset X and we add elements in every possible way and use the values of
obtained subsets X’1 , X’2 … ,X’k to compute the value/solution for X.
We mostly use the following notations/operations on masks:
bit(i, mask) – the i-th bit of mask
count(mask) – the number of non-zero bits in the mask
first(mask) – the number of the lowest non-zero bit in the mask
set(i, mask) – set the ith bit in the mask
check(i, mask) – check the ith bit in the mask
How is this problem solved using Bitmasking + DP?
The idea is to use the fact that there are upto 10 persons. So we can use an integer variable
as a bitmask to store which person is wearing a cap and which is not.

Let i be the current cap number (caps from 1 to i-1 are already
processed). Let integer variable mask indicates that the persons w
earing and not wearing caps. If i'th bit is set in mask, then
i'th person is wearing a cap, else not.

// consider the case when ith cap is not included


// in the arrangement
countWays(mask, i) = countWays(mask, i+1) +

401
Chapter 45. Bitmasking and Dynamic Programming | Set 1 (Count ways to assign unique
cap to every person)

// when ith cap is included in the arrangement


// so, assign this cap to all possible persons
// one by one and recur for remaining persons.
&Sum; countWays(mask | (1 << j), i+1)
for every person j that can wear cap i

Note that the expression "mask | (1 << j)" sets j'th bit in mask.
And a person can wear cap i if it is there in the person's cap list
provided as input.

If we draw the complete recursion tree, we can observe that many subproblems are solved
again and again. So we use Dynamic Programming. A table dp[][] is used such that in every
entry dp[i][j], i is mask and j is cap number.
Since we want to access all persons that can wear a given cap, we use an array of vectors,
capList[101]. A value capList[i] indicates the list of persons that can wear cap i.
Below is the implementation of above idea.

C/C++

// C++ program to find number of ways to wear hats


#include<bits/stdc++.h>
#define MOD 1000000007
using namespace std;
  
// capList[i]'th vector contains the list of persons having a cap with id i
// id is between 1 to 100 so we declared an array of 101 vectors as indexing
// starts from 0.
vector<int> capList[101];
  
// dp[2^10][101] .. in dp[i][j], i denotes the mask i.e., it tells that
// how many and which persons are wearing cap. j denotes the first j caps
// used. So, dp[i][j] tells the number ways we assign j caps to mask i
// such that none of them wears the same cap
int dp[1025][101];
  
// This is used for base case, it has all the N bits set
// so, it tells whether all N persons are wearing a cap.
int allmask;
  
// Mask is the set of persons, i is cap-id (OR the 
// number of caps processed starting from first cap).
long long int countWaysUtil(int mask, int i)
{
    // If all persons are wearing a cap so we
    // are done and this is one way so return 1
    if (mask == allmask) return 1;

402
Chapter 45. Bitmasking and Dynamic Programming | Set 1 (Count ways to assign unique
cap to every person)

  
    // If not everyone is wearing a cap and also there are no more
    // caps left to process, so there is no way, thus return 0;
    if (i > 100) return 0;
  
    // If we already have solved this subproblem, return the answer.
    if (dp[mask][i] != -1) return dp[mask][i];
  
    // Ways, when we don't include this cap in our arrangement
    // or solution set.
    long long int ways = countWaysUtil(mask, i+1);
  
    // size is the total number of persons having cap with id i.
    int size = capList[i].size();
  
    // So, assign one by one ith cap to all the possible persons
    // and recur for remaining caps.
    for (int j = 0; j < size; j++)
    {
        // if person capList[i][j] is already wearing a cap so continue as
        // we cannot assign him this cap
        if (mask & (1 << capList[i][j])) continue;
  
        // Else assign him this cap and recur for remaining caps with
        // new updated mask vector
        else ways += countWaysUtil(mask | (1 << capList[i][j]), i+1);
        ways %= MOD;
    }
  
    // Save the result and return it.
    return dp[mask][i] = ways;
}
  
// Reads n lines from standard input for current test case
void countWays(int n)
{
    //----------- READ INPUT --------------------------
    string temp, str;
    int x;
    getline(cin, str);  // to get rid of newline character
    for (int i=0; i<n; i++)
    {
        getline(cin, str);
        stringstream ss(str);
  
        // while there are words in the streamobject ss
        while (ss >> temp)
        {

403
Chapter 45. Bitmasking and Dynamic Programming | Set 1 (Count ways to assign unique
cap to every person)

            stringstream s;
            s << temp;
            s >> x;
  
            // add the ith person in the list of cap if with id x
            capList[x].push_back(i);
        }
    }
    //----------------------------------------------------
  
    // All mask is used to check whether all persons
    // are included or not, set all n bits as 1
    allmask = (1 << n) - 1;
  
    // Initialize all entries in dp as -1
    memset(dp, -1, sizeof dp);
  
    // Call recursive function count ways
    cout << countWaysUtil(0, 1) << endl;
}
  
// Driver Program
int main()

     int n;   // number of persons in every test case
     cin >> n;
     countWays(n);
     return 0;
}

Java

// Java program to find number of ways to wear hats


  
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Vector;
  
class Test
{
    static final int MOD = 1000000007;
      
    // for input
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
      
    // capList[i]'th vector contains the list of persons having a cap with id i
    // id is between 1 to 100 so we declared an array of 101 vectors as indexing
    // starts from 0.

404
Chapter 45. Bitmasking and Dynamic Programming | Set 1 (Count ways to assign unique
cap to every person)

    static Vector<Integer> capList[] = new Vector[101];


      
       
    // dp[2^10][101] .. in dp[i][j], i denotes the mask i.e., it tells that
    // how many and which persons are wearing cap. j denotes the first j caps
    // used. So, dp[i][j] tells the number ways we assign j caps to mask i
    // such that none of them wears the same cap
    static int dp[][] = new int[1025][101];
       
    // This is used for base case, it has all the N bits set
    // so, it tells whether all N persons are wearing a cap.
    static int allmask;
       
    // Mask is the set of persons, i is cap-id (OR the 
    // number of caps processed starting from first cap).
    static long countWaysUtil(int mask, int i)
    {
        // If all persons are wearing a cap so we
        // are done and this is one way so return 1
        if (mask == allmask) return 1;
       
        // If not everyone is wearing a cap and also there are no more
        // caps left to process, so there is no way, thus return 0;
        if (i > 100) return 0;
       
        // If we already have solved this subproblem, return the answer.
        if (dp[mask][i] != -1) return dp[mask][i];
       
        // Ways, when we don't include this cap in our arrangement
        // or solution set.
        long ways = countWaysUtil(mask, i+1);
       
        // size is the total number of persons having cap with id i.
        int size = capList[i].size();
       
        // So, assign one by one ith cap to all the possible persons
        // and recur for remaining caps.
        for (int j = 0; j < size; j++)
        {
            // if person capList[i][j] is already wearing a cap so continue as
            // we cannot assign him this cap
            if ((mask & (1 << capList[i].get(j))) != 0) continue;
       
            // Else assign him this cap and recur for remaining caps with
            // new updated mask vector
            else ways += countWaysUtil(mask | (1 << capList[i].get(j)), i+1);
            ways %= MOD;
        }

405
Chapter 45. Bitmasking and Dynamic Programming | Set 1 (Count ways to assign unique
cap to every person)

       
        // Save the result and return it.
        return dp[mask][i] = (int) ways;
    }
       
    // Reads n lines from standard input for current test case
    static void countWays(int n) throws Exception
    {
        //----------- READ INPUT --------------------------
        String str;
        String split[];
        int x;
                
        for (int i=0; i<n; i++)
        {
            str = br.readLine();
            split = str.split(" ");
            
            // while there are words in the split[]
            for (int j = 0; j < split.length; j++) {
                 // add the ith person in the list of cap if with id x
                x = Integer.parseInt(split[j]);
                capList[x].add(i);
            }
            
        }
        //----------------------------------------------------
       
        // All mask is used to check of all persons
        // are included or not, set all n bits as 1
        allmask = (1 << n) - 1;
       
        // Initialize all entries in dp as -1
        for (int[] is : dp) {
            for (int i = 0; i < is.length; i++) {
                is[i] = -1;
            }
        }
       
        // Call recursive function count ways
        System.out.println(countWaysUtil(0, 1));
    }
  
    // Driver method
    public static void main(String args[]) throws Exception
    {
        int n;   // number of persons in every test case
          

406
Chapter 45. Bitmasking and Dynamic Programming | Set 1 (Count ways to assign unique
cap to every person)

        // initializing vector array


        for (int i = 0; i < capList.length; i++)
            capList[i] = new Vector<>();
          
          
        n = Integer.parseInt(br.readLine());
        countWays(n);
    }
}
// This code is contributed by Gaurav Miglani

Python

#Python program to find number of ways to wear hats


from collections import defaultdict
  
class AssignCap:
  
    # Initialize variables
    def __init__(self):
  
            self.allmask = 0
  
            self.total_caps = 100
  
            self.caps = defaultdict(list)
  
  
    #  Mask is the set of persons, i is the current cap number.
    def countWaysUtil(self,dp, mask, cap_no):
          
        # If all persons are wearing a cap so we
        # are done and this is one way so return 1
        if mask == self.allmask:
            return 1
  
        # If not everyone is wearing a cap and also there are no more
        # caps left to process, so there is no way, thus return 0;
        if cap_no > self.total_caps:
            return 0
  
        # If we have already solved this subproblem, return the answer.
        if dp[mask][cap_no]!= -1 :
            return dp[mask][cap_no]
  
        # Ways, when we don't include this cap in our arrangement
        # or solution set
        ways = self.countWaysUtil(dp, mask, cap_no + 1)

407
Chapter 45. Bitmasking and Dynamic Programming | Set 1 (Count ways to assign unique
cap to every person)

          
        # assign ith cap one by one  to all the possible persons
        # and recur for remaining caps.
        if cap_no in self.caps:
  
            for ppl in self.caps[cap_no]:
                  
                # if person 'ppl' is already wearing a cap then continue
                if mask & (1 << ppl) : continue
                  
                # Else assign him this cap and recur for remaining caps with
                # new updated mask vector
                ways += self.countWaysUtil(dp, mask | (1 << ppl), cap_no + 1) 
  
                ways = ways % (10**9 + 7)
  
        # Save the result and return it
        dp[mask][cap_no] = ways
  
        return dp[mask][cap_no]
  
  
  
    def countWays(self,N):
  
        # Reads n lines from standard input for current test case
        # create dictionary for cap. cap[i] = list of person having
        # cap no i
        for ppl in range(N):
  
            cap_possessed_by_person = map(int, raw_input().strip().split())
  
            for i in cap_possessed_by_person:
  
                self.caps[i].append(ppl)
  
        # allmask is used to check if all persons
        # are included or not, set all n bits as 1
        self.allmask = (1 << N) -1
  
        # Initialize all entries in dp as -1
        dp = [[-1 for j in range(self.total_caps + 1)] for i in range(2 ** N)]
  
        # Call recursive function countWaysUtil
        # result will be in dp[0][1]
        print self.countWaysUtil(dp, 0, 1,)
  
#Driver Program

408
Chapter 45. Bitmasking and Dynamic Programming | Set 1 (Count ways to assign unique
cap to every person)

def main():
    No_of_people = input() # number of persons in every test case
  
    AssignCap().countWays(No_of_people)
  
  
if __name__ == '__main__':
    main()
  
# This code is contributed by Neelam Yadav

Input:

3
5 100 1
2
5 100

Output:

This article is contributed by Gaurav Ahirwar. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above

Source

https://www.geeksforgeeks.org/bitmasking-and-dynamic-programming-set-1-count-ways-to-assign-unique-cap-to-ev

409
Chapter 46

Bitmasking and Dynamic


Programming | Set-2 (TSP)

Bitmasking and Dynamic Programming | Set-2 (TSP) - GeeksforGeeks


In this post, we will be using our knowledge of dynamic programming and Bitmasking
technique to solve one of the famous NP-hard problem “Travelling Salesman Problem”.
Before solving the problem, we assume that the reader has the knowledge of

• DP and formation of DP transition relation


• Bitmasking in DP
• Travelling Salesman problem

To understand this concept lets consider the below problem :

Problem Description:

Given a 2D grid of characters representing


a town where '*' represents the
houses, '#' represents the blockage,
'.' represents the vacant street
area. Currently you are (0, 0) position.

Our task is to determine the minimum distance


to be moved to visit all the houses and return
to our initial position at (0, 0). You can
only move to adjacent cells that share exactly
1 edge with the current cell.

The above problem is the well-known Travelling Salesman Problem.

410
Chapter 46. Bitmasking and Dynamic Programming | Set-2 (TSP)

The first part is to calculate the minimum distance between the two cells. We can do it by
simply using a BFS as all the distances are unit distance. To optimize our solution we will
be pre-calculating the distances taking the initial location and the location of the houses as
the source point for our BFS.
Each BFS traversal takes O(size of grid) time. Therefore, it is O(X * size_of_grid) for
overall pre-calculation, where X = number of houses + 1 (initial position)
Now lets’s think of a DP state
So we will be needing to track the visited houses and the last visited house to uniquely
identify a state in this problem.
Therefore, we will be taking dp[index][mask] as our DP state.
Here,
index : tells us the location of current house
mask : tells us the houses that are visited ( if ith bit is set in mask then this means that
the ith dirty tile is cleaned)
Whereas dp[index][mask] will tell us the minimum distance to visit X(number of set bits in
mask) houses corresponding to their order of their occurrence in the mask where the last
visited house is house at location index.
State transition relation
So our initial state will be dp[0][0] this tells that we are currently at initial tile that is our
initial location and mask is 0 that states that no house is visited till now.
And our final destination state will be dp[any index][LIMIT_MASK], here
LIMIT_MASK = (1<<N) – 1
and N = number of houses.
Therefore our DP state transition can be stated as

dp(curr_idx)(curr_mask) = min{
for idx : off_bits_in_curr_mask
dp(idx)(cur_mask.set_bit(idx)) + dist[curr_idx][idx]
}

The above relation can be visualized as the minimum distance to visit all the houses by
standing at curr_idx house and by already visiting cur_mask houses is equal to min of
distance between the curr_idx house and idx house + minimum distance to visit all the
houses by standing at idx house and by already
visiting ( cur_mask | (1 <<idx) ) houses.
So, here we iterate over all possible idx values such that cur_mask has ith bit as 0 that tells
us that ith house is not visited.
Whenever we have our mask = LIMIT_MASK, this means that we have visited all the
houses in the town. So, we will add the distance from the last visited town (i.e the town at
cur_idx positon) to the initial position (0, 0).
The C++ program for the above implementation is given below:

411
Chapter 46. Bitmasking and Dynamic Programming | Set-2 (TSP)

#include <bits/stdc++.h>
using namespace std;
  
#define INF 99999999
#define MAXR 12
#define MAXC 12
#define MAXMASK 2048
#define MAXHOUSE 12
  
// stores distance taking souce
// as every dirty tile
int dist[MAXR][MAXC][MAXHOUSE];
  
// memoization for dp states
int dp[MAXHOUSE][MAXMASK];
  
// stores coordinates for
// dirty tiles
vector < pair < int, int > > dirty;
  
// Directions
int X[] = {-1, 0, 0, 1};
int Y[] = {0, 1, -1, 0};
  
char arr[21][21];
  
// len : number of dirty tiles + 1
// limit : 2 ^ len -1
// r, c : number of rows and columns
int len, limit, r, c;
  
  
// Returns true if current position
// is safe to visit
// else returns false
// Time Complexity : O(1)
bool safe(int x, int y)
{
    if (x >= r or y>= c or x<0 or y<0)
       return false;
    if (arr[x][y] == '#')
       return false;
    return true;
}
  
  
// runs BFS traversal at tile idx
// calulates distance to every cell

412
Chapter 46. Bitmasking and Dynamic Programming | Set-2 (TSP)

// in the grid
// Time Complexity : O(r*c)
void getDist(int idx){
  
    // visited array to track visited cells
    bool vis[21][21];
    memset(vis, false, sizeof(vis));
  
    // getting current positon
    int cx = dirty[idx].first;
    int cy = dirty[idx].second;
  
    // initializing queue for bfs
    queue < pair < int, int > > pq;
    pq.push({cx, cy});
  
    // initializing the dist to max
    // because some cells cannot be visited
    // by taking source cell as idx
    for (int i = 0;i<= r;i++)
        for (int j = 0;j<= c;j++)
            dist[i][j][idx] = INF;
  
    // base conditions
    vis[cx][cy] = true;
    dist[cx][cy][idx] = 0;
  
    while (! pq.empty())
    {
        auto x = pq.front();
        pq.pop();
        for (int i = 0;i<4;i++)
        {
           cx = x.first + X[i];
           cy = x.second + Y[i];
           if (safe(cx, cy))
           {
               if (vis[cx][cy])
                   continue;
               vis[cx][cy] = true;
               dist[cx][cy][idx] = dist[x.first][x.second][idx] + 1;
               pq.push({cx, cy});
            }
         }
    }
}
  
// Dynamic Programming state transition recursion

413
Chapter 46. Bitmasking and Dynamic Programming | Set-2 (TSP)

// with memoization. Time Complexity: O(n*n*2 ^ n)


int solve(int idx, int mask)
{
    // goal state
    if (mask == limit)
       return dist[0][0][idx];
  
    // if already visited state
    if (dp[idx][mask] != -1)
       return dp[idx][mask];
  
    int ret = INT_MAX;
  
    // state transiton relation
    for (int i = 0;i<len;i++)
    {
        if ((mask & (1<<i)) == 0)
        {
            int newMask = mask | (1<<i);
            ret = min( ret, solve(i, newMask)
                + dist[dirty[i].first][dirty[i].second][idx]);
        }
    }
  
    // adding memoization and returning
    return dp[idx][mask] = ret;
}
  
void init()
{
    // initializing containers
    memset(dp, -1, sizeof(dp));
    dirty.clear();
  
    // populating dirty tile positions
    for (int i = 0;i<r;i++)
        for (int j = 0;j<c;j++)
        {
            if (arr[i][j] == '*')
               dirty.push_back({i, j});
        }
  
    // inserting ronot's location at the
    // begining of the dirty tile
    dirty.insert(dirty.begin(), {0, 0});
  
    len = dirty.size();
  

414
Chapter 46. Bitmasking and Dynamic Programming | Set-2 (TSP)

    // calculating LIMIT_MASK


    limit = (1<<len) - 1;
  
    // precalculating distances from all
    // dirty tiles to each cell in the grid
    for (int i = 0;i<len;i++)
       getDist(i);
}
  
int main(int argc, char const *argv[])
{
    // Test case #1:
    //     .....*.
    //     ...#...
    //     .*.#.*.
    //     .......
  
char A[4][7] = {    {'.', '.', '.', '.', '.', '*', '.'},
                    {'.', '.', '.', '#', '.', '.', '.'},
                    {'.', '*', '.', '#', '.', '*', '.'},
                    {'.', '.', '.', '.', '.', '.', '.'}
                };
  
    r = 4; c = 7;
  
    cout << "The given grid : " << endl;
  
    for (int i = 0;i<r;i++)
    {
        for (int j = 0;j<c;j++)
        {
            cout << A[i][j] << " ";
            arr[i][j] = A[i][j];
        }
        cout << endl;
    }
  
    // - initializitiation
    // - precalculations
    init();
  
    int ans = solve(0, 1);
  
    cout << "Minimum distance for the given grid : ";
    cout << ans << endl;
  
  
    // Test Case #2

415
Chapter 46. Bitmasking and Dynamic Programming | Set-2 (TSP)

    //     ...#...
    //     ...#.*.
    //     ...#...
    //     .*.#.*.
    //     ...#...
  
    char Arr[5][7] = {  {'.', '.', '.', '#', '.', '.', '.'},
                        {'.', '.', '.', '#', '.', '*', '.'},
                        {'.', '.', '.', '#', '.', '.', '.'},
                        {'.', '*', '.', '#', '.', '*', '.'},
                        {'.', '.', '.', '#', '.', '.', '.'}
                };
  
    r = 5; c = 7;
  
    cout << "The given grid : " << endl;
  
    for (int i = 0;i<r;i++)
    {
        for (int j = 0;j<c;j++)
        {
            cout << Arr[i][j] << " ";
            arr[i][j] = Arr[i][j];
        }
        cout << endl;
    }
  
    // - initializitiation
    // - precalculations
    init();
    ans = solve(0, 1);
    cout << "Minimum distance for the given grid : ";
    if (ans >= INF)
        cout << "not possible" << endl;
    else
        cout << ans << endl;
  
    return 0;
}

Output:

The given grid :


. . . . . * .
. . . # . . .
. * . # . * .
. . . . . . .

416
Chapter 46. Bitmasking and Dynamic Programming | Set-2 (TSP)

Minimum distance for the given grid : 16


The given grid :
. . . # . . .
. . . # . * .
. . . # . . .
. * . # . * .
. . . # . . .
Minimum distance for the given grid : not possible

Note:
We have used the initial state to be dp[0][1] because we have pushed the start location at
the first position in the container of houses. Hence, our Bit Mask will be 1 as the 0th bit is
set i.e we have visited the starting location for our trip.
Time Complexity:
Consider the number of houses to be n. So, there are n * (2n ) states and at every state,
we are looping over n houses to transit over to next state and because of memoization we
are doing this looping transition only once for each state. Therefore, our Time Complexity
is O(n2 * 2n ).
Recommended:

• http://www.spoj.com/problems/CLEANRBT/
• https://www.youtube.com/watch?v=-JjA4BLQyqE

Source

https://www.geeksforgeeks.org/bitmasking-dynamic-programming-set-2-tsp/

417
Chapter 47

Check for possible path in 2D


matrix

Check for possible path in 2D matrix - GeeksforGeeks


Given a 2D array(m x n), check if there is any path from top left to bottom right. In the
matrix, -1 is considered as blockage (can’t go through this cell) and 0 is considered path cell
(can go through it).
Examples:

Input : arr[][] = {{ 0, 0, 0, -1, 0},


{-1, 0, 0, -1, -1},
{ 0, 0, 0, -1, 0},
{-1, 0, 0, 0, 0},
{ 0, 0, -1, 0, 0}}
Output : Yes

Input : arr[][] = {{ 0, 0, 0, -1, 0},


{-1, 0, 0, -1, -1},
{ 0, 0, 0, -1, 0},
{-1, 0, -1, 0, 0},
{ 0, 0, -1, 0, 0}}
Output : No

Approach :
A simple solution is to do BFS or DFS to find if there is a path.
A better solution is to mark all accessible nodes by changing their value to 1. First change
the value of first top left element value to 1 then in the first row get previous value and set
to current index in only first row if the value is -1 then no change then in first column do
the same.

418
Chapter 47. Check for possible path in 2D matrix

Then start from first row and first column and take previous row value and previous row
column and find max between them, and set to current index, if current index value is -1
then no change.
At the end if right bottom is 1 then return yes else return no.
C++

// CPP program to find if there is path 


// from top left to right bottom
#include <iostream>
using namespace std;
  
#define row 5
#define col 5
  
// to find the path from
// top left to bottom right
bool isPath(int arr[row][col])
{
    // set arr[0][0] = 1
    arr[0][0] = 1;
  
    // Mark reachable (from top left) nodes 
    // in first row and first column.
    for (int i = 1; i < row; i++) 
        if (arr[0][i] != -1)
            arr[0][i] = arr[0][i - 1];   
  
    for (int j = 1; j < col; j++) 
        if (arr[j][0] != -1)
            arr[j][0] = arr[j - 1][0];    
  
    // Mark reachable nodes in remaining
    // matrix.
    for (int i = 1; i < row; i++) 
        for (int j = 1; j < col; j++) 
          if (arr[i][j] != -1)
              arr[i][j] = max(arr[i][j - 1],
                            arr[i - 1][j]);       
      
    // return yes if right bottom 
    // index is 1
    return (arr[row - 1][col - 1] == 1);
}
  
// Driver Code
int main()
{
    // Given array

419
Chapter 47. Check for possible path in 2D matrix

    int arr[row][col] = { { 0, 0, 0, -1, 0 },


                          { -1, 0, 0, -1, -1 },
                          { 0, 0, 0, -1, 0 },
                          { -1, 0, -1, 0, -1 },
                          { 0, 0, -1, 0, 0 } };
  
    // path from arr[0][0] to arr[row][col]
    if (isPath(arr))
      cout << "Yes";
    else
      cout << "No";
  
return 0;
}

Java

// Java program to find if there is path


// from top left to right bottom
class GFG
{
    // to find the path from
    // top left to bottom right
    static boolean isPath(int arr[][])
    {
        // set arr[0][0] = 1
        arr[0][0] = 1;
  
        // Mark reachable (from top left) nodes
        // in first row and first column.
        for (int i = 1; i < 5; i++)
            if (arr[0][i] != -1)
                arr[0][i] = arr[0][i - 1];
        for (int j = 1; j < 5; j++)
            if (arr[j][0] != -1)
                arr[j][0] = arr[j - 1][0];
  
        // Mark reachable nodes in
        //  remaining matrix.
        for (int i = 1; i < 5; i++)
            for (int j = 1; j < 5; j++)
                if (arr[i][j] != -1)
                    arr[i][j] = Math.max(arr[i][j - 1],
                                        arr[i - 1][j]);
  
        // return yes if right 
        // bottom index is 1
        return (arr[5 - 1][5 - 1] == 1);

420
Chapter 47. Check for possible path in 2D matrix

    }
       
    //Driver code 
    public static void main(String[] args)
    {
        // Given array
        int arr[][] = { { 0, 0, 0, -1, 0 },
                        { -1, 0, 0, -1, -1 },
                        { 0, 0, 0, -1, 0 },
                        { -1, 0, -1, 0, -1 },
                        { 0, 0, -1, 0, 0 } };
  
        // path from arr[0][0] 
        // to arr[row][col]
        if (isPath(arr))
            System.out.println("Yes");
        else
            System.out.println("No");
    }
}
// This code is contributed 
// by prerna saini 

C#

// C# program to find if there is path


// from top left to right bottom
using System;
  
class GFG
{
    // to find the path from
    // top left to bottom right
    static bool isPath(int [,]arr)
    {
        // set arr[0][0] = 1
        arr[0, 0] = 1;
  
        // Mark reachable (from top left) nodes
        // in first row and first column.
        for (int i = 1; i < 5; i++)
            if (arr[0, i] != -1)
                arr[0, i] = arr[0, i - 1];
        for (int j = 1; j < 5; j++)
            if (arr[j,0] != -1)
                arr[j,0] = arr[j - 1, 0];
  
        // Mark reachable nodes in

421
Chapter 47. Check for possible path in 2D matrix

        // remaining matrix.


        for (int i = 1; i < 5; i++)
            for (int j = 1; j < 5; j++)
                if (arr[i, j] != -1)
                    arr[i, j] = Math.Max(arr[i, j - 1],
                                        arr[i - 1, j]);
  
        // return yes if right 
        // bottom index is 1
        return (arr[5 - 1, 5 - 1] == 1);
    }
      
    //Driver code 
    public static void Main()
    {
        // Given array
        int [,]arr = { { 0, 0, 0, -1, 0 },
                        { -1, 0, 0, -1, -1 },
                        { 0, 0, 0, -1, 0 },
                        { -1, 0, -1, 0, -1 },
                        { 0, 0, -1, 0, 0 } };
  
        // path from arr[0][0] 
        // to arr[row][col]
        if (isPath(arr))
            Console.WriteLine("Yes");
        else
            Console.WriteLine("No");
    }
}
  
// This code is contributed 
// by vt_m

PHP

<?php
// PHP program to find if 
// there is path from top
// left to right bottom
$row = 5;
$col = 5;
  
// to find the path from
// top left to bottom right
function isPath($arr)
{
    global $row, $col;

422
Chapter 47. Check for possible path in 2D matrix

      
    $arr[0][0] = 1;
  
    // Mark reachable (from 
    // top left) nodes in 
    // first row and first column.
    for ($i = 1; $i < $row; $i++) 
        if ($arr[0][$i] != -1)
            $arr[0][$i] = $arr[0][$i - 1]; 
  
    for ($j = 1; $j < $col; $j++) 
        if ($arr[$j][0] != -1)
            $arr[$j][0] = $arr[$j - 1][0]; 
  
    // Mark reachable nodes 
    // in remaining matrix.
    for ($i = 1; $i < $row; $i++) 
        for ($j = 1; $j < $col; $j++) 
        if ($arr[$i][$j] != -1)
            $arr[$i][$j] = max($arr[$i][$j - 1],
                               $arr[$i - 1][$j]); 
      
    // return yes if right 
    // bottom index is 1
    return ($arr[$row - 1][$col - 1] == 1);
}
  
// Driver Code
  
// Given array
$arr = array(array(0, 0, 0, 1, 0),
             array(-1, 0, 0, -1, -1),
             array(0, 0, 0, -1, 0),
             array(-1, 0, -1, 0, -1),
             array(0, 0, -1, 0, 0));
  
// path from arr[0][0]
// to arr[row][col]
if (isPath($arr))
echo "Yes";
else
echo "No";
      
// This code is contributed by anuj_67.
?>

Output:

423
Chapter 47. Check for possible path in 2D matrix

No

Time Complexity is O(n^2).


Improved By : vt_m

Source

https://www.geeksforgeeks.org/check-possible-path-2d-matrix/

424
Chapter 48

Check if all people can vote on


two machines

Check if all people can vote on two machines - GeeksforGeeks


There are n people and two identical voting machines. We are also given an array a[] of
size n such that a[i] stores time required by i-th person to go to any machine, mark his vote
and come back. At one time instant, only one person can be there on each of the machines.
Given a value x, defining the maximum allowable time for which machines are operational,
check whether all persons can cast their vote or not.
Examples:

Input : n = 3, x = 4
a[] = {2, 4, 2}
Output : YES
There are n = 3 persons say and maximum
allowed time is x = 4 units. Let the persons
be P0, P1 and P2 and two machines be M0 and M1.
At t0 : P0 goes to M0
At t0 : P2 goes to M1
At t2 : M0 is free, p3 goes to M0
At t4 : both M0 and M1 are free and all 3 have
given their vote.

Let sum be the total time taken by all n people. If sum <=x, then answer will obviously
be YES. Otherwise, we need to check whether the given array can be split in two parts
such that sum of first part and sum of second part are both less than or equal to x. The
problem is similar to the knapsack problem. Imagine two knapsacks each with capacity x.
Now find, maximum people who can vote on any one machine i.e. find maximum subset
sum for knapsack of capacity x. Let this sum be s1. Now if (sum-s1) <= x, then answer is
YES else answer is NO.

425
Chapter 48. Check if all people can vote on two machines

// C++ program to check if all people can


// vote using two machines within limited
// time
#include<bits/stdc++.h>
using namespace std;
  
// Returns true if n people can vote using
// two machines in x time.
bool canVote(int a[], int n, int x)
{
    // dp[i][j] stores maximum possible number
    // of people among arr[0..i-1] can vote
    // in j time.
    int dp[n+1][x+1];
    memset(dp, 0, sizeof(dp));
  
    // Find sum of all times
    int sum = 0;
    for (int i=0; i<=n; i++ )
        sum += a[i];
  
    // Fill dp[][] in bottom up manner (Similar
    // to knapsack).
    for (int i=1; i<=n; i++)
        for (int j=1; j<=x; j++)
            if (a[i] <= j)
                dp[i][j] = max(dp[i-1][j],
                        a[i] + dp[i-1][j-a[i]]);
            else
                dp[i][j] = dp[i-1][j];
  
    // If remaining people can go to other machine.
    return (sum - dp[n][x] <= x);
}
  
// Driver code
int main()
{
    int n = 3, x = 4;
    int a[] = {2, 4, 2};
    canVote(a, n, x)? cout << "YES\n" :
                      cout << "NO\n";
    return 0;
}

Output:

426
Chapter 48. Check if all people can vote on two machines

YES

Time Complexity : O(x * n)


Auxiliary Space : O(x * n)

Source

https://www.geeksforgeeks.org/check-people-can-vote-two-machines/

427
Chapter 49

Check if any valid sequence is


divisible by M

Check if any valid sequence is divisible by M - GeeksforGeeks


Given an array of N integers, using ‘+’ and ‘-‘ between the elements check if there is a way
to form a sequence of numbers which evaluate to a number divisible by M
Examples:

Input : arr = {1, 2, 3, 4, 6}


M = 4
Output : True,
There is a valid sequence i. e., (1 - 2
+ 3 + 4 + 6), which evaluates to 12 that
is divisible by 4

Input : arr = {1, 3, 9}


M = 2
Output : False
There is no sequence which evaluates to
a number divisible by M.

A simple solution is to recursively consider all possible scenarios ie either use a ;+’ or a ‘-‘
operator between the elements and maintain a variable sum which stores the result.If this
result is divisible by M then return true else return false
Recursive implementation is as follows:

bool isPossible(int index, int sum)


{
    // Base case

428
Chapter 49. Check if any valid sequence is divisible by M

    if (index == n) {
    
        // check if sum is divisible by M
        if ((sum % M) == 0)
            return true;
        return false;
    }
  
    // recursively call by considering '+' 
    // or '-' between index and index+1
  
    // 1.Try placing '+'
    bool placeAdd = isPossible(index + 1, 
                        sum + arr[index]);
  
    // 2. Try placing '-'
    bool placeMinus = isPossible(index + 1, 
                         sum - arr[index]);
  
    if (placeAdd || placeMinus) 
        return true;
      
    return false;
}

There are overlapping subproblems as shown in the image below (Note: the image represents
the recursion tree till index = 3)

429
Chapter 49. Check if any valid sequence is divisible by M

So, now we will solve this using dynamic programming


Method 1:
We apply Dynamic Programming with two states :-
(i) index,
(ii) sum
So DP[index][sum] stores the current index we are at and sum stores the result of evaluation
of the sequence formed till that index.

#include <bits/stdc++.h>
using namespace std;
  
const int MAX = 1000;
  
bool isPossible(int n, int index, int sum, 
          int M, int arr[], int dp[][MAX])
{
  
    // Base case
    if (index == n) {
  
        // check if sum is divisible by M

430
Chapter 49. Check if any valid sequence is divisible by M

        if ((sum % M) == 0)
            return true;
        return false;
    }
  
    // check if the current state 
    // is already computed
    if (dp[index][sum] != -1) 
        return dp[index][sum];
      
    // 1.Try placing '+'
    bool placeAdd = isPossible(n, index + 1, 
               sum + arr[index], M, arr, dp);
  
    // 2. Try placing '-'
    bool placeMinus = isPossible(n, index + 1, 
                sum - arr[index], M, arr, dp);
  
    // calculate value of res for recursive case
    bool res = (placeAdd || placeMinus);
  
    // store the value for res for current 
    // states and return for parent call
    dp[index][sum] = res;
    return res;
}
int main()
{
    int arr[] = { 1, 2, 3, 4, 6 };
    int n = sizeof(arr)/sizeof(arr[0]);
    int M = 4;
  
    int dp[n + 1][MAX];
    memset(dp, -1, sizeof(dp));
  
    bool res;
    res = isPossible(n, 0, 0, M, arr, dp);
  
    cout << (res ? "True" : "False") << endl;
    return 0;
}

Output:

True

The Complexity of this method is O(N*sum) where sum is the maximum possible sum for

431
Chapter 49. Check if any valid sequence is divisible by M

the sequence of integers and N is the number of elements in the array.


Method 2(efficient):
This is more efficient than Method 1. Here also, we apply Dynamic Programming but with
two different states :-
(i) index,
(ii) modulo
So DP[index][modulo] stores the modulus of the result of evaluation of the sequence formed
till that index, with M.

#include <bits/stdc++.h>
using namespace std;
  
const int MAX = 100;
  
int isPossible(int n, int index, int modulo,
            int M, int arr[], int dp[][MAX])
{
    // Calculate modulo for this call
    modulo = ((modulo % M) + M) % M;
  
    // Base case
    if (index == n) {
  
        // check if sum is divisible by M
        if (modulo == 0)
            return 1;
        return 0;
    }
  
    // check if the current state is 
    // already computed
    if (dp[index][modulo] != -1) 
        return dp[index][modulo];
  
    // 1.Try placing '+'
    int placeAdd = isPossible(n, index + 1,
            modulo + arr[index], M, arr, dp);
  
    // 2. Try placing '-'
    int placeMinus = isPossible(n, index + 1, 
            modulo - arr[index], M, arr, dp);
  
    // calculate value of res for recursive
    // case
    bool res = (placeAdd || placeMinus);
  
    // store the value for res for current 
    // states and return for parent call

432
Chapter 49. Check if any valid sequence is divisible by M

    dp[index][modulo] = res;
    return res;
}
  
int main()
{
    int arr[] = { 1, 2, 3, 4, 6 };
    int n = sizeof(arr)/sizeof(arr[0]);
    int M = 4;
  
    // MAX is the Maximum value M can take
    int dp[n + 1][MAX];
    memset(dp, -1, sizeof(dp));
  
    bool res;
    res = isPossible(n, 1, arr[0], M, arr, dp);
  
    cout << (res ? "True" : "False") << endl;
    return 0;
}

Output:

True

The Complexity of this method is O(N*M).

Source

https://www.geeksforgeeks.org/check-valid-sequence-divisible-m/

433
Chapter 50

Check if array sum can be made


K by three operations on it

Check if array sum can be made K by three operations on it - GeeksforGeeks


Given an array A of N integers and a positive integer K. Only three operations can be
performed on this array:
1) Replace an integer with the negative value of the integer,
2) Add index number (1-based indexing) of the element to the element itself and
3) Subtract index number of the element from the element itself.
The task is to check if the given array can be transformed, using any of above three allowed
operations performed only once on each element. such that the sum of the array becomes
K.
Examples:

Input : N = 3, K = 2
A[] = { 1, 1, 1 }
Output : Yes
Explanation
Replace index 0 element with -1. It will sum of array equal to k = 2.

Input : N = 4, K = 5
A[] = { 1, 2, 3, 4 }
Output : Yes

Pre Requisites Dynamic Programming


Approach The idea is to use dynamic programming to solve the problem.
Declare a 2D Boolean array, dp[][], where dp[i][j] states if there is any way to obtain the
sum of the array equal to j using some operations on the firsti elements of the array.
dp[i][j] will be true if the sum is possible else it will be False.

434
Chapter 50. Check if array sum can be made K by three operations on it

Also, it is possible that the intermediate sum of the array is negative, in that case do not
perform any operation and ignore it thus letting the sum be always positive because k is
always positive.
For calculating dp[i][j] we need the values of all states that can make a sum j if we apply an
operation on a[i] and add it to the sum.
Below is the C++ implementation of this approach

/* C++ Program to find if Array can have a sum


   of K by applying three types of possible 
   operations on it */
#include <bits/stdc++.h>
using namespace std;
#define MAX 100
  
// Check if it is possible to achieve a sum with
// three operation allowed.
int check(int i, int sum, int n, int k, int a[],
                               int dp[MAX][MAX])
{
    // If sum is negative.
    if (sum <= 0)
        return false;
  
    // If going out of bound.
    if (i >= n) {
        // If sum is achieved.
        if (sum == k)
            return true;
  
        return false;
    }
  
    // If the current state is not evaluated yet.
    if (dp[i][sum] != -1)
        return dp[i][sum];
  
    // Replacing element with negative value of
    // the element.
    dp[i][sum] = check(i + 1, sum - 2 * a[i], n, 
          k, a, dp) || check(i + 1, sum, n, k, a, dp);
  
    // Substracting index number from the element.
    dp[i][sum] = check(i + 1, sum - (i + 1), n, 
         k, a, dp) || dp[i][sum];
  
    // Adding index number to the element.
    dp[i][sum] = check(i + 1, sum + i + 1, n,

435
Chapter 50. Check if array sum can be made K by three operations on it

                      k, a, dp) || dp[i][sum];


  
    return dp[i][sum];
}
  
// Wrapper Function
bool wrapper(int n, int k, int a[])
{
    int sum = 0;
    for (int i = 0; i < n; i++) 
        sum += a[i];    
  
    int dp[MAX][MAX];
    memset(dp, -1, sizeof(dp));
  
    return check(0, sum, n, k, a, dp);
}
  
// Driver Code
int main()
{
    int a[] = { 1, 2, 3, 4 };
    int n = 4, k = 5;
    (wrapper(n, k, a) ? (cout << "Yes") : (cout << "No"));
    return 0;
}

Output:

Yes

Source

https://www.geeksforgeeks.org/check-if-array-sum-can-be-made-k-by-three-operations-on-it/

436
Chapter 51

Check if it is possible to
transform one string to another

Check if it is possible to transform one string to another - GeeksforGeeks


Given two strings s1 and s2(call letters in uppercase). Check if it is possible to convert s1
to s2 by performing following operations.

1. Make some lowercase letters uppercase.


2. Delete all the lowercase letters.

Examples:

Input : s1 = daBcd s2 = ABC


Output : yes
Explanation : daBcd -> dABCd -> ABC
Covert a and b at index 1 and 3 to
upper case, delete the rest those are
lowercase. We get the string s2.

Input : s1 = argaju s2 = RAJ


Output : yes
Explanation : argaju -> aRgAJu -> RAJ
convert index 1, 3 and 4 to uppercase
and then delete. All lowercase letters

Input : s1 = ABcd s2= BCD


Output : NO

Approach:
Let DPi, j be 1 if it is possible to convert 1st i characters of s1 to j characters of s2, else
DPi, j =0. Close observations gives us two conditions to deal with.

437
Chapter 51. Check if it is possible to transform one string to another

Initially DP0, 0 =1, if DPi, j =1 then it is possible to check for next sets using following
conditions.
1. If s1[i] in upper case is equal to s2[j] then it is possible to convert i+1 characters of s1 to
j+1 characters of s2, hence DPi+1, j+1 =1.
2. If s1[i] is in lower case, then it is possible to delete that element and hence i+1 characters
can be converted to j characters of s2. Hence DPi+1, j =1.
If DPn, m =1, then it is possible to convert s1 to s2 by following conditions.
Below is the CPP illustration of the above approach.

C++

// cpp program to check if a string can


// be converted to another string by
// performing operations
#include <bits/stdc++.h>
using namespace std;
  
// function to check if a string can be
// converted to  another string by
// performing following operations
bool check(string s1, string s2)
{
    // calculates length
    int n = s1.length();
    int m = s2.length();
  
    bool dp[n + 1][m + 1];
    for (int i = 0; i <= n; i++) {
        for (int j = 0; j <= m; j++) {
            dp[i][j] = false;
        }
    }
    // mark 1st position as true
    dp[0][0] = true;
  
    // traverese for all DPi, j
    for (int i = 0; i < s1.length(); i++) {
        for (int j = 0; j <= s2.length(); j++) {
  
            // if possible for to convert i 
            // characters of s1 to j characters
            // of s2
            if (dp[i][j]) {
  
                // if upper_case(s1[i])==s2[j]
                // is same

438
Chapter 51. Check if it is possible to transform one string to another

                if (j < s2.length() && 


                    (toupper(s1[i]) == s2[j]))
                    dp[i + 1][j + 1] = true;
  
                // if not upper then deletion is 
                // possible
                if (!isupper(s1[i]))
                    dp[i + 1][j] = true;
            }
        }
    }
  
    return (dp[n][m]);
}
  
// driver code
int main()
{
    string s1 = "daBcd";
    string s2 = "ABC";
  
    if (check(s1, s2))
        cout << "YES";
    else
        cout << "NO";
  
    return 0;
}

Java

// Java program to check if a string can


// be converted to another string by
// performing operations
import java.io.*;
  
class GFG {
      
    // function to check if a string can be
    // converted to another string by
    // performing following operations
    static boolean check(String s1, String s2)
    {
        // calculates length
        int n = s1.length();
        int m = s2.length();
      
        boolean dp[][]=new boolean[n + 1][m + 1];

439
Chapter 51. Check if it is possible to transform one string to another

        for (int i = 0; i <= n; i++) 


        {
            for (int j = 0; j <= m; j++)
            {
                dp[i][j] = false;
            }
        }
        // mark 1st position as true
        dp[0][0] = true;
      
        // traverese for all DPi, j
        for (int i = 0; i < s1.length(); i++)
        {
            for (int j = 0; j <= s2.length(); j++)
            {
      
                // if possible for to convert i 
                // characters of s1 to j characters
                // of s2
                if (dp[i][j]) {
      
                    // if upper_case(s1[i])==s2[j]
                    // is same
                    if (j < s2.length() && 
                        (Character.toUpperCase(s1.charAt(i)) == s2.charAt(j)))
                        dp[i + 1][j + 1] = true;
      
                    // if not upper then deletion is 
                    // possible
                    if (!Character.isUpperCase(s1.charAt(i)))
                        dp[i + 1][j] = true;
                }
            }
        }
      
        return (dp[n][m]);
    }
      
    // driver code
    public static void main(String args[])
    {
        String s1 = "daBcd";
        String s2 = "ABC";
      
        if (check(s1, s2))
            System.out.println("YES");
        else
            System.out.println("NO");

440
Chapter 51. Check if it is possible to transform one string to another

      
    }
}
  
// This code is contributed by Nikita Tiwari.

Output:

YES

Source

https://www.geeksforgeeks.org/check-possible-transform-one-string-another/

441
Chapter 52

Check if possible to cross the


matrix with given power

Check if possible to cross the matrix with given power - GeeksforGeeks


Given a matrix of N X M, each cell consist of an integer. We have initial power of K
and we are allowed to move right, down or diagonal. When we move to any cell, we absorb
mat[i][j] value and loose that much amount from your power. If our power became less than
0 at any time, we cannot move further from that point. Now, our task is to find if there
is any path from (1, 1) to (n, m) that we can cover with power k. If possible, output the
maximum value we can absorb, else if there is no path print “-1”.
Examples :

Input : N = 3, M = 3, K = 7
mat[][] = { { 2, 3, 1 },
{ 6, 1, 9 },
{ 8, 2, 3 } };
Output : 6
Path (1, 1) -> (2, 2) -> (3, 3) to complete
journey to absorb 6 value.

Input : N = 3, M = 4, K = 9
mat[][] = {
{ 2, 3, 4, 1 },
{ 6, 5, 5, 3 },
{ 5, 2, 3, 4 }
};
Output : -1

The idea is to use Dynamic Programming to solve the problem.


Approach :

442
Chapter 52. Check if possible to cross the matrix with given power

• Declare a boolean 3D matrix, say dp[ ][ ][ ], with N*M*(K+1) dimension such that
dp[ i ][ j ][ k ] is true if it possible to reach the square in the ith row and jth column
with exactly k value collected so far.
• We can write the recurrence dp[ i ][ j ][ k ] = true if either

dp[i-1][j][k-mat[i][j]] or
dp[i][j-1][k-mat[i][j]] or
dp[i-1][j-1][k-mat[i][j]]

i.e the three possible moves we could have.


• We have base case dp[0][0][0] be true.
• The answer is -2 if dp[n-1][m-1][k] is false for all k between 0 and k+1.

• Otherwise, the answer is the maximum k such that dp[n-1][m-1][k] is true.

Below is C++ implementation of this approach :


CPP

// CPP program to find if it is possible to cross


// the matrix with given power
#include <bits/stdc++.h>
#define N 105
#define R 3
#define C 4
using namespace std;
  
int maximumValue(int n, int m, int p, int grid[R][C])
{
    bool dp[N][N][N];
  
    // Initializing array dp with false value.
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            for (int k = 0; k < N; k++)
                dp[i][j][k] = false;
        }
    }
  
    // For each value of dp[i][j][k]
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            for (int k = grid[i][j]; k <= p; k++) {
  
                // For first cell and for each value of k
                if (i == 0 && j == 0) {

443
Chapter 52. Check if possible to cross the matrix with given power

                    if (k == grid[i][j])
                        dp[i][j][k] = true;
                }
  
                // For first cell of each row
                else if (i == 0) {
                    dp[i][j][k] = (dp[i][j][k] || 
                        dp[i][j - 1][k - grid[i][j]]);
                }
  
                // For first cell of each column
                else if (j == 0) {
                    dp[i][j][k] = (dp[i][j][k] ||
                        dp[i - 1][j][k - grid[i][j]]);
                }
  
                // For rest of the cell
                else {
  
                    // Down movement.
                    dp[i][j][k] = (dp[i][j][k] ||
                        dp[i][j - 1][k - grid[i][j]]);
  
                    // Right movement.
                    dp[i][j][k] = (dp[i][j][k] ||
                        dp[i - 1][j][k - grid[i][j]]);
  
                    // Diagonal movement.
                    dp[i][j][k] = (dp[i][j][k] ||
                        dp[i - 1][j - 1][k - grid[i][j]]);
                }
            }
        }
    }
  
    // Finding maximum k.
    int ans = 0;
    for (ans = k; ans >= 0; ans--)
        if (dp[n - 1][m - 1][ans])
            break;
  
    return ans;
}
  
// Driver Code
int main()
{
    int n = 3, m = 4, p = 9;

444
Chapter 52. Check if possible to cross the matrix with given power

    int grid[R][C] = {
        { 2, 3, 4, 1 },
        { 6, 5, 5, 3 },
        { 5, 2, 3, 4 }
    };
  
    cout << maximumValue(n, m, p, grid) << endl;
    return 0;
}

Java

// Java program to find if it 


// is possible to cross the matrix
// with given power
class GFG
{
      
static final int N = 105;
static final int R = 3;
static final int C = 4;
  
static int maximumValue(int n, int m, int p,
                                int grid[][])
{
    boolean dp[][][] = new boolean[N][N][N];
    int i, j, k;
  
    // Initializing array dp with false value.
    for (i = 0; i < N; i++) {
        for (j = 0; j < N; j++) {
            for (k = 0; k < N; k++)
                dp[i][j][k] = false;
        }
    }
  
    // For each value of dp[i][j][k]
    for (i = 0; i < n; i++) {
        for (j = 0; j < m; j++) {
            for (k = grid[i][j]; k <= p; k++) {
  
                // For first cell and for 
                // each value of k
                if (i == 0 && j == 0) {
                    if (k == grid[i][j])
                        dp[i][j][k] = true;
                }
  

445
Chapter 52. Check if possible to cross the matrix with given power

                // For first cell of each row


                else if (i == 0) {
                    dp[i][j][k] = (dp[i][j][k] || 
                        dp[i][j - 1][k - grid[i][j]]);
                }
  
                // For first cell of each column
                else if (j == 0) {
                    dp[i][j][k] = (dp[i][j][k] ||
                        dp[i - 1][j][k - grid[i][j]]);
                }
  
                // For rest of the cell
                else {
  
                    // Down movement.
                    dp[i][j][k] = (dp[i][j][k] ||
                        dp[i][j - 1][k - grid[i][j]]);
  
                    // Right movement.
                    dp[i][j][k] = (dp[i][j][k] ||
                        dp[i - 1][j][k - grid[i][j]]);
  
                    // Diagonal movement.
                    dp[i][j][k] = (dp[i][j][k] ||
                        dp[i - 1][j - 1][k - grid[i][j]]);
                }
            }
        }
    }
    k = p;
      
    // Finding maximum k.
    int ans = 0;
    for (ans = k; ans >= 0; ans--)
        if (dp[n - 1][m - 1][ans])
            break;
  
    return ans;
}
  
  
// Driver code 
public static void main (String[] args)
{
    int n = 3, m = 4, p = 9;
    int grid[][] = {{ 2, 3, 4, 1 },
                    { 6, 5, 5, 3 },

446
Chapter 52. Check if possible to cross the matrix with given power

                    { 5, 2, 3, 4 }};
  
    System.out.println(maximumValue(n, m, p, grid));
}
}
  
// This code is contributed by Anant Agarwal.

C#

// C# program to find if it
// is possible to cross the matrix
// with given power
using System;
  
class GFG {
  
    static int N = 105;
    // static int R = 3;
    // static int C = 4;
  
    static int maximumValue(int n, int m, int p,
                                   int[, ] grid)
    {
        bool[,, ] dp = new bool[N, N, N];
        int i, j, k;
  
        // Initializing array dp with false value.
        for (i = 0; i < N; i++) {
            for (j = 0; j < N; j++) {
                for (k = 0; k < N; k++)
                    dp[i, j, k] = false;
            }
        }
  
        // For each value of dp[i][j][k]
        for (i = 0; i < n; i++) {
            for (j = 0; j < m; j++) {
                for (k = grid[i, j]; k <= p; k++) {
  
                    // For first cell and for
                    // each value of k
                    if (i == 0 && j == 0) {
                        if (k == grid[i, j])
                            dp[i, j, k] = true;
                    }
  
                    // For first cell of each row

447
Chapter 52. Check if possible to cross the matrix with given power

                    else if (i == 0) {
                        dp[i, j, k] = (dp[i, j, k] || 
                        dp[i, j - 1, k - grid[i, j]]);
                    }
  
                    // For first cell of each column
                    else if (j == 0) {
                        dp[i, j, k] = (dp[i, j, k] || 
                        dp[i - 1, j, k - grid[i, j]]);
                    }
  
                    // For rest of the cell
                    else {
  
                        // Down movement.
                        dp[i, j, k] = (dp[i, j, k] || 
                        dp[i, j - 1, k - grid[i, j]]);
  
                        // Right movement.
                        dp[i, j, k] = (dp[i, j, k] || 
                        dp[i - 1, j, k - grid[i, j]]);
  
                        // Diagonal movement.
                        dp[i, j, k] = (dp[i, j, k] ||
                        dp[i - 1, j - 1, k - grid[i, j]]);
                    }
                }
            }
        }
        k = p;
  
        // Finding maximum k.
        int ans = 0;
        for (ans = k; ans >= 0; ans--)
            if (dp[n - 1, m - 1, ans])
                break;
  
        return ans;
    }
  
    // Driver code
    public static void Main()
    {
        int n = 3, m = 4, p = 9;
        int[, ] grid = { { 2, 3, 4, 1 },
                         { 6, 5, 5, 3 },
                         { 5, 2, 3, 4 } };
  

448
Chapter 52. Check if possible to cross the matrix with given power

        Console.WriteLine(maximumValue(n, m, p, grid));
    }
}
  
// This code is contributed by vt_m.

Output:

-1

Time Complexity: O(n3 )

Source

https://www.geeksforgeeks.org/check-possible-cross-matrix-given-power/

449
Chapter 53

Check whether row or column


swaps produce maximum size
binary sub-matrix with all 1s

Check whether row or column swaps produce maximum size binary sub-matrix with all 1s -
GeeksforGeeks
Given a binary matrix, the task is to find whether row swaps or column swaps give maximum
size sub-matrix with all 1’s. In a row swap, we are allowed to swap any two rows. In a
column swap we are allowed to swap any two columns. Output “Row Swap” or “Column
Swap” and the maximum size.
Examples:

Input : 1 1 1
1 0 1
Output : Column Swap
4
By swapping column 1 and column 2(0-based indexing),
index (0, 0) to (1, 1) makes the largest binary
sub-matrix.

Input : 0 0 0
1 1 0
1 1 0
0 0 0
1 1 0
Output : Row Swap
6

Input : 1 1 0

450
Chapter 53. Check whether row or column swaps produce maximum size binary sub-matrix
with all 1s

0 0 0
0 0 0
1 1 0
1 1 0
0 0 0
1 1 0
Output : Row Swap
8

The idea is to find both row swap and column swap maximum size binary submatrix and
compare.
To find the maximum sized binary sub-matrix with row swaps allowed, make a 2-D array,
say dp[i][j]. Each value of dp[i][j] contains the number of consecutive 1s on right side of (i,j)
in i-th row. Now, store each column in the 1-D temporary array one by one, say b[] and
sort, and find maximum b[i] * (n – i), since b[i] is indicating the sub-matrix width and (n –
i) is sub-matrix height.
Similarly, to find the maximum size binary sub-matrix with column swap allowed, find
dp[i][j], where each value contains the number of consecutive 1 below the (i, j) in j-th
column. Similarly, store each row in the 1-D temporary array one by one, say b[] and sort.
Find maximum b[i] * (m – i), since b[i] is indicating the submatrix height and (n – i) is
submatrix width.
Below is C++ implementation of this approach:

// C++ program to find maximum binary sub-matrix


// with row swaps and column swaps.
#include <bits/stdc++.h>
#define R 5
#define C 3
using namespace std;
  
// Precompute the number of consecutive 1 below the
// (i, j) in j-th column and the number of consecutive 1s
// on right side of (i, j) in i-th row.
void precompute(int mat[R][C], int ryt[][C + 2],
                               int dwn[R + 2][C + 2])
{
    // Travesing the 2d matrix from top-right.
    for (int j=C-1; j>=0; j--)
    {
        for (int i=0; i<R; ++i)
        {
            // If (i,j) contain 0, do nothing
            if (mat[i][j] == 0)
                ryt[i][j] = 0;
  
            // Counting consecutive 1 on right side

451
Chapter 53. Check whether row or column swaps produce maximum size binary sub-matrix
with all 1s

            else
                ryt[i][j] = ryt[i][j + 1] + 1;
        }
    }
  
  
    // Travesing the 2d matrix from bottom-left.
    for (int i = R - 1; i >= 0; i--)
    {
        for (int j = 0; j < C; ++j)
        {
            // If (i,j) contain 0, do nothing
            if (mat[i][j] == 0)
                dwn[i][j] = 0;
  
            // Counting consecutive 1 down to (i,j).
            else
                dwn[i][j] = dwn[i + 1][j] + 1;
        }
    }
}
  
// Return maximum size submatrix with row swap allowed.
int solveRowSwap(int ryt[R + 2][C + 2])
{
    int b[R] = { 0 }, ans = 0;
  
    for (int j=0; j<C; j++)
    {
        // Copying the column
        for (int i=0; i<R; i++)
            b[i] = ryt[i][j];
  
        // Sort the copied array
        sort(b, b + R);
  
        // Find maximum submatrix size.
        for (int i = 0; i < R; ++i)
            ans = max(ans, b[i] * (R - i));
    }
  
    return ans;
}
  
// Return maximum size submatrix with column
// swap allowed.
int solveColumnSwap(int dwn[R + 2][C + 2])
{

452
Chapter 53. Check whether row or column swaps produce maximum size binary sub-matrix
with all 1s

    int b[C] = { 0 }, ans = 0;


  
    for (int i = 0; i < R; ++i)
    {
        // Copying the row.
        for (int j = 0; j < C; ++j)
            b[j] = dwn[i][j];
  
        // Sort the copied array
        sort(b, b + C);
  
        // Find maximum submatrix size.
        for (int i = 0; i < C; ++i)
            ans = max(ans, b[i] * (C - i));
    }
  
    return ans;
}
  
void findMax1s(int mat[R][C])
{
    int ryt[R + 2][C + 2], dwn[R + 2][C + 2];
    memset(ryt, 0, sizeof ryt);
    memset(dwn, 0, sizeof dwn);
  
    precompute(mat, ryt, dwn);
  
    // Solving for row swap and column swap
    int rswap = solveRowSwap(ryt);
    int cswap = solveColumnSwap(dwn);
  
    // Comparing both.
    (rswap > cswap)? (cout << "Row Swap\n" << rswap << endl):
                     (cout << "Column Swap\n" << cswap << endl);
}
  
// Driven Program
int main()
{
    int mat[R][C] = {{ 0, 0, 0 },
                     { 1, 1, 0 },
                     { 1, 1, 0 },
                     { 0, 0, 0 },
                     { 1, 1, 0 }};
  
    findMax1s(mat);
    return 0;
}

453
Chapter 53. Check whether row or column swaps produce maximum size binary sub-matrix
with all 1s

Output:

Row Swap
6

Source

https://www.geeksforgeeks.org/check-whether-row-column-swap-produces-maximum-size-binary-sub-matrix-1s/

454
Chapter 54

Choice of Area

Choice of Area - GeeksforGeeks


Consider a game, in which you have two types of powers, A and B and there are 3 types
of Areas X, Y and Z. Every second you have to switch between these areas, each area has
specific properties by which your power A and power B increase or decrease. We need to
keep choosing areas in such a way that our survival time is maximized. Survival time ends
when any of the powers, A or B reaches less than 0.
Examples:

Initial value of Power A = 20


Initial value of Power B = 8

Area X (3, 2) : If you step into Area X,


A increases by 3,
B increases by 2

Area Y (-5, -10) : If you step into Area Y,


A decreases by 5,
B decreases by 10

Area Z (-20, 5) : If you step into Area Z,


A decreases by 20,
B increases by 5

It is possible to choose any area in our first step.


We can survive at max 5 unit of time by following
these choice of areas :
X -> Z -> X -> Y -> X

This problem can be solved using recursion, after each time unit we can go to any of the
area but we will choose that area which ultimately leads to maximum survival time. As

455
Chapter 54. Choice of Area

recursion can lead to solving same subproblem many time, we will memoize the result on
basis of power A and B, if we reach to same pair of power A and B, we won’t solve it again
instead we will take the previously calculated result.
Given below is the simple implementation of above approach.

CPP

//  C++ code to get maximum survival time


#include <bits/stdc++.h>
using namespace std;
  
//  structure to represent an area
struct area
{
    //  increment or decrement in A and B
    int a, b;
    area(int a, int b) : a(a), b(b)
    {}
};
  
//  Utility method to get maximum of 3 integers
int max(int a, int b, int c)
{
    return max(a, max(b, c));
}
  
//  Utility method to get maximum survival time
int maxSurvival(int A, int B, area X, area Y, area Z,
                int last, map<pair<int, int>, int>& memo)
{
    //  if any of A or B is less than 0, return 0
    if (A <= 0 || B <= 0)
        return 0;
    pair<int, int> cur = make_pair(A, B);
  
    //  if already calculated, return calculated value
    if (memo.find(cur) != memo.end())
        return memo[cur];
  
    int temp;
  
    //  step to areas on basis of last chose area
    switch(last)
    {
    case 1:
        temp = 1 + max(maxSurvival(A + Y.a, B + Y.b,
                                   X, Y, Z, 2, memo),
                       maxSurvival(A + Z.a, B + Z.b,

456
Chapter 54. Choice of Area

                                  X, Y, Z, 3, memo));
        break;
    case 2:
        temp = 1 + max(maxSurvival(A + X.a, B + X.b,
                                  X, Y, Z, 1, memo),
                       maxSurvival(A + Z.a, B + Z.b,
                                  X, Y, Z, 3, memo));
        break;
    case 3:
        temp = 1 + max(maxSurvival(A + X.a, B + X.b,
                                  X, Y, Z, 1, memo),
                       maxSurvival(A + Y.a, B + Y.b,
                                  X, Y, Z, 2, memo));
        break;
    }
  
    //  store the result into map
    memo[cur] = temp;
  
    return temp;
}
  
//  method returns maximum survival time
int getMaxSurvivalTime(int A, int B, area X, area Y, area Z)
{
    if (A <= 0 || B <= 0)
        return 0;
    map< pair<int, int>, int > memo;
  
    //  At first, we can step into any of the area
    return
        max(maxSurvival(A + X.a, B + X.b, X, Y, Z, 1, memo),
            maxSurvival(A + Y.a, B + Y.b, X, Y, Z, 2, memo),
            maxSurvival(A + Z.a, B + Z.b, X, Y, Z, 3, memo));
}
  
//  Driver code to test above method
int main()
{
    area X(3, 2);
    area Y(-5, -10);
    area Z(-20, 5);
  
    int A = 20;
    int B = 8;
    cout << getMaxSurvivalTime(A, B, X, Y, Z);
  
    return 0;

457
Chapter 54. Choice of Area

Python3

# Python code to get maximum survival time


  
# Class to represent an area
class area:
    def __init__(self, a, b):
        self.a = a
        self.b = b
  
# Utility method to get maximum survival time
def maxSurvival(A, B, X, Y, Z, last, memo):
    # if any of A or B is less than 0, return 0
    if (A <= 0 or B <= 0):
        return 0
    cur = area(A, B)
  
    # if already calculated, return calculated value
    for ele in memo.keys():
        if (cur.a == ele.a and cur.b == ele.b):
            return memo[ele]
  
    # step to areas on basis of last chosen area
    if (last == 1):
        temp = 1 + max(maxSurvival(A + Y.a, B + Y.b,
                                   X, Y, Z, 2, memo),
                       maxSurvival(A + Z.a, B + Z.b,
                                   X, Y, Z, 3, memo))
    elif (last == 2):
        temp = 1 + max(maxSurvival(A + X.a, B + X.b,
                                   X, Y, Z, 1, memo),
               maxSurvival(A + Z.a, B + Z.b,
                   X, Y, Z, 3, memo))
    elif (last == 3):
        temp = 1 + max(maxSurvival(A + X.a, B + X.b,
                   X, Y, Z, 1, memo),
               maxSurvival(A + Y.a, B + Y.b,
                   X, Y, Z, 2, memo))
  
    # store the result into map
    memo[cur] = temp
  
    return temp
  
# method returns maximum survival time
def getMaxSurvivalTime(A, B, X, Y, Z):

458
Chapter 54. Choice of Area

    if (A <= 0 or B <= 0):


        return 0
    memo = dict()
  
    # At first, we can step into any of the area
    return max(maxSurvival(A + X.a, B + X.b, X, Y, Z, 1, memo),
           maxSurvival(A + Y.a, B + Y.b, X, Y, Z, 2, memo),
           maxSurvival(A + Z.a, B + Z.b, X, Y, Z, 3, memo))
  
# Driver code to test above method
X = area(3, 2)
Y = area(-5, -10)
Z = area(-20, 5)
  
A = 20
B = 8
print(getMaxSurvivalTime(A, B, X, Y, Z))
  
# This code is contributed by Soumen Ghosh.

Output:

Source

https://www.geeksforgeeks.org/game-theory-choice-area/

459
Chapter 55

Choose maximum weight with


given weight and value ratio

Choose maximum weight with given weight and value ratio - GeeksforGeeks
Given weights and values of n items and a value k. We need to choose a subset of these
items in such a way that ratio of the sum of weight and sum of values of chosen items is K
and sum of weight is maximum among all possible subset choices.

Input : weight[] = [4, 8, 9]


values[] = [2, 4, 6]
K = 2
Output : 12
We can choose only first and second item only,
because (4 + 8) / (2 + 4) = 2 which is equal to K
we can't include third item with weight 9 because
then ratio condition won't be satisfied so result
will be (4 + 8) = 12

We can solve this problem using dynamic programming. We can make a 2 state dp where
dp(i, j) will store maximum possible sum of weights under given conditions when total items
are N and required ratio is K.
Now in two states of dp, we will store the last item chosen and the difference between sum
of weight and sum of values. We will multiply item values by K so that second state of dp
will actually store (sum of weight – K*(sum of values)) for chosen items. Now we can see
that our answer will be stored in dp(N-1, 0) because as last item is (N-1)th so all items
are being considered and difference between sum of weight and K*(sum of values) is 0 that
means sum of weight and sum of values has a ratio K.
After defining above dp state we can write transition among states simply as shown below,

460
Chapter 55. Choose maximum weight with given weight and value ratio

dp(last, diff) = max (dp(last - 1, diff),


dp(last-1, diff + wt[last] - val[last]*K))

dp(last – 1, diff) represents the condition when current


item is not chosen and
dp(last – 1, diff + wt[last] – val[last] * K)) represents
the condition when current item is chosen so difference
is updated with weight and value of current item.

In below code a top-down approach is used for solving this dynamic programming and for
storing dp states a map is used because the difference can be negative also and the 2D array
can create problem in that case and special care need to be taken.
C++

// C++ program to choose item with maximum


// sum of weight under given constraint
#include <bits/stdc++.h>
using namespace std;
  
// memoized recursive method to return maximum
// weight with K as ratio of weight and values
int maxWeightRec(int wt[], int val[], int K,
                  map<pair<int, int>, int>& mp,
                            int last, int diff)
{
    //  base cases : if no item is remaining
    if (last == -1)
    {
        if (diff == 0)
            return 0;
        else
            return INT_MIN;
    }
  
    // first make pair with last chosen item and
    // difference between weight and values
    pair<int, int> tmp = make_pair(last, diff);
    if (mp.find(tmp) != mp.end())
        return mp[tmp];
  
    /*  choose maximum value from following two
        1) not selecting the current item and calling
           recursively
        2) selection current item, including the weight
           and updating the difference before calling
           recurively */
    mp[tmp] = max(maxWeightRec(wt, val, K, mp, last - 1, diff),

461
Chapter 55. Choose maximum weight with given weight and value ratio

                   wt[last] + maxWeightRec(wt, val, K, mp,


                   last - 1, diff + wt[last] - val[last] * K));
  
    return mp[tmp];
}
  
// method returns maximum sum of weight with K
// as ration of sum of weight and their values
int maxWeight(int wt[], int val[], int K, int N)
{
    map<pair<int, int>, int> mp;
    return maxWeightRec(wt, val, K, mp, N - 1, 0);
}
  
//  Driver code to test above methods
int main()
{
    int wt[] = {4, 8, 9};
    int val[] = {2, 4, 6};
    int N = sizeof(wt) / sizeof(int);
    int K = 2;
  
    cout << maxWeight(wt, val, K, N);
    return 0;
}

Java

// Java program to choose item with maximum


// sum of weight under given constraint
  
import java.awt.Point;
import java.util.HashMap;
  
class Test
{
    // memoized recursive method to return maximum
    // weight with K as ratio of weight and values
    static int maxWeightRec(int wt[], int val[], int K,
                      HashMap<Point, Integer> hm,
                                int last, int diff)
    {
        //  base cases : if no item is remaining
        if (last == -1)
        {
            if (diff == 0)
                return 0;
            else

462
Chapter 55. Choose maximum weight with given weight and value ratio

                return Integer.MIN_VALUE;
        }
       
        // first make pair with last chosen item and
        // difference between weight and values
        Point tmp = new Point(last, diff);
        if (hm.containsKey(tmp))
            return hm.get(tmp);
       
        /*  choose maximum value from following two
            1) not selecting the current item and calling
               recursively
            2) selection current item, including the weight
               and updating the difference before calling
               recursively */
       hm.put(tmp,Math.max(maxWeightRec(wt, val, K, hm, last - 1, diff),
                       wt[last] + maxWeightRec(wt, val, K, hm,
                       last - 1, diff + wt[last] - val[last] * K)));
       
        return hm.get(tmp);
    }
       
    // method returns maximum sum of weight with K
    // as ration of sum of weight and their values
    static int maxWeight(int wt[], int val[], int K, int N)
    {
        HashMap<Point, Integer> hm = new HashMap<>();
        return maxWeightRec(wt, val, K, hm, N - 1, 0);
    }
      
    // Driver method
    public static void main(String args[])
    {
        int wt[] = {4, 8, 9};
        int val[] = {2, 4, 6};
          
        int K = 2;
       
        System.out.println(maxWeight(wt, val, K, wt.length));
    }
}
// This code is contributed by Gaurav Miglani

Output:

12

463
Chapter 55. Choose maximum weight with given weight and value ratio

Source

https://www.geeksforgeeks.org/choose-maximum-weight-given-weight-value-ratio/

464
Chapter 56

Clustering/Partitioning an
array such that sum of square
differences is minimum

Clustering/Partitioning an array such that sum of square differences is minimum - Geeks-


forGeeks
Given an array of n numbers and a number k. We need to divide the array into k par-
titions (clusters) of same or different length. For a given k, there can be one or more

ways to make clusters (partitions). We define a function Cost(i) for the cluster, as
the square of the difference between its first and last element. If the current cluster is

, where is the length of

current cluster, then .


Amongst all the possible kinds of partitions, we have to find the partition that will minimize
the function,

Examples :

Input : arr[] = {1, 5, 8, 10}


k = 2
Output : 20
Explanation :

465
Chapter 56. Clustering/Partitioning an array such that sum of square differences is
minimum

Consider clustering 4 elements 1, 5, 8, 10


into 2 clusters. There are three options:
1. S1 = 1, S2 = 5, 8, 10, with total cost
+ = 25.
2. S1 = 1, 5, S2 = 8, 10, with total cost
+ = 20.
3. S1 = 1, 5, 8, S2 = 10, with total cost
+ = 49.
So, the optimal clustering is the second one,
so the output of the above problem is 20.

Input : arr[] = {5, 8, 1, 10}


k = 3
Output : 20
Explanation :
The three partitions are {5, 8}, {1} and {10}

To solve the problem, we assume that we have k slabs. We have to insert them in some k
different positions in the array, which will give us the required partition scheme, and the
one having minimum value for f(x) will be the answer.
Naive solution:
If we solve the above problem by the naive method, we would simply take all the possibilities
and compute the minimum.

C++

// C++ program to find minimum cost k partitions


// of array.
#include<iostream>
using namespace std;
  
// Initialize answer as infinite.
const int inf = 1000000000;
int ans = inf;
  
// function to generate all possible answers.
// and comute minimum of all costs.
// i   --> is index of previous partition
// par --> is current number of partitions
// a[] and n --> Input array and its size
// current_ans --> Cost of partitions made so far.
void solve(int i, int par, int a[], int n,
                  int k, int current_ans)
{
    // If number of partitions is more than k
    if (par > k)

466
Chapter 56. Clustering/Partitioning an array such that sum of square differences is
minimum

        return;
  
    // If we have mad k partitions and have
    // reached last element
    if (par==k && i==n-1)
    {
        ans = min(ans, current_ans);
        return;
    }
  
    // 1) Partition array at different points
    // 2) For every point, increase count of 
    //    partitions, "par" by 1.
    // 3) Before recursive call, add cost of 
    //    the partition to current_ans
    for (int j=i+1; j<n; j++)
        solve(j, par+1, a, n, k, current_ans +
                  (a[j]-a[i+1])*(a[j]-a[i+1]));
}
  
// Driver code
int main()
{
    int k = 2;
    int a[] = {1, 5, 8, 10};
    int n = sizeof(a)/sizeof(a[0]);
    solve(-1, 0, a, n, k, 0);
    cout << ans << endl;
    return 0;
}

Java

// Java program to find minimum cost k partitions


// of array.
import java.io.*;
  
class GFG
{
    // Initialize answer as infinite.
    static int inf = 1000000000;
    static int ans = inf;
      
    // function to generate all possible answers.
    // and comute minimum of all costs.
    // i --> is index of previous partition
    // par --> is current number of partitions
    // a[] and n --> Input array and its size

467
Chapter 56. Clustering/Partitioning an array such that sum of square differences is
minimum

    // current_ans --> Cost of partitions made so far.


    static void solve(int i, int par, int a[], int n,
                               int k, int current_ans)
    {
        // If number of partitions is more than k
        if (par > k)
            return;
      
        // If we have mad k partitions and have
        // reached last element
        if (par == k && i == n - 1)
        {
            ans = Math.min(ans, current_ans);
            return;
        }
      
        // 1) Partition array at different points
        // 2) For every point, increase count of 
        // partitions, "par" by 1.
        // 3) Before recursive call, add cost of 
        // the partition to current_ans
        for (int j = i + 1; j < n; j++)
            solve(j, par + 1, a, n, k, current_ans +
                 (a[j] - a[i + 1]) * (a[j] - a[i + 1]));
    }
      
    // Driver code
    public static void main (String[] args) 
    {
        int k = 2;
        int a[] = {1, 5, 8, 10};
        int n = a.length;
        solve(-1, 0, a, n, k, 0);
        System.out.println(ans);
          
    }

  
// This code is contributed by vt_m.

C#

// C# program to find minimum


// cost k partitions of array.
using System;
  
class GFG
{

468
Chapter 56. Clustering/Partitioning an array such that sum of square differences is
minimum

    // Initialize answer as infinite.


    static int inf = 1000000000;
    static int ans = inf;
      
    // function to generate all possible answers.
    // and comute minimum of all costs.
    // i --> is index of previous partition
    // par --> is current number of partitions
    // a[] and n --> Input array and its size
    // current_ans --> Cost of partitions made so far.
    static void solve(int i, int par, int []a,
                      int n, int k, int current_ans)
    {
        // If number of partitions is more than k
        if (par > k)
            return;
      
        // If we have mad k partitions and
        // have reached last element
        if (par == k && i == n - 1)
        {
            ans = Math.Min(ans, current_ans);
            return;
        }
      
        // 1) Partition array at different points
        // 2) For every point, increase count of 
        // partitions, "par" by 1.
        // 3) Before recursive call, add cost of 
        // the partition to current_ans
        for (int j = i + 1; j < n; j++)
            solve(j, par + 1, a, n, k, current_ans +
                 (a[j] - a[i + 1]) * (a[j] - a[i + 1]));
    }
      
    // Driver code
    public static void Main () 
    {
        int k = 2;
        int []a = {1, 5, 8, 10};
        int n = a.Length;
        solve(-1, 0, a, n, k, 0);
        Console.Write(ans);
    }

  
// This code is contributed by nitin mittal.

469
Chapter 56. Clustering/Partitioning an array such that sum of square differences is
minimum

Output:

20

Time Complexity: Its clear that the above algorithm has Time Complexity of .

Dynamic Programming:
We create a table dp[n+1][k+1] table and initialize all values as infinite.

dp[i][j] stores optimal partition cost


for arr[0..i-1] and j partitions.

Let us compute the value of dp[i][j]. we take an index m, such that m < i, and put a partition
next to that position such that there is no slab in between the indices i and m. It can be
seen simply that answer to the current scenario is dp[m][j-1] + (a[i-1]-a[m])*(a[i-1]-a[m]),

where the first term signifies the minimum f(x) till the element with j-1 partitions
and the second one signifies the cost of current cluster. So we will take the minimum of all
the possible indices m and dp[i][j] will be assigned the minimum amongst them.
C++

// C++ program to find minimum cost k partitions


// of array.
#include<iostream>
using namespace std;
const int inf = 1000000000;
  
// Returns minimum cost of partitioning a[] in
// k clusters.
int minCost(int a[], int n, int k)
{
    // Create a dp[][] table and initialize
    // all values as infinite. dp[i][j] is
    // going to store optimal partition cost
    // for arr[0..i-1] and j partitions
    int dp[n+1][k+1];
    for (int i=0; i<=n; i++)
        for (int j=0;j<=k;j++)
            dp[i][j] = inf;
  
    // Fill dp[][] in bottom up manner
    dp[0][0] = 0;

470
Chapter 56. Clustering/Partitioning an array such that sum of square differences is
minimum

  
    // Current ending position (After i-th
    // iteration result for a[0..i-1] is computed.
    for (int i=1;i<=n;i++)
  
        // j is number of partitions
        for (int j=1;j<=k;j++)
  
            // Picking previous partition for
            // current i.
            for (int m=i-1;m>=0;m--)
                dp[i][j] = min(dp[i][j], dp[m][j-1] +
                          (a[i-1]-a[m])*(a[i-1]-a[m]));
  
  
    return dp[n][k];
}
  
// Driver code
int main()
{
    int k = 2;
    int a[] = {1, 5, 8, 10};
    int n = sizeof(a)/sizeof(a[0]);
    cout << minCost(a, n, k) << endl;
    return 0;
}

Java

// Java program to find minimum cost 


// k partitions of array.
import java.io.*;
  
class GFG 
{
    static int inf = 1000000000;
      
    // Returns minimum cost of partitioning 
    // a[] in k clusters.
    static int minCost(int a[], int n, int k)
    {
        // Create a dp[][] table and initialize
        // all values as infinite. dp[i][j] is
        // going to store optimal partition cost
        // for arr[0..i-1] and j partitions
        int dp[][] = new int[n + 1][k + 1];
        for (int i = 0; i <= n; i++)

471
Chapter 56. Clustering/Partitioning an array such that sum of square differences is
minimum

            for (int j = 0; j <= k; j++)


                dp[i][j] = inf;
      
        // Fill dp[][] in bottom up manner
        dp[0][0] = 0;
      
        // Current ending position (After i-th
        // iteration result for a[0..i-1] is computed.
        for (int i = 1; i <= n; i++)
      
            // j is number of partitions
            for (int j = 1; j <= k; j++)
      
                // Picking previous partition for
                // current i.
                for (int m = i - 1; m >= 0; m--)
                    dp[i][j] = Math.min(dp[i][j], dp[m][j - 1] +
                              (a[i - 1] - a[m]) * (a[i - 1] - a[m]));
      
      
        return dp[n][k];
    }
      
    // Driver code
    public static void main (String[] args) 
    {
        int k = 2;
        int a[] = {1, 5, 8, 10};
        int n = a.length;
        System.out.println(minCost(a, n, k));
              
    }
}
  
// This code is contributed by vt_m.

C#

// C# program to find minimum cost 


// k partitions of array.
using System;
  
class GFG {
      
    static int inf = 1000000000;
      
    // Returns minimum cost of partitioning 
    // a[] in k clusters.

472
Chapter 56. Clustering/Partitioning an array such that sum of square differences is
minimum

    static int minCost(int []a, int n, int k)


    {
          
        // Create a dp[][] table and initialize
        // all values as infinite. dp[i][j] is
        // going to store optimal partition cost
        // for arr[0..i-1] and j partitions
        int [,]dp = new int[n + 1,k + 1];
        for (int i = 0; i <= n; i++)
            for (int j = 0; j <= k; j++)
                dp[i,j] = inf;
      
        // Fill dp[][] in bottom
        // up manner
        dp[0,0] = 0;
      
        // Current ending position 
        // (After i-th iteration 
        // result for a[0..i-1]
        // is computed.
        for (int i = 1; i <= n; i++)
      
            // j is number of partitions
            for (int j = 1; j <= k; j++)
      
                // Picking previous
                // partition for
                // current i.
                for (int m = i - 1; m >= 0; m--)
                    dp[i,j] = Math.Min(dp[i,j],
                                 dp[m,j - 1] +
                               (a[i - 1] - a[m]) * 
                               (a[i - 1] - a[m]));
      
      
        return dp[n,k];
    }
      
    // Driver code
    public static void Main () 
    {
        int k = 2;
        int []a = {1, 5, 8, 10};
        int n = a.Length;
        Console.Write(minCost(a, n, k));
              
    }
}

473
Chapter 56. Clustering/Partitioning an array such that sum of square differences is
minimum

  
// This code is contributed by nitin mittal

Output:

20

Time Complexity: Having the three simple loops, the complexity of the above algorithm

is .
Improved By : nitin mittal

Source

https://www.geeksforgeeks.org/clusteringpartitioning-an-array-such-that-sum-of-square-differences-is-minimum/

474
Chapter 57

Coin game winner where every


player has three choices

Coin game winner where every player has three choices - GeeksforGeeks
A and B are playing a game. At the beginning there are n coins. Given two more numbers
x and y. In each move a player can pick x or y or l coins. A always starts the game. The
player who picks the last coin wins the game. For a given value of n, find whether A will
win the game or not if both are playing optimally.
Examples:

Input : n = 5, x = 3, y = 4
Output : A
There are 5 coins, every player can pick 1 or
3 or 4 coins on his/her turn.
A can win by picking 3 coins in first chance.
Now 2 coins will be left so B will pick one
coin and now A can win by picking the last coin.

Input : 2 3 4
Output : B

Let us take few example values of n for x = 3, y = 4.


n = 0 A can not pick any coin so he losses
n = 1 A can pick 1 coin and win the game
n = 2 A can pick only 1 coin. Now B will pick 1 coin and win the game
n = 3 4 A will win the game by picking 3 or 4 coins
n = 5, 6 A will choose 3 or 4 coins. Now B will have to choose from 2 coins so A will win.
We can observe that A wins game for n coins only when it loses for coins n-1, n-x and n-y.

C++

475
Chapter 57. Coin game winner where every player has three choices

// CPP program to find winner of game


// if player can pick 1, x, y coins
#include <bits/stdc++.h>
using namespace std;
  
// To find winner of game
bool findWinner(int x, int y, int n)
{
    // To store results
    int dp[n + 1];
  
    // Initial values
    dp[0] = false;
    dp[1]