1 00:00:00,000 --> 00:00:01,996 [SQUEAKING] 2 00:00:01,996 --> 00:00:03,992 [RUSTLING] 3 00:00:03,992 --> 00:00:06,487 [CLICKING] 4 00:00:11,970 --> 00:00:12,970 ERIK DEMAINE: All right. 5 00:00:12,970 --> 00:00:18,010 Welcome back to 006 and our dynamic programming quadruple 6 00:00:18,010 --> 00:00:18,580 of lectures. 7 00:00:18,580 --> 00:00:23,410 We are over halfway through, into lecture three of four. 8 00:00:23,410 --> 00:00:27,040 Today, we're going to follow up on this idea of problem 9 00:00:27,040 --> 00:00:30,310 constraints and expansion that was mentioned, especially, 10 00:00:30,310 --> 00:00:32,180 towards the end of last lecture. 11 00:00:32,180 --> 00:00:36,910 We saw an example of subproblem expansion by a factor of 2 12 00:00:36,910 --> 00:00:39,430 in the two-player game with coins 13 00:00:39,430 --> 00:00:43,150 where we wanted to have two versions of the game, 14 00:00:43,150 --> 00:00:45,518 one where I go first and one where you go first. 15 00:00:45,518 --> 00:00:47,560 So this was expanding the number of such problems 16 00:00:47,560 --> 00:00:48,610 by a factor of 2. 17 00:00:48,610 --> 00:00:51,100 Today, we'll see a bunch more examples of this idea, 18 00:00:51,100 --> 00:00:53,620 including in one setting we've seen already, 19 00:00:53,620 --> 00:00:55,120 which is Bellman-Ford, which you can 20 00:00:55,120 --> 00:00:57,525 think of as a dynamic program. 21 00:00:57,525 --> 00:00:58,900 Maybe it's a good time to mention 22 00:00:58,900 --> 00:01:03,010 that Bellman invented dynamic programming in the '50s. 23 00:01:03,010 --> 00:01:05,100 Same Bellman in the Bellman-Ford algorithm. 24 00:01:05,100 --> 00:01:06,850 This was actually an independent discovery 25 00:01:06,850 --> 00:01:11,050 by both of them-- and other people. 26 00:01:11,050 --> 00:01:13,803 He invented dynamic programming, and then, a few years later, he 27 00:01:13,803 --> 00:01:15,970 applied it to solve the single-source shortest paths 28 00:01:15,970 --> 00:01:16,538 problem. 29 00:01:16,538 --> 00:01:17,830 We saw them in the other order. 30 00:01:17,830 --> 00:01:19,580 We saw single-source shortest paths first, 31 00:01:19,580 --> 00:01:20,900 because it was a little easier. 32 00:01:20,900 --> 00:01:24,370 And now we're seeing the general framework that this fits into. 33 00:01:24,370 --> 00:01:26,710 And so we'll see how that works. 34 00:01:26,710 --> 00:01:28,690 Why did Bellman call dynamic programming 35 00:01:28,690 --> 00:01:29,530 dynamic programming? 36 00:01:29,530 --> 00:01:31,810 Mostly because it sounded cool, and he 37 00:01:31,810 --> 00:01:35,375 was trying to impress government agencies giving him grants. 38 00:01:35,375 --> 00:01:37,750 I mean, how can you argue with something as cool-sounding 39 00:01:37,750 --> 00:01:39,430 as dynamic programming? 40 00:01:39,430 --> 00:01:41,050 But there is some logic to it. 41 00:01:41,050 --> 00:01:43,900 Programming is a reference to an old form of this word, which 42 00:01:43,900 --> 00:01:45,040 means optimization. 43 00:01:45,040 --> 00:01:47,050 And generally, we're trying to optimize things. 44 00:01:47,050 --> 00:01:49,030 And instead of optimizing according 45 00:01:49,030 --> 00:01:53,035 to some static kind of approach or program, 46 00:01:53,035 --> 00:01:54,160 we're doing it dynamically. 47 00:01:54,160 --> 00:01:56,800 This is a reference to the local brute force we're doing 48 00:01:56,800 --> 00:01:58,780 to optimize at each stage. 49 00:01:58,780 --> 00:02:01,240 You can't tell, at the top, what you're 50 00:02:01,240 --> 00:02:02,840 going to do in the middle. 51 00:02:02,840 --> 00:02:03,760 And so it's kind of-- 52 00:02:03,760 --> 00:02:06,620 each subproblem is behaving differently. 53 00:02:06,620 --> 00:02:08,110 And so, in that sense, dynamic. 54 00:02:08,110 --> 00:02:10,270 And it sounds cool. 55 00:02:10,270 --> 00:02:10,800 All right. 56 00:02:10,800 --> 00:02:12,550 Then we'll go to all-pairs shortest paths. 57 00:02:12,550 --> 00:02:16,918 We'll see a new algorithm for that that's not asymptotically 58 00:02:16,918 --> 00:02:18,460 any better, but it's nice and simple, 59 00:02:18,460 --> 00:02:22,090 and another way to-- a cool way to see subproblem expansion. 60 00:02:22,090 --> 00:02:25,810 And then we'll look at a couple of sort of practical problems-- 61 00:02:25,810 --> 00:02:28,240 parenthesizing arithmetic expressions 62 00:02:28,240 --> 00:02:30,840 and a real-world problem, piano and guitar fingering, 63 00:02:30,840 --> 00:02:34,420 so assigning a fingering how to play a piece. 64 00:02:34,420 --> 00:02:36,730 And we're going to do that with our SRTBOT framework. 65 00:02:36,730 --> 00:02:38,500 Quick recollection of what that is. 66 00:02:38,500 --> 00:02:40,030 We define subproblems. 67 00:02:40,030 --> 00:02:41,920 And we saw how to do that for sequences. 68 00:02:41,920 --> 00:02:44,830 We try either prefixes, suffixes, or substrings. 69 00:02:44,830 --> 00:02:48,490 We prefer prefixes and suffixes because there's fewer of them. 70 00:02:48,490 --> 00:02:50,680 If there's more than one sequence, 71 00:02:50,680 --> 00:02:53,215 we take the product of those spaces. 72 00:02:53,215 --> 00:02:55,090 And then the idea we're going to stress today 73 00:02:55,090 --> 00:02:57,250 is, we can always add subproblems 74 00:02:57,250 --> 00:02:59,410 to make the next step easier. 75 00:02:59,410 --> 00:03:01,720 In particular, adding constraints to subproblems, 76 00:03:01,720 --> 00:03:06,190 in some sense, lets us remember things about the subproblem 77 00:03:06,190 --> 00:03:08,440 that's calling us-- or about the past, 78 00:03:08,440 --> 00:03:09,760 is one way to think about it-- 79 00:03:09,760 --> 00:03:11,350 or in general, to "remember state." 80 00:03:11,350 --> 00:03:14,860 Just by adding more subproblems, we can remember more stuff-- 81 00:03:14,860 --> 00:03:18,940 not just what things we're working on, but some context. 82 00:03:18,940 --> 00:03:21,190 And that's what we'll see lots of examples of today. 83 00:03:21,190 --> 00:03:23,770 It will hopefully make sense by the end of the lecture. 84 00:03:23,770 --> 00:03:26,410 Then, we need to relate these subproblems with the recurrence 85 00:03:26,410 --> 00:03:27,415 relation-- 86 00:03:27,415 --> 00:03:29,290 actually, we usually just call it a relation. 87 00:03:29,290 --> 00:03:33,070 And the key idea here is to come up with a question 88 00:03:33,070 --> 00:03:36,010 that, if you knew the answer to that question, 89 00:03:36,010 --> 00:03:40,360 you could reduce the subproblem you're 90 00:03:40,360 --> 00:03:45,940 trying to solve to smaller subproblem solutions. 91 00:03:45,940 --> 00:03:49,990 This question is sort of the fundamental aspect of-- 92 00:03:49,990 --> 00:03:51,670 some fundamental aspect of a solution. 93 00:03:51,670 --> 00:03:53,920 Typically, when you're dealing with suffixes, 94 00:03:53,920 --> 00:03:56,553 you want to ask some question about the first item, s of i. 95 00:03:56,553 --> 00:03:57,970 When you're dealing with prefixes, 96 00:03:57,970 --> 00:04:01,090 you want to ask a question about some-- 97 00:04:01,090 --> 00:04:03,790 near the last item, s of i minus 1. 98 00:04:03,790 --> 00:04:05,290 And for substrings, who knows? 99 00:04:05,290 --> 00:04:07,300 Somewhere in the middle. 100 00:04:07,300 --> 00:04:09,920 We'll see an example of that today. 101 00:04:09,920 --> 00:04:13,390 Once you have-- oh, this is a reveal. 102 00:04:13,390 --> 00:04:14,950 Something coming later. 103 00:04:14,950 --> 00:04:17,589 Once you have identified such a question, 104 00:04:17,589 --> 00:04:19,690 the dynamic programming approach is, 105 00:04:19,690 --> 00:04:21,790 don't be smart about how to answer that question-- 106 00:04:21,790 --> 00:04:22,870 just locally brute force. 107 00:04:22,870 --> 00:04:25,030 Try all possible answers to the question. 108 00:04:25,030 --> 00:04:29,052 For each one, recurse, and take the best solution 109 00:04:29,052 --> 00:04:31,510 according to whatever metric you're trying to do, typically 110 00:04:31,510 --> 00:04:34,090 minimization or maximization. 111 00:04:34,090 --> 00:04:36,070 Another way to think of this local brute force, 112 00:04:36,070 --> 00:04:37,487 which I like to think in my head-- 113 00:04:37,487 --> 00:04:39,940 so maybe some people like this, some people don't-- 114 00:04:39,940 --> 00:04:43,670 is to think about guessing the answer to the question. 115 00:04:43,670 --> 00:04:47,200 So maybe the answer could be 0, 1, or 2. 116 00:04:47,200 --> 00:04:50,680 And my algorithm will say, guess which is the right answer. 117 00:04:50,680 --> 00:04:54,370 And I'll assume that my algorithm correctly guesses 118 00:04:54,370 --> 00:04:58,090 the answer and analyze that. 119 00:04:58,090 --> 00:05:00,880 So we can think of the program as going straight through-- 120 00:05:00,880 --> 00:05:03,220 guessing the answer and then recursing, 121 00:05:03,220 --> 00:05:05,752 and then combining the solutions however. 122 00:05:05,752 --> 00:05:07,210 But then, at the end, of course, we 123 00:05:07,210 --> 00:05:08,920 can't assume that the guess was correct. 124 00:05:08,920 --> 00:05:11,402 In fact, we have to loop over all of those guesses. 125 00:05:11,402 --> 00:05:12,360 So it's the same thing. 126 00:05:12,360 --> 00:05:15,130 Just, if you think of it this way, 127 00:05:15,130 --> 00:05:16,875 there's less looping in your program. 128 00:05:16,875 --> 00:05:18,750 But when you analyze it, definitely, the loop 129 00:05:18,750 --> 00:05:19,470 is really there. 130 00:05:19,470 --> 00:05:23,070 You have to pay for all of the possible answers. 131 00:05:23,070 --> 00:05:23,790 OK. 132 00:05:23,790 --> 00:05:26,370 Then we need to make sure this relation is acyclic, 133 00:05:26,370 --> 00:05:27,690 get a subproblem DAG. 134 00:05:27,690 --> 00:05:30,030 And I like to specify an explicit topological order 135 00:05:30,030 --> 00:05:31,020 to make that clear. 136 00:05:31,020 --> 00:05:32,748 We have base cases for the relation. 137 00:05:32,748 --> 00:05:34,290 We have to solve the original problem 138 00:05:34,290 --> 00:05:36,040 in terms of these subproblems, and then we 139 00:05:36,040 --> 00:05:38,040 analyze the running time, usually, 140 00:05:38,040 --> 00:05:41,610 as the number of subproblems times the non-recursive work 141 00:05:41,610 --> 00:05:44,493 in the relation. 142 00:05:44,493 --> 00:05:46,410 So recursion is free because we're multiplying 143 00:05:46,410 --> 00:05:47,280 by the number of subproblems. 144 00:05:47,280 --> 00:05:48,863 You can also sum over the subproblems. 145 00:05:48,863 --> 00:05:51,005 Sometimes that gives you a tighter bound. 146 00:05:51,005 --> 00:05:52,380 And then, of course, we also have 147 00:05:52,380 --> 00:05:56,500 to add on the running time we spend in the original problem. 148 00:05:56,500 --> 00:05:57,000 All right. 149 00:05:57,000 --> 00:05:59,280 That was a quick recap. 150 00:05:59,280 --> 00:06:02,310 Now, one problem we saw in this framework two 151 00:06:02,310 --> 00:06:03,930 lectures ago-- the first lecture was 152 00:06:03,930 --> 00:06:07,380 single-source shortest paths in a DAG, 153 00:06:07,380 --> 00:06:09,180 which, a lot of dynamic programs actually 154 00:06:09,180 --> 00:06:12,130 can be reduced to a single-source shortest paths 155 00:06:12,130 --> 00:06:12,630 in a DAG. 156 00:06:12,630 --> 00:06:14,520 In fact, the reverse is true. 157 00:06:14,520 --> 00:06:16,890 Single-source shortest paths in a DAG can be thought of. 158 00:06:16,890 --> 00:06:18,840 The DAG relaxation algorithm we saw 159 00:06:18,840 --> 00:06:21,600 is essentially a dynamic program where the subproblems are 160 00:06:21,600 --> 00:06:26,490 delta of s, v. The relation of delta of s, v is the min. 161 00:06:26,490 --> 00:06:29,520 So what are we thinking about here? 162 00:06:29,520 --> 00:06:36,287 We're guessing-- this is sort of a new phrase I want to add. 163 00:06:36,287 --> 00:06:37,620 Actually, I wrote it right here. 164 00:06:37,620 --> 00:06:41,892 The last edge, u, v, on a shortest s to v path. 165 00:06:41,892 --> 00:06:43,350 That's a delta of s, v. The problem 166 00:06:43,350 --> 00:06:47,730 we're trying to solve is, find shortest s to v path. 167 00:06:47,730 --> 00:06:52,110 And it's some path, and we don't know what it looks like, 168 00:06:52,110 --> 00:06:55,440 but some feature of the solution of this path 169 00:06:55,440 --> 00:06:57,900 we're trying to find is, well, what's the last edge? 170 00:06:57,900 --> 00:07:02,270 It comes from some vertex here, unless the path is of length 0 171 00:07:02,270 --> 00:07:04,800 and s equals v. That's a special case dealt 172 00:07:04,800 --> 00:07:05,940 with in the base case. 173 00:07:05,940 --> 00:07:08,543 Otherwise, there's some vertex u before v. 174 00:07:08,543 --> 00:07:09,960 We don't know what it is, so we're 175 00:07:09,960 --> 00:07:12,940 going to locally brute force, or guess what the right answer is. 176 00:07:12,940 --> 00:07:15,210 So look at all incoming edges from u 177 00:07:15,210 --> 00:07:18,240 to v, and for each of them, take the recursive shortest path 178 00:07:18,240 --> 00:07:20,530 from s to u, plus the weight of the edge. 179 00:07:20,530 --> 00:07:24,430 So this is the guessing or local brute force perspective. 180 00:07:24,430 --> 00:07:27,360 And the reason this works is because G is acyclic, 181 00:07:27,360 --> 00:07:29,890 and so it has a topological order. 182 00:07:29,890 --> 00:07:32,760 Otherwise, if the graph has a cycle-- 183 00:07:32,760 --> 00:07:34,980 and that's the case we want to go to next-- 184 00:07:34,980 --> 00:07:38,150 this recursive call from delta of s, v to delta of s, 185 00:07:38,150 --> 00:07:41,220 u will have loops in it. 186 00:07:41,220 --> 00:07:43,177 And so you'll never evaluate this recursion. 187 00:07:43,177 --> 00:07:44,010 You'll never finish. 188 00:07:44,010 --> 00:07:45,390 You'll never minimalize. 189 00:07:45,390 --> 00:07:46,030 You'll be sad. 190 00:07:46,030 --> 00:07:48,120 It will take infinite time. 191 00:07:48,120 --> 00:07:50,790 So don't use this algorithm unless you have a DAG. 192 00:07:50,790 --> 00:07:51,630 For DAG, it's great. 193 00:07:51,630 --> 00:07:53,560 It's linear time. 194 00:07:53,560 --> 00:07:54,960 So that was a little review. 195 00:07:54,960 --> 00:07:58,410 Now, here is a single-source shortest paths 196 00:07:58,410 --> 00:08:01,740 in general graphs, which we know as Bellman-Ford, 197 00:08:01,740 --> 00:08:05,790 but rephrased into the SRTBOT framework. 198 00:08:05,790 --> 00:08:10,530 So we defined this problem, in the Bellman-Ford lecture, 199 00:08:10,530 --> 00:08:13,530 delta sub k of s, v. Remember, this 200 00:08:13,530 --> 00:08:15,563 was the weight of a shortest path from s 201 00:08:15,563 --> 00:08:20,980 to v that is restricted to use, at most, k edges. 202 00:08:20,980 --> 00:08:22,540 This made the problem feasible. 203 00:08:22,540 --> 00:08:24,670 We ended up taking the product of the graph 204 00:08:24,670 --> 00:08:29,450 into all of these different subproblems, in fact. 205 00:08:29,450 --> 00:08:31,450 But from the perspective of dynamic programming, 206 00:08:31,450 --> 00:08:33,460 we think of this as a subproblem constraint. 207 00:08:33,460 --> 00:08:35,890 What we really want is the shortest s to v path, 208 00:08:35,890 --> 00:08:37,070 but that's hard. 209 00:08:37,070 --> 00:08:39,309 So we're going to break it up into smaller pieces. 210 00:08:39,309 --> 00:08:41,868 For each k between 0 and v, we're 211 00:08:41,868 --> 00:08:44,410 going to say, well, let's think about this problem restricted 212 00:08:44,410 --> 00:08:46,570 to use, at most, k edges. 213 00:08:46,570 --> 00:08:49,300 And for simple paths, if there are no negative weight cycles, 214 00:08:49,300 --> 00:08:51,430 we only have to go up to v minus 1. 215 00:08:51,430 --> 00:08:52,060 We proved that. 216 00:08:52,060 --> 00:08:53,602 And we know we're-- then we're happy. 217 00:08:55,820 --> 00:08:58,890 But that's sort of the last thing we want to solve. 218 00:08:58,890 --> 00:09:01,640 So if we look down at the original problem we want, 219 00:09:01,640 --> 00:09:06,440 it's delta sub v minus 1 of s, v for all v. 220 00:09:06,440 --> 00:09:08,390 So if we could solve these subproblems, 221 00:09:08,390 --> 00:09:09,980 as we saw with Bellman-Ford, we can 222 00:09:09,980 --> 00:09:11,160 solve the original problem-- unless there 223 00:09:11,160 --> 00:09:12,285 are negative weight cycles. 224 00:09:12,285 --> 00:09:15,892 And we use delta sub v of s, v to check whether they're 225 00:09:15,892 --> 00:09:16,850 negative weight cycles. 226 00:09:16,850 --> 00:09:19,010 I don't want to repeat that, but that's the all 227 00:09:19,010 --> 00:09:20,510 in the original problem. 228 00:09:20,510 --> 00:09:23,780 And then we can take this relation 229 00:09:23,780 --> 00:09:26,510 that we wrote for DAG shortest paths 230 00:09:26,510 --> 00:09:29,100 and just port it over here. 231 00:09:29,100 --> 00:09:30,530 So remember, for a general graph, 232 00:09:30,530 --> 00:09:32,750 this has cycles, so we can't use it, 233 00:09:32,750 --> 00:09:35,250 because we're just referring to arbitrary delta of s, 234 00:09:35,250 --> 00:09:40,080 vs, so there's no reason to expect no cycles there. 235 00:09:40,080 --> 00:09:42,800 In fact, the call graph is exactly the graph G, 236 00:09:42,800 --> 00:09:46,410 so it has a cycle if and only if G does. 237 00:09:46,410 --> 00:09:51,050 But now, over here, I'm running exactly the same formula 238 00:09:51,050 --> 00:09:54,500 for this min, but I added a sub k here 239 00:09:54,500 --> 00:09:57,320 and a sub k minus 1 here, the observation 240 00:09:57,320 --> 00:09:59,930 being, if I've already guessed what 241 00:09:59,930 --> 00:10:02,360 the last edge u, v is for this path, 242 00:10:02,360 --> 00:10:06,290 then if this whole thing has length at most k, 243 00:10:06,290 --> 00:10:11,380 then this piece has length at most k minus 1. 244 00:10:11,380 --> 00:10:17,840 So I only need to solve delta sub k minus 1 of s, v here. 245 00:10:17,840 --> 00:10:20,290 And so that's what I wrote-- sorry, of s, u. 246 00:10:20,290 --> 00:10:22,580 That's what I wrote here. 247 00:10:22,580 --> 00:10:25,140 There's one other thing, which is, 248 00:10:25,140 --> 00:10:26,990 as I mentioned a little while ago, 249 00:10:26,990 --> 00:10:29,570 it could be that we use fewer than k edges. 250 00:10:29,570 --> 00:10:31,670 And so let's consider the case where 251 00:10:31,670 --> 00:10:36,140 we don't follow the last edge, and we just add to this min 252 00:10:36,140 --> 00:10:39,170 the shortest path using, at most, k minus 1 edges. 253 00:10:39,170 --> 00:10:42,260 That's one option for having, at most, k edges. 254 00:10:42,260 --> 00:10:44,360 If we wrote equality here, then we 255 00:10:44,360 --> 00:10:48,560 would remove that, like the last problem section. 256 00:10:48,560 --> 00:10:52,110 OK, good. 257 00:10:52,110 --> 00:10:56,370 The key observation here is that this recurrence does not 258 00:10:56,370 --> 00:10:57,630 have cycles. 259 00:10:57,630 --> 00:11:00,990 Just by adding this index, if we solve these problems 260 00:11:00,990 --> 00:11:04,620 in order of increasing k, all of the references from delta sub 261 00:11:04,620 --> 00:11:06,870 care in terms of delta k minus 1. 262 00:11:06,870 --> 00:11:08,940 And so this is now magically acyclic. 263 00:11:08,940 --> 00:11:12,180 This is why Bellman-Ford worked. 264 00:11:12,180 --> 00:11:14,040 But now, I think in a very pleasing way, 265 00:11:14,040 --> 00:11:15,720 we're taking our graph acyclic. 266 00:11:15,720 --> 00:11:18,870 And by spreading it out over various copies of k 267 00:11:18,870 --> 00:11:21,480 and referencing always the smaller one, 268 00:11:21,480 --> 00:11:23,070 we get an acyclic graph-- 269 00:11:23,070 --> 00:11:24,600 acyclic relations. 270 00:11:24,600 --> 00:11:26,910 We have base cases, like normal. 271 00:11:26,910 --> 00:11:29,100 And then we can analyze the running time 272 00:11:29,100 --> 00:11:31,910 in the usual way, which is summing-- 273 00:11:35,160 --> 00:11:36,300 how much does this cost? 274 00:11:36,300 --> 00:11:39,390 We're going to take the cost of computing the relation, which 275 00:11:39,390 --> 00:11:42,240 is the number of incoming edges to v-- 276 00:11:42,240 --> 00:11:46,790 that's this theta-- and then some overall subproblem. 277 00:11:46,790 --> 00:11:50,280 So sum over k and sum over v. Wrote it 278 00:11:50,280 --> 00:11:53,670 as a sum instead of a product because this thing 279 00:11:53,670 --> 00:11:59,880 is theta E. The sum of incoming edges over all vertices 280 00:11:59,880 --> 00:12:03,030 is exactly the size of E. And then we sum-- 281 00:12:03,030 --> 00:12:05,520 there's no k in this formula, so we just multiply by v 282 00:12:05,520 --> 00:12:09,780 and we get v E. So our good friend Bellman-Ford recast 283 00:12:09,780 --> 00:12:11,940 kind of the opposite way. 284 00:12:11,940 --> 00:12:13,500 Before, we were using relaxations. 285 00:12:13,500 --> 00:12:15,750 Now, we're just writing the min explicitly. 286 00:12:15,750 --> 00:12:17,580 But essentially the same computation, just 287 00:12:17,580 --> 00:12:20,160 in a different order. 288 00:12:20,160 --> 00:12:21,270 OK, cool. 289 00:12:21,270 --> 00:12:24,400 Those are reviews of old algorithms, 290 00:12:24,400 --> 00:12:28,860 but in this new framework to show how powerful it is. 291 00:12:28,860 --> 00:12:35,850 Let's look at another example, which is our friend-- 292 00:12:35,850 --> 00:12:40,500 right here-- all-pair shortest paths. 293 00:12:40,500 --> 00:12:43,410 A few lectures ago, we saw Johnson's algorithm, 294 00:12:43,410 --> 00:12:46,480 which solves this very well. 295 00:12:46,480 --> 00:12:51,570 So one option we could use is just 296 00:12:51,570 --> 00:12:56,040 this same set of subproblems, but for all u and v. 297 00:12:56,040 --> 00:12:59,040 For u and v and v-- 298 00:12:59,040 --> 00:13:00,940 that's what we really care about. 299 00:13:00,940 --> 00:13:05,910 And then we could say k up to v. Something like that. 300 00:13:05,910 --> 00:13:08,840 So this would work, but it would give the same running time 301 00:13:08,840 --> 00:13:11,180 as running Bellman-Ford v times. 302 00:13:11,180 --> 00:13:13,190 This is one solution we know, but not 303 00:13:13,190 --> 00:13:16,160 the best solution we know, for how to solve shortest paths. 304 00:13:16,160 --> 00:13:24,860 This would give v squared E, which is at most v to the 4th. 305 00:13:24,860 --> 00:13:27,590 For dense graphs, it is theta v to the 4th. 306 00:13:27,590 --> 00:13:31,280 So this is v times v times v. But worst case 307 00:13:31,280 --> 00:13:33,230 is v to the 4th what I would like 308 00:13:33,230 --> 00:13:34,940 to show you now is a different way 309 00:13:34,940 --> 00:13:38,600 to solve this problem-- almost identical, but gives 310 00:13:38,600 --> 00:13:43,090 v cubed running time, which, for dense graphs, is really good. 311 00:13:43,090 --> 00:13:45,730 So we're going to reduce this 4 down to a 3. 312 00:13:45,730 --> 00:13:49,442 And this is an algorithm called Floyd-Warshall. 313 00:13:49,442 --> 00:13:51,150 It's definitely not an obvious algorithm. 314 00:13:51,150 --> 00:13:52,780 It's a very cool idea. 315 00:13:52,780 --> 00:13:55,175 And it's a nice example of a different way-- 316 00:13:55,175 --> 00:13:56,800 remember, this is subproblem expansion. 317 00:13:56,800 --> 00:13:58,990 We took the problems we cared about multiplied 318 00:13:58,990 --> 00:14:00,455 by this choice of k. 319 00:14:00,455 --> 00:14:02,080 Here, we're going to do the same thing, 320 00:14:02,080 --> 00:14:04,470 but define it differently. 321 00:14:04,470 --> 00:14:07,510 We're going to define those subproblems differently. 322 00:14:07,510 --> 00:14:14,380 First, I want to number the vertices, 323 00:14:14,380 --> 00:14:16,760 starting at 1 for convenience. 324 00:14:16,760 --> 00:14:19,210 So let's see, y-- 325 00:14:19,210 --> 00:14:22,330 and then we're going to define some subproblems, which 326 00:14:22,330 --> 00:14:25,590 are delta-- 327 00:14:25,590 --> 00:14:27,615 I'll call it u, v, comma k. 328 00:14:30,310 --> 00:14:37,050 Maybe, to avoid conflict, I will write a d here. 329 00:14:37,050 --> 00:14:40,560 This is just a definition local to this algorithm. 330 00:14:40,560 --> 00:14:47,265 So I want the weight of shortest s to v path. 331 00:14:51,510 --> 00:14:53,522 So far, just the same as the problem we 332 00:14:53,522 --> 00:14:54,480 actually want to solve. 333 00:14:54,480 --> 00:14:56,280 This is delta of-- 334 00:14:56,280 --> 00:15:04,740 sorry, u, v. But I'm going to add a constraint, which is, 335 00:15:04,740 --> 00:15:19,970 using only vertices in u, v and 1 to up to k. 336 00:15:19,970 --> 00:15:23,280 This is the divine inspiration to define subproblems this way. 337 00:15:23,280 --> 00:15:26,760 It's a different constraint than the one we saw here, 338 00:15:26,760 --> 00:15:30,840 which was using, at most, k edges. 339 00:15:30,840 --> 00:15:32,720 So in some sense, what's slow about 340 00:15:32,720 --> 00:15:35,150 this algorithm is that we have to loop over 341 00:15:35,150 --> 00:15:37,860 all of the incoming vertices. 342 00:15:37,860 --> 00:15:39,720 This is expensive. 343 00:15:39,720 --> 00:15:42,150 Costs order the degree, which ends up with an E term. 344 00:15:42,150 --> 00:15:45,630 We're going to try to convert that E term into a v term 345 00:15:45,630 --> 00:15:49,750 by just knowing which vertex to come from-- 346 00:15:49,750 --> 00:15:51,220 which sounds impossible. 347 00:15:51,220 --> 00:15:53,980 But it turns out, if you write the subproblems this way-- 348 00:15:53,980 --> 00:15:56,860 so I'm naming the vertices. 349 00:15:56,860 --> 00:16:01,120 And say, well, let me just find a path that uses u, 350 00:16:01,120 --> 00:16:03,980 v and the vertex labeled 1. 351 00:16:03,980 --> 00:16:05,600 There's only, like, two options. 352 00:16:05,600 --> 00:16:08,980 I could go straight from u to v, or I could go from u to 1 to v. 353 00:16:08,980 --> 00:16:11,980 And then, how about with 1 and 2, and 1 and 2 and 3? 354 00:16:11,980 --> 00:16:14,630 The same vertices. 355 00:16:14,630 --> 00:16:18,110 By label instead of by counting them. 356 00:16:18,110 --> 00:16:23,330 Slight tweak, but it turns out this speeds up the algorithm. 357 00:16:23,330 --> 00:16:26,900 So let me first tell you how many subproblems there are. 358 00:16:31,820 --> 00:16:34,730 This is v cubed subproblems. 359 00:16:34,730 --> 00:16:39,600 Two choices for u and v, and I have v choices for-- 360 00:16:39,600 --> 00:16:41,720 sorry, I have v choices for u, v choices for v, 361 00:16:41,720 --> 00:16:46,040 and v choices for k, roughly. 362 00:16:46,040 --> 00:16:48,210 v cubed of these. 363 00:16:48,210 --> 00:16:51,140 But the key thing is-- that sounds like a lot. 364 00:16:51,140 --> 00:16:54,470 But the relation becomes cheaper now, 365 00:16:54,470 --> 00:16:57,740 because I can just write delta u-- 366 00:16:57,740 --> 00:17:07,430 sorry, d of u v k is the min of two things, d of u, 367 00:17:07,430 --> 00:17:19,385 v, k minus 1 and d of u, k, k minus 1, plus d of k, 368 00:17:19,385 --> 00:17:24,310 v, k minus 1. 369 00:17:24,310 --> 00:17:28,420 It's a strange formula because we're using indices 370 00:17:28,420 --> 00:17:34,360 like k for vertices also, as well as u and v for vertices, 371 00:17:34,360 --> 00:17:35,860 but we're also using k as a counter. 372 00:17:35,860 --> 00:17:38,390 But we can do this because our vertices are numbered. 373 00:17:38,390 --> 00:17:38,890 OK. 374 00:17:38,890 --> 00:17:40,460 So the idea is the following. 375 00:17:40,460 --> 00:17:44,920 We have vertex u, have a vertex v. And we've already 376 00:17:44,920 --> 00:17:48,430 found the shortest path that uses vertices 1 377 00:17:48,430 --> 00:17:51,040 through k minus 1. 378 00:17:51,040 --> 00:17:53,510 That's what this quantity is. 379 00:17:53,510 --> 00:17:54,790 So it could be-- 380 00:17:54,790 --> 00:17:57,447 and now, we're trying to add in this vertex k 381 00:17:57,447 --> 00:17:59,530 and think about, what are all the paths that could 382 00:17:59,530 --> 00:18:02,310 go from u to v using 1 up to k? 383 00:18:02,310 --> 00:18:04,060 Well, it could be the shortest path from u 384 00:18:04,060 --> 00:18:06,700 to v using 1 up to k doesn't use vertex k. 385 00:18:06,700 --> 00:18:08,290 That's the first option. 386 00:18:08,290 --> 00:18:10,210 Just use vertices 1 up to k minus 1. 387 00:18:10,210 --> 00:18:12,640 Maybe we don't need to use k. 388 00:18:12,640 --> 00:18:15,310 Or it could be that the path goes through k. 389 00:18:15,310 --> 00:18:18,340 Well, it starts at u, and it goes to k, 390 00:18:18,340 --> 00:18:21,912 and then it goes from k to v, all using-- 391 00:18:21,912 --> 00:18:24,370 for simple paths, if we assume there are no negative weight 392 00:18:24,370 --> 00:18:26,943 cycles and you have to run Bellman-Ford to detect them-- 393 00:18:26,943 --> 00:18:29,110 but assuming no negative weight cycles, the shortest 394 00:18:29,110 --> 00:18:32,630 path from u to v through k must start by using vertices less 395 00:18:32,630 --> 00:18:35,223 than k and then use vertices less than k again. 396 00:18:35,223 --> 00:18:36,640 And that's what I've written here. 397 00:18:36,640 --> 00:18:41,590 It's from u to k using k minus 1 up to k minus 1 labels, 398 00:18:41,590 --> 00:18:45,280 and from k to v using labels up to k minus 1. 399 00:18:45,280 --> 00:18:47,890 The cool thing here is, the min only has two terms. 400 00:18:47,890 --> 00:18:51,550 So this takes constant time non-recursive work. 401 00:18:51,550 --> 00:18:56,720 So this is, k is not on the shortest path. 402 00:18:56,720 --> 00:18:59,300 And this is, k is on the shortest path. 403 00:19:02,520 --> 00:19:03,090 Cool. 404 00:19:03,090 --> 00:19:06,660 So this is constant non-recursive work. 405 00:19:09,540 --> 00:19:14,770 If we jump ahead to the running time for this algorithm, 406 00:19:14,770 --> 00:19:20,130 we get the number of subproblems, which is v cubed, 407 00:19:20,130 --> 00:19:26,200 times the amount of work per subproblem, which is constant. 408 00:19:26,200 --> 00:19:29,330 So that's just a v cubed algorithm. 409 00:19:29,330 --> 00:19:33,590 For dense graphs, this is really good. 410 00:19:33,590 --> 00:19:37,850 When E is v squared, then this is the same thing as v times E, 411 00:19:37,850 --> 00:19:39,830 so as good as Bellman-Ford. 412 00:19:39,830 --> 00:19:42,860 It's not as good as Johnson for sparse graphs. 413 00:19:42,860 --> 00:19:47,060 Sparse graphs, remember-- or, in general, with Johnson, 414 00:19:47,060 --> 00:19:52,100 we got v squared log n plus v. And this is always 415 00:19:52,100 --> 00:19:53,270 spending v cubed. 416 00:19:53,270 --> 00:19:55,950 But it's cool because it's a very simple algorithm. 417 00:19:55,950 --> 00:19:59,930 Let's quickly write the topological order. 418 00:20:04,700 --> 00:20:08,780 All we need is to guarantee that we solve problems in increasing 419 00:20:08,780 --> 00:20:11,480 k order, because every reference here 420 00:20:11,480 --> 00:20:16,110 is to a smaller k for the third argument. 421 00:20:16,110 --> 00:20:17,540 And so, for example, you can just 422 00:20:17,540 --> 00:20:20,390 write a triply nested loop-- 423 00:20:20,390 --> 00:20:30,805 k equals 0, 1 up to v, and u and v, and v and v. 424 00:20:30,805 --> 00:20:32,930 So if you wanted to write this algorithm bottom-up, 425 00:20:32,930 --> 00:20:34,880 you just write this triple four-loop 426 00:20:34,880 --> 00:20:38,870 and then plug in this recurrence relation here. 427 00:20:38,870 --> 00:20:43,040 And think of d as a table, as a set mapping, 428 00:20:43,040 --> 00:20:45,830 instead of as a function call. 429 00:20:45,830 --> 00:20:48,350 And boom, in four lines, you've got your algorithm-- 430 00:20:48,350 --> 00:20:50,210 except you also need a base case. 431 00:20:50,210 --> 00:20:57,080 The base case here is u, v, 0. 432 00:20:57,080 --> 00:20:58,760 So I have to define what that means. 433 00:20:58,760 --> 00:21:02,780 But when k equals 0, the 1 through k set is empty. 434 00:21:02,780 --> 00:21:06,860 So all I'm allowed to use are my vertices u and v. 435 00:21:06,860 --> 00:21:08,450 There are three cases for this-- 436 00:21:08,450 --> 00:21:18,980 0 if u equals v. It's w of u, v if there's an edge from u to v. 437 00:21:18,980 --> 00:21:21,300 And it's infinity otherwise. 438 00:21:24,990 --> 00:21:25,490 OK. 439 00:21:25,490 --> 00:21:28,820 But easy base case, constant time for each. 440 00:21:28,820 --> 00:21:33,420 And then the original problems we want to solve 441 00:21:33,420 --> 00:21:38,010 are delta u, v, size of v. Because I remember 442 00:21:38,010 --> 00:21:41,168 the vertices 1 through size of v. And if k equals size of v, 443 00:21:41,168 --> 00:21:42,960 that means I get to use all of my vertices. 444 00:21:42,960 --> 00:21:44,850 So that is regular shortest paths. 445 00:21:44,850 --> 00:21:48,660 This is assuming no negative weight cycles. 446 00:21:51,142 --> 00:21:53,100 We already know how to do negative weight cycle 447 00:21:53,100 --> 00:21:57,690 detection, so I'm not going to talk about that again. 448 00:21:57,690 --> 00:22:01,140 But then, this will be my shortest pathway because-- 449 00:22:01,140 --> 00:22:02,140 yeah. 450 00:22:02,140 --> 00:22:04,980 I implicitly assumed here that my path was simple 451 00:22:04,980 --> 00:22:08,400 because I imagined that I only use k once-- 452 00:22:08,400 --> 00:22:09,910 0 or 1 time. 453 00:22:09,910 --> 00:22:13,530 And that's true if there are no negative weight cycles. 454 00:22:13,530 --> 00:22:14,030 Cool. 455 00:22:14,030 --> 00:22:17,090 And we already did the time part of SRTBOT. 456 00:22:17,090 --> 00:22:18,470 So v cubed algorithm. 457 00:22:18,470 --> 00:22:20,930 Very simple. 458 00:22:20,930 --> 00:22:24,170 Basically, five lines of code, and you've 459 00:22:24,170 --> 00:22:25,530 got all-pairs shortest paths. 460 00:22:25,530 --> 00:22:28,220 And if your graph is dense, this is a great running time. 461 00:22:28,220 --> 00:22:29,990 If your graph is not dense, you should 462 00:22:29,990 --> 00:22:32,750 use Johnson, like you will in-- 463 00:22:32,750 --> 00:22:35,600 or like you have implemented in your problem set. 464 00:22:35,600 --> 00:22:36,500 Yeah. 465 00:22:36,500 --> 00:22:37,220 AUDIENCE: So how does this this compare 466 00:22:37,220 --> 00:22:39,710 to just running Dijkstra's algorithm a bunch of times? 467 00:22:39,710 --> 00:22:41,750 ERIK DEMAINE: What about using Dijkstra? 468 00:22:41,750 --> 00:22:44,300 Let's compute. 469 00:22:44,300 --> 00:22:50,840 Running Dijkstra v times is the running time of Johnson. 470 00:22:56,535 --> 00:22:57,910 Running Dijkstra a bunch of times 471 00:22:57,910 --> 00:23:01,420 is great if your graph has only non-negative edge weights. 472 00:23:01,420 --> 00:23:03,520 Then you should just run Dijkstra. 473 00:23:03,520 --> 00:23:05,050 You get this running time. 474 00:23:05,050 --> 00:23:07,323 And for sparse graphs, this is superior. 475 00:23:07,323 --> 00:23:08,740 If you have negative edge weights, 476 00:23:08,740 --> 00:23:11,198 you should run Johnson, which is Bellman-Ford once and then 477 00:23:11,198 --> 00:23:13,900 Dijkstra three times. 478 00:23:13,900 --> 00:23:21,010 And we're comparing this to v cubed, which we just got. 479 00:23:21,010 --> 00:23:22,900 So this-- I mean, how these compare 480 00:23:22,900 --> 00:23:24,670 depends on how v and E relate. 481 00:23:24,670 --> 00:23:30,190 On the one hand, maybe v is theta E. 482 00:23:30,190 --> 00:23:32,200 That's what I would call a very sparse graph. 483 00:23:32,200 --> 00:23:34,250 And it's quite common. 484 00:23:34,250 --> 00:23:42,280 Then, the running time we get here is v squared log v-- 485 00:23:42,280 --> 00:23:45,140 roughly v squared. 486 00:23:45,140 --> 00:23:48,340 On the other hand, if we have a very dense graph, 487 00:23:48,340 --> 00:23:50,270 v is theta E squared-- 488 00:23:50,270 --> 00:23:53,380 which, for simple graphs, is the most we could hope for-- 489 00:23:53,380 --> 00:24:00,630 then this running time is v cubed. 490 00:24:00,630 --> 00:24:02,620 If you know the v is near E squared, 491 00:24:02,620 --> 00:24:06,090 then this is giving you v cubed anyway, from the vE term. 492 00:24:06,090 --> 00:24:07,918 So why not just use this algorithm? 493 00:24:07,918 --> 00:24:09,960 And often, you know, a priori, whether your graph 494 00:24:09,960 --> 00:24:12,168 is very sparse or very dense or somewhere in between. 495 00:24:12,168 --> 00:24:13,543 If it's somewhere in between, you 496 00:24:13,543 --> 00:24:15,120 should still use Johnson's algorithm, 497 00:24:15,120 --> 00:24:17,610 because you're going to get the benefit from sparsity 498 00:24:17,610 --> 00:24:21,030 and only have to pay this vE instead of the v cubed. 499 00:24:21,030 --> 00:24:23,280 But if you know ahead of time, constant fraction 500 00:24:23,280 --> 00:24:26,832 of the edges are there, then just use-- 501 00:24:26,832 --> 00:24:29,040 or you have a small enough graph that you don't care, 502 00:24:29,040 --> 00:24:33,340 just Floyd-Warshall because it's simple and fast. 503 00:24:33,340 --> 00:24:35,540 Good question. 504 00:24:35,540 --> 00:24:37,480 Any other questions? 505 00:24:37,480 --> 00:24:40,090 This is an example of subproblem expansion-- 506 00:24:40,090 --> 00:24:42,910 a very non-intuitive one, where we use 507 00:24:42,910 --> 00:24:45,370 some prefix of the vertices. 508 00:24:45,370 --> 00:24:46,910 But notice, it's prefixes again-- 509 00:24:46,910 --> 00:24:48,790 a number of the vertices from 1 up to v. 510 00:24:48,790 --> 00:24:50,830 And I took a prefix of those vertices. 511 00:24:50,830 --> 00:24:53,950 So I just solved the problem using prefix vertices 1 512 00:24:53,950 --> 00:24:54,490 through k. 513 00:24:54,490 --> 00:24:57,170 So it's actually a familiar idea. 514 00:24:57,170 --> 00:25:00,010 If all you had seen are all dynamic programming examples 515 00:25:00,010 --> 00:25:02,320 of prefixes, suffixes, substrings, actually, 516 00:25:02,320 --> 00:25:04,990 it's pretty natural way to solve shortest paths-- 517 00:25:04,990 --> 00:25:08,610 maybe even more natural than this. 518 00:25:08,610 --> 00:25:11,860 Anyway, all right. 519 00:25:11,860 --> 00:25:13,760 Enough shortest paths. 520 00:25:13,760 --> 00:25:16,150 Let's solve two more problems that 521 00:25:16,150 --> 00:25:19,060 are more in our standard wheelhouse that 522 00:25:19,060 --> 00:25:22,810 will involve sequences of inputs, not graphs. 523 00:25:22,810 --> 00:25:26,610 First one is arithmetic parenthesization. 524 00:25:26,610 --> 00:25:28,190 First, let me define this problem. 525 00:25:48,700 --> 00:25:49,200 OK. 526 00:25:49,200 --> 00:25:54,630 We are given a formula with, say, plus and times. 527 00:25:54,630 --> 00:25:58,140 Let me give you an actual example-- 528 00:25:58,140 --> 00:26:04,365 7 plus 4 times 3 plus 5. 529 00:26:07,670 --> 00:26:10,910 Now, when you read this, because you've been well-trained, 530 00:26:10,910 --> 00:26:13,328 you think, OK, I'm going to multiply 4 and 3 first 531 00:26:13,328 --> 00:26:14,870 because that has a higher precedence, 532 00:26:14,870 --> 00:26:16,970 and then I'll add the results up. 533 00:26:16,970 --> 00:26:20,072 But what I'm going to let you do is parenthesize this expression 534 00:26:20,072 --> 00:26:20,780 however you want. 535 00:26:20,780 --> 00:26:24,080 For example, you can add parentheses here and here. 536 00:26:24,080 --> 00:26:26,480 You must make a balanced parenthesis expression, 537 00:26:26,480 --> 00:26:28,730 a valid way to pair up-- 538 00:26:28,730 --> 00:26:30,710 or not just pair up, but a valid way 539 00:26:30,710 --> 00:26:32,030 to evaluate this expression. 540 00:26:32,030 --> 00:26:34,360 Any order you want. 541 00:26:34,360 --> 00:26:35,360 I could be inconsistent. 542 00:26:35,360 --> 00:26:40,100 I could, for example, do this sum, and then do this product, 543 00:26:40,100 --> 00:26:42,330 and then do this sum. 544 00:26:42,330 --> 00:26:46,800 But some kind of expression tree over this. 545 00:26:46,800 --> 00:26:48,390 And each one evaluates to something. 546 00:26:48,390 --> 00:26:54,540 This is 11 and this is 8, and so this is 88. 547 00:26:54,540 --> 00:26:57,760 And my goal is to maximize that computation. 548 00:26:57,760 --> 00:26:59,880 And I claim that this is the way to maximize 549 00:26:59,880 --> 00:27:02,280 that particular example. 550 00:27:02,280 --> 00:27:07,050 Let me write it in general, and get my notation 551 00:27:07,050 --> 00:27:09,150 to match my notes. 552 00:27:09,150 --> 00:27:23,540 Given a formula a 0, star 1, a 1, star 2, a 2, 553 00:27:23,540 --> 00:27:28,820 and so on up to star n minus 1, a n 554 00:27:28,820 --> 00:27:37,320 minus 1, where each a i is an integer, as we 555 00:27:37,320 --> 00:27:45,590 like in this class, and each star i is either plus or times. 556 00:27:45,590 --> 00:27:48,760 OK so I'm using star as a generic operator. 557 00:27:48,760 --> 00:27:51,110 I chose star because it is the superposition of star 558 00:27:51,110 --> 00:27:53,180 on top of a times symbol. 559 00:27:53,180 --> 00:27:56,240 So it's clear. 560 00:27:56,240 --> 00:27:58,940 So you're given some formula, any mixture of plus and times 561 00:27:58,940 --> 00:28:02,820 that you like, involving n integers. 562 00:28:02,820 --> 00:28:08,640 And your goal is to place parentheses 563 00:28:08,640 --> 00:28:16,380 to maximize the result. So you can try all of the combinations 564 00:28:16,380 --> 00:28:17,220 here. 565 00:28:17,220 --> 00:28:21,120 If I, for example, take the product of 4 times 3, I get 12. 566 00:28:21,120 --> 00:28:22,890 If I do that first, I get 12. 567 00:28:22,890 --> 00:28:29,250 Then if I add 5 and 7, I get 24, which is less than 88. 568 00:28:29,250 --> 00:28:31,200 And I check them all, and this one 569 00:28:31,200 --> 00:28:35,610 is the maximum for that example. 570 00:28:35,610 --> 00:28:39,030 Interesting problem. 571 00:28:39,030 --> 00:28:40,860 It's a bit of a toy problem, but it's 572 00:28:40,860 --> 00:28:45,700 motivated by lots of actual problems, which 573 00:28:45,700 --> 00:28:46,630 I won't go into here. 574 00:28:49,390 --> 00:28:54,870 To apply this framework, we need to identify some subproblems. 575 00:28:54,870 --> 00:28:56,890 This is a sequence problem. 576 00:28:56,890 --> 00:28:59,070 We're given a sequence of symbols. 577 00:28:59,070 --> 00:29:02,050 And so the natural thing is to try prefixes, suffixes, 578 00:29:02,050 --> 00:29:02,910 and substrings. 579 00:29:02,910 --> 00:29:06,030 I'm going to jump ahead and think about the relation first. 580 00:29:06,030 --> 00:29:09,390 I want to identify some question about a subproblem 581 00:29:09,390 --> 00:29:11,310 or its solution that would let me 582 00:29:11,310 --> 00:29:12,957 reduce to smaller subproblems. 583 00:29:12,957 --> 00:29:14,040 This is a little trickier. 584 00:29:14,040 --> 00:29:15,220 This is very different. 585 00:29:15,220 --> 00:29:18,090 We're not always doing something on the left or on the right, 586 00:29:18,090 --> 00:29:20,070 or we can't assume there's something happening 587 00:29:20,070 --> 00:29:22,740 on the left, because maybe we take a product in the middle 588 00:29:22,740 --> 00:29:23,685 first. 589 00:29:23,685 --> 00:29:25,530 If I take a product in the middle first, 590 00:29:25,530 --> 00:29:28,658 then I have some result here, but I still have three things. 591 00:29:28,658 --> 00:29:31,200 I have the thing to the left, I have the thing in the middle, 592 00:29:31,200 --> 00:29:32,590 and I have the thing on the right. 593 00:29:32,590 --> 00:29:34,632 It turns out to be very messy to think about what 594 00:29:34,632 --> 00:29:36,780 the first operation is. 595 00:29:36,780 --> 00:29:40,950 Because we can think of this as a tree, 596 00:29:40,950 --> 00:29:43,230 where we take a product here-- 597 00:29:43,230 --> 00:29:51,150 we take a sum of 7 and 4 and 3 and 5 over here 598 00:29:51,150 --> 00:29:53,102 and then take the product at the root. 599 00:29:53,102 --> 00:29:54,810 But I don't know what the tree is, right? 600 00:29:54,810 --> 00:29:56,820 I only know these numbers and these operators, 601 00:29:56,820 --> 00:30:00,120 but I don't know how to organize this tree. 602 00:30:00,120 --> 00:30:02,220 The idea is, if you think of this tree, 603 00:30:02,220 --> 00:30:05,010 what is the one thing that's easiest to identify? 604 00:30:05,010 --> 00:30:06,660 It's the root. 605 00:30:06,660 --> 00:30:09,120 The root corresponds to the last operation 606 00:30:09,120 --> 00:30:10,740 I do in this computation. 607 00:30:10,740 --> 00:30:12,960 The last thing I did was take a product. 608 00:30:12,960 --> 00:30:17,070 And that's a lot easier, because if I guess who is at the root-- 609 00:30:17,070 --> 00:30:18,420 which operator is at the root-- 610 00:30:18,420 --> 00:30:20,910 that naturally decomposes into the left subtree 611 00:30:20,910 --> 00:30:22,500 and the right subtree. 612 00:30:22,500 --> 00:30:25,050 And those will always be substrings. 613 00:30:25,050 --> 00:30:28,110 We kind of know this. 614 00:30:28,110 --> 00:30:30,120 This node corresponds to everything 615 00:30:30,120 --> 00:30:37,440 left of this operator, and this substring or this subtree 616 00:30:37,440 --> 00:30:40,060 corresponds to everything to the right of the operator. 617 00:30:40,060 --> 00:30:51,690 So this is our idea, is we're going to guess which operation, 618 00:30:51,690 --> 00:30:55,680 star i, is evaluated last-- 619 00:30:59,950 --> 00:31:03,530 or, in other words, at the root. 620 00:31:03,530 --> 00:31:04,990 So this is the question. 621 00:31:04,990 --> 00:31:07,810 It has n possible answers-- 622 00:31:07,810 --> 00:31:10,720 I guess, actually, n minus 1 from operator 1, 623 00:31:10,720 --> 00:31:12,460 operator n minus 1. 624 00:31:12,460 --> 00:31:18,630 And so we'll just brute force all of those choices. 625 00:31:18,630 --> 00:31:21,150 I wanted to start here because-- 626 00:31:21,150 --> 00:31:23,700 to realize that if, I choose some star 627 00:31:23,700 --> 00:31:26,430 i in the middle, which might be the right thing, 628 00:31:26,430 --> 00:31:27,660 like in this example. 629 00:31:27,660 --> 00:31:29,850 Star i is the middle one-- 630 00:31:29,850 --> 00:31:31,560 middle operator. 631 00:31:31,560 --> 00:31:33,210 I naturally decompose into everything 632 00:31:33,210 --> 00:31:34,800 to the left of that operator and everything 633 00:31:34,800 --> 00:31:36,120 to the right of that operator. 634 00:31:36,120 --> 00:31:38,560 This is a prefix. 635 00:31:38,560 --> 00:31:40,970 This is a suffix. 636 00:31:40,970 --> 00:31:43,520 So you might think, oh, my subproblems are all prefixes 637 00:31:43,520 --> 00:31:44,660 and all suffixes. 638 00:31:44,660 --> 00:31:47,180 But that would be wrong, because if you 639 00:31:47,180 --> 00:31:49,610 have a bunch of operators-- 640 00:31:49,610 --> 00:31:51,335 and say you choose this one to be last. 641 00:31:54,110 --> 00:31:56,770 So I have a prefix here and a suffix here. 642 00:31:56,770 --> 00:31:58,150 And then there will be some-- 643 00:31:58,150 --> 00:32:01,510 within this suffix, I'll choose some operator 644 00:32:01,510 --> 00:32:04,490 to be the root of that one, and I have a prefix 645 00:32:04,490 --> 00:32:06,430 and a suffix of this suffix. 646 00:32:06,430 --> 00:32:08,920 But in particular, I will have to evaluate 647 00:32:08,920 --> 00:32:11,320 this subproblem, which is a prefix of a suffix-- 648 00:32:11,320 --> 00:32:13,190 in other words, a substring. 649 00:32:13,190 --> 00:32:15,910 So never use a mixture of prefixes and suffixes. 650 00:32:15,910 --> 00:32:20,320 If you need both, you probably need all substrings. 651 00:32:20,320 --> 00:32:30,605 So our subproblems are going to be substrings. 652 00:32:36,430 --> 00:32:37,298 OK. 653 00:32:37,298 --> 00:32:39,340 I'm not going to write the subproblems quite yet, 654 00:32:39,340 --> 00:32:41,780 because there's another idea we need. 655 00:32:41,780 --> 00:32:45,710 So what do I need to do with the substring? 656 00:32:45,710 --> 00:32:47,700 I'm going to guess the middle operator 657 00:32:47,700 --> 00:32:49,310 and then evaluate the left substring, 658 00:32:49,310 --> 00:32:50,807 evaluate the right substring. 659 00:32:50,807 --> 00:32:52,640 What am I trying to do with those substring? 660 00:32:52,640 --> 00:32:55,130 I guess I'm trying to solve this problem, which 661 00:32:55,130 --> 00:32:58,740 is, place parentheses in order to maximize the result, 662 00:32:58,740 --> 00:33:01,440 and then return what the result is. 663 00:33:01,440 --> 00:33:03,440 And I can use paren pointers to reconstruct what 664 00:33:03,440 --> 00:33:05,300 the parentheses actually are. 665 00:33:10,200 --> 00:33:11,810 Once I guess what the last operator 666 00:33:11,810 --> 00:33:14,900 is, it enough to maximize the part to the right 667 00:33:14,900 --> 00:33:16,970 and maximize the part to the left? 668 00:33:16,970 --> 00:33:19,760 Will that always maximize my sum or product 669 00:33:19,760 --> 00:33:22,560 according to what this operator is? 670 00:33:22,560 --> 00:33:24,360 And if you think about it for a while. 671 00:33:24,360 --> 00:33:24,860 Yeah. 672 00:33:24,860 --> 00:33:28,920 If I want to maximize the sum, I should maximize the two parts. 673 00:33:28,920 --> 00:33:30,420 And if I want to maximize a product, 674 00:33:30,420 --> 00:33:31,753 I should maximize the two parts. 675 00:33:31,753 --> 00:33:33,030 That seems right. 676 00:33:33,030 --> 00:33:37,740 Except, I didn't say that my integers are positive. 677 00:33:37,740 --> 00:33:39,490 That's true if your integers are positive. 678 00:33:39,490 --> 00:33:41,790 But to make this problem more interesting, 679 00:33:41,790 --> 00:33:45,240 we're going to allow the integers to be negative. 680 00:33:45,240 --> 00:33:53,670 For example, 7 plus minus 4 times 3 plus minus 5. 681 00:33:53,670 --> 00:33:55,950 So I just added a couple of minuses 682 00:33:55,950 --> 00:34:00,740 to a couple of the numbers here. 683 00:34:00,740 --> 00:34:03,260 Then it's no longer best to pair them this way. 684 00:34:03,260 --> 00:34:06,110 If I pair them this way, like this, 685 00:34:06,110 --> 00:34:10,520 or if I add parentheses this way, I get 3 here, 686 00:34:10,520 --> 00:34:12,960 and I get minus 2 here. 687 00:34:12,960 --> 00:34:16,259 So I get-- the product of that is negative 6, 688 00:34:16,259 --> 00:34:17,750 which i probably not the maximum. 689 00:34:17,750 --> 00:34:19,790 In fact, I can do better, I believe, 690 00:34:19,790 --> 00:34:24,735 by doing the left operator last. 691 00:34:28,469 --> 00:34:31,260 So this, I claim, the best parenthisization, 692 00:34:31,260 --> 00:34:32,760 if I remembered it correctly. 693 00:34:32,760 --> 00:34:43,545 This is, minus 2 times minus 4 is 8, plus 7 is 15. 694 00:34:43,545 --> 00:34:45,170 So I got a positive number-- definitely 695 00:34:45,170 --> 00:34:46,753 better than the negative number I got. 696 00:34:46,753 --> 00:34:48,380 I claim this is the best. 697 00:34:48,380 --> 00:34:50,139 And the key property here is, when 698 00:34:50,139 --> 00:34:51,889 we take a product of two negative numbers, 699 00:34:51,889 --> 00:34:53,179 we get a positive number. 700 00:34:53,179 --> 00:34:56,360 Sometimes, you actually want to make things small, 701 00:34:56,360 --> 00:34:58,620 because small might mean very negative. 702 00:34:58,620 --> 00:35:01,460 You take two very big negative numbers-- 703 00:35:01,460 --> 00:35:03,930 very small negative numbers, in other words. 704 00:35:03,930 --> 00:35:07,490 You take their product, you get a very big product, positively, 705 00:35:07,490 --> 00:35:08,970 because the signs cancel. 706 00:35:08,970 --> 00:35:09,470 OK. 707 00:35:09,470 --> 00:35:11,210 So this seems tricky. 708 00:35:11,210 --> 00:35:12,950 We want to work on substrings, but we 709 00:35:12,950 --> 00:35:15,380 don't know whether we're trying to maximize, 710 00:35:15,380 --> 00:35:16,940 or you might think, well, maybe I'm 711 00:35:16,940 --> 00:35:18,980 trying to maximize the absolute value. 712 00:35:18,980 --> 00:35:19,860 But that's not good. 713 00:35:19,860 --> 00:35:22,580 Maybe overall, on this entire expression, 714 00:35:22,580 --> 00:35:24,410 I get negative 1 million. 715 00:35:24,410 --> 00:35:25,800 And that's not what I wanted. 716 00:35:25,800 --> 00:35:27,570 I wanted to maximize the sum. 717 00:35:27,570 --> 00:35:32,450 So I still need to solve the max evaluation 718 00:35:32,450 --> 00:35:34,820 that I can get, the max parenthesization, 719 00:35:34,820 --> 00:35:38,660 but I also need to solve the min parenthesization. 720 00:35:38,660 --> 00:35:42,200 If I can solve max and min, I'll know the entire range 721 00:35:42,200 --> 00:35:43,680 that I could get. 722 00:35:43,680 --> 00:35:44,930 And I really only-- 723 00:35:44,930 --> 00:35:48,350 I'll care about min especially when it lets me go negative. 724 00:35:48,350 --> 00:35:52,250 But let's just solve, in all cases, the min and the max, 725 00:35:52,250 --> 00:35:53,780 and then just brute force the rest. 726 00:35:53,780 --> 00:35:56,360 That's what I'm going to write down. 727 00:35:56,360 --> 00:35:59,760 So that was some motivation and why we are going 728 00:35:59,760 --> 00:36:02,270 to define subproblems this way. 729 00:36:02,270 --> 00:36:08,390 I'm going to define x of i, comma j, comma opt to be-- 730 00:36:08,390 --> 00:36:13,400 opt, here, is going to be either min or max. 731 00:36:13,400 --> 00:36:16,040 And this is my subproblem expansion. 732 00:36:16,040 --> 00:36:19,040 I really just care about max at the very end, 733 00:36:19,040 --> 00:36:21,480 but I'm going to care about min along the way. 734 00:36:21,480 --> 00:36:25,880 And i, j is going to specify my substring. 735 00:36:25,880 --> 00:36:30,740 So this is going to be the opt value-- 736 00:36:30,740 --> 00:36:34,370 opt stands for "optimum" here, or "optimization." 737 00:36:34,370 --> 00:36:41,780 The opt value I can get for the substring a i star plus 1, 738 00:36:41,780 --> 00:36:51,410 a i plus 1, and so on to star j minus 1, a j minus 1. 739 00:36:51,410 --> 00:36:52,340 OK. 740 00:36:52,340 --> 00:36:55,220 Being careful to get my indices correct here. 741 00:36:55,220 --> 00:37:02,360 And I want 0 less than or equal to i, less than j, 742 00:37:02,360 --> 00:37:04,988 less than equal to n. 743 00:37:04,988 --> 00:37:08,730 I claim and opt like this. 744 00:37:08,730 --> 00:37:09,230 OK. 745 00:37:09,230 --> 00:37:11,810 I'm going to get the min value and the max value separately. 746 00:37:11,810 --> 00:37:13,790 Those are two different subproblems. 747 00:37:13,790 --> 00:37:14,670 This is my expansion. 748 00:37:14,670 --> 00:37:17,240 This is the constraint I'm adding. 749 00:37:17,240 --> 00:37:20,450 And I'm only focusing on this substring from i inclusive 750 00:37:20,450 --> 00:37:22,930 to j exclusive. 751 00:37:22,930 --> 00:37:24,940 OK. 752 00:37:24,940 --> 00:37:27,610 So I claim those are good subproblems. 753 00:37:27,610 --> 00:37:30,490 Let's write down a recurrence relation. 754 00:37:48,210 --> 00:37:48,840 OK. 755 00:37:48,840 --> 00:37:49,340 Relate. 756 00:37:55,840 --> 00:38:01,910 I want to write x of i, j, opt on the left. 757 00:38:01,910 --> 00:38:06,650 And I want to optimize-- so this will be min or max-- 758 00:38:06,650 --> 00:38:09,720 on a set of choices. 759 00:38:09,720 --> 00:38:12,090 What is my set of choices? 760 00:38:12,090 --> 00:38:14,580 Well, like I said, I want to guess 761 00:38:14,580 --> 00:38:17,070 what is the last operation evaluated. 762 00:38:17,070 --> 00:38:20,080 I wrote star i here, but star i is already defined, 763 00:38:20,080 --> 00:38:22,110 so I'm going to use star k. 764 00:38:22,110 --> 00:38:26,760 So I'm going to guess which of my operations between i 765 00:38:26,760 --> 00:38:30,990 plus 1 and j minus 1 is the last one, and I evaluate. 766 00:38:30,990 --> 00:38:34,830 And that decomposes everything left of k. 767 00:38:34,830 --> 00:38:42,880 So that would be x of i, comma k, comma something. 768 00:38:42,880 --> 00:38:48,060 And then we will do operator star k on the part 769 00:38:48,060 --> 00:38:54,280 after k, which is from k to j, something. 770 00:38:54,280 --> 00:38:57,640 And I'm choosing between-- 771 00:38:57,640 --> 00:39:01,180 I think it's i less than k less than j. 772 00:39:01,180 --> 00:39:04,930 k is some operator in between, because I started i plus 1 773 00:39:04,930 --> 00:39:06,260 and I ended j minus 1. 774 00:39:06,260 --> 00:39:09,470 So those are the possible choices for k. 775 00:39:09,470 --> 00:39:10,490 I tried them all. 776 00:39:10,490 --> 00:39:12,950 That's my local brute force. 777 00:39:12,950 --> 00:39:14,990 And then I take what I can get on the left, what 778 00:39:14,990 --> 00:39:18,290 I can get on the right, and multiply or add them 779 00:39:18,290 --> 00:39:22,310 according to whether the operator is plus or times. 780 00:39:22,310 --> 00:39:25,100 Now, should I maximize or minimize this one? 781 00:39:25,100 --> 00:39:27,530 Should I maximize or minimize this one? 782 00:39:27,530 --> 00:39:28,700 I don't know. 783 00:39:28,700 --> 00:39:33,030 So I'm just going to do more local brute force. 784 00:39:33,030 --> 00:39:36,290 Well, let's just say opt prime for the left-- 785 00:39:36,290 --> 00:39:39,080 or maybe I'll call it opt L for the left 786 00:39:39,080 --> 00:39:42,020 and opt R for the right part. 787 00:39:42,020 --> 00:39:44,240 And I'll just add this to my four-loop. 788 00:39:44,240 --> 00:39:50,960 Let's just try opt L and opt R. Just take all possible choices 789 00:39:50,960 --> 00:39:51,950 among min and max. 790 00:39:55,324 --> 00:39:58,770 Now, you could think hard-- and for addition, for example, 791 00:39:58,770 --> 00:40:00,710 if you're maximizing, you really only 792 00:40:00,710 --> 00:40:02,330 need to maximize the two parts. 793 00:40:02,330 --> 00:40:04,690 And if you're minimizing, you can prove you all 794 00:40:04,690 --> 00:40:06,810 need to minimize the two parts. 795 00:40:06,810 --> 00:40:09,380 But for multiplication, it's messy. 796 00:40:09,380 --> 00:40:12,470 It could be, really, any of the options. 797 00:40:12,470 --> 00:40:14,020 Because sometimes, when you minimize, 798 00:40:14,020 --> 00:40:15,020 you get a negative term. 799 00:40:15,020 --> 00:40:18,120 Sometimes, you don't. 800 00:40:18,120 --> 00:40:20,970 And so it depends what you're trying to do. 801 00:40:20,970 --> 00:40:22,460 You have to consider all the signs. 802 00:40:22,460 --> 00:40:24,830 But we don't need to think hard. 803 00:40:24,830 --> 00:40:26,370 We can just try all options. 804 00:40:26,370 --> 00:40:28,310 There's only four choices for opt L 805 00:40:28,310 --> 00:40:30,020 and opt R among min and max. 806 00:40:30,020 --> 00:40:33,050 You could do min-min, min-max, max-min, and max-max. 807 00:40:33,050 --> 00:40:35,690 So try-- it's just a multiplication by 4 808 00:40:35,690 --> 00:40:37,070 in this four-loop. 809 00:40:37,070 --> 00:40:38,540 The big cost is actually this one, 810 00:40:38,540 --> 00:40:43,550 because there are j minus i choices for k. 811 00:40:43,550 --> 00:40:46,550 There's a constant number of choices for opt L and opt R. 812 00:40:46,550 --> 00:40:48,380 And you need to prove that this is correct. 813 00:40:48,380 --> 00:40:50,610 I won't do it here. 814 00:40:50,610 --> 00:40:54,260 But the idea is, if you're trying to minimize or maximize 815 00:40:54,260 --> 00:40:58,550 your sum or product, it's enough to know what 816 00:40:58,550 --> 00:40:59,743 ranges these could come in. 817 00:40:59,743 --> 00:41:01,160 And the optimal choice will always 818 00:41:01,160 --> 00:41:04,020 be an extreme in that range. 819 00:41:04,020 --> 00:41:05,590 We consider all of them here. 820 00:41:05,590 --> 00:41:07,780 And so we get this recurrence. 821 00:41:07,780 --> 00:41:10,290 Now, it needs a base case, and we need 822 00:41:10,290 --> 00:41:14,580 to check that it's acyclic. 823 00:41:14,580 --> 00:41:19,550 But topological order is just increasing j minus i. 824 00:41:19,550 --> 00:41:25,470 This is the usual order for substring problems, 825 00:41:25,470 --> 00:41:27,760 because this is increasing length of the substring. 826 00:41:27,760 --> 00:41:29,528 So start with very tiny substrings. 827 00:41:29,528 --> 00:41:31,320 Here, we'll start with length 1 substrings. 828 00:41:31,320 --> 00:41:32,940 We just have an a, i there. 829 00:41:32,940 --> 00:41:34,680 So that's going to be our base case. 830 00:41:34,680 --> 00:41:37,553 And you grow up to the entire string. 831 00:41:37,553 --> 00:41:38,970 And it doesn't matter how we order 832 00:41:38,970 --> 00:41:41,680 relative to opt as long as we are increasing in j minus i, 833 00:41:41,680 --> 00:41:44,790 because i to k and k to j will always 834 00:41:44,790 --> 00:41:49,500 be strictly smaller than i to j, and so this will be acyclic. 835 00:41:49,500 --> 00:41:55,230 The base case is x of i, i plus 1, opt. 836 00:41:55,230 --> 00:41:56,768 This is always a i. 837 00:41:56,768 --> 00:41:58,560 Doesn't matter what opt is, because there's 838 00:41:58,560 --> 00:42:00,100 nothing-- there's no choice. 839 00:42:00,100 --> 00:42:02,520 You just have a single number in that substring, 840 00:42:02,520 --> 00:42:04,020 because we're exclusive on i plus 1. 841 00:42:06,550 --> 00:42:08,970 And then the original problem we want to solve 842 00:42:08,970 --> 00:42:13,530 is x of 0, n, max. 843 00:42:13,530 --> 00:42:16,510 You could also solve min and see how small you can get it. 844 00:42:16,510 --> 00:42:18,510 So if you wanted to maximize the absolute value, 845 00:42:18,510 --> 00:42:20,940 you could solve the max problem and the min problem 846 00:42:20,940 --> 00:42:25,280 and take the largest of those two options. 847 00:42:25,280 --> 00:42:27,710 And how much time does this take? 848 00:42:27,710 --> 00:42:29,810 Well, how many subproblems are there? 849 00:42:29,810 --> 00:42:32,060 For substring problems, we have n squared subproblems. 850 00:42:32,060 --> 00:42:34,760 Now, we multiply the number of subproblems by 2, 851 00:42:34,760 --> 00:42:36,450 but that's still n squared. 852 00:42:36,450 --> 00:42:38,870 So we have n squared subproblems. 853 00:42:42,560 --> 00:42:45,350 And how much work per subproblem are we doing? 854 00:42:45,350 --> 00:42:49,820 Well, as I mentioned, we're doing j minus i choices for k 855 00:42:49,820 --> 00:42:52,130 and a constant number of choices for opt L and opt R. 856 00:42:52,130 --> 00:42:55,310 So this is theta j minus i, which, if I'll be sloppy, 857 00:42:55,310 --> 00:42:58,070 that's at most big O of n. 858 00:42:58,070 --> 00:43:00,770 And it turns out to be the right answer anyway. 859 00:43:00,770 --> 00:43:05,325 So there's a linear amount of non-recursive work. 860 00:43:05,325 --> 00:43:06,950 In fact, it's like a triangular number, 861 00:43:06,950 --> 00:43:11,365 but that's still theta n cubed. 862 00:43:15,400 --> 00:43:18,820 Same running time as v cubed we just got. 863 00:43:18,820 --> 00:43:20,835 But polynomial time. 864 00:43:20,835 --> 00:43:22,960 And this is pretty impressive, because we're really 865 00:43:22,960 --> 00:43:25,240 brute forcing all possible parenthesizations. 866 00:43:25,240 --> 00:43:28,870 There about 4 to the n, exponentially many, 867 00:43:28,870 --> 00:43:31,000 parenthesizations of an expression. 868 00:43:31,000 --> 00:43:32,770 But we're finding the biggest-- 869 00:43:32,770 --> 00:43:35,420 the one that evaluates the largest value and the one that 870 00:43:35,420 --> 00:43:37,510 evaluates to the smallest value in just n 871 00:43:37,510 --> 00:43:40,500 cubed time-- polynomial. 872 00:43:40,500 --> 00:43:44,130 And a key here was subproblem expansion, 873 00:43:44,130 --> 00:43:46,450 where we, in addition to solving the max problem, 874 00:43:46,450 --> 00:43:50,130 we also solved the min problem, because sometimes, you 875 00:43:50,130 --> 00:43:53,580 want to take two very small negative numbers 876 00:43:53,580 --> 00:43:56,430 and product them together to get a larger positive number. 877 00:43:59,180 --> 00:44:01,010 Cool. 878 00:44:01,010 --> 00:44:01,975 Question? 879 00:44:01,975 --> 00:44:03,350 AUDIENCE: Would anything go wrong 880 00:44:03,350 --> 00:44:06,410 if I added minus or divide? 881 00:44:06,410 --> 00:44:11,050 ERIK DEMAINE: So what if I had operators minus and divide? 882 00:44:11,050 --> 00:44:12,090 It's a good question. 883 00:44:12,090 --> 00:44:15,340 I'm certain that minus should work fine. 884 00:44:15,340 --> 00:44:19,510 If we do min and max, this should still 885 00:44:19,510 --> 00:44:21,850 evaluate the largest thing for division. 886 00:44:21,850 --> 00:44:23,710 I need to think about the cases. 887 00:44:23,710 --> 00:44:26,590 I would guess it works, but what we 888 00:44:26,590 --> 00:44:30,970 need to prove is that the way to maximize or minimize 889 00:44:30,970 --> 00:44:36,250 a division, say, given two numbers in the left and right, 890 00:44:36,250 --> 00:44:39,700 is that it either corresponds to maximizing or minimizing 891 00:44:39,700 --> 00:44:42,610 the thing on the left and then maximizing or minimizing 892 00:44:42,610 --> 00:44:43,650 the thing on the right. 893 00:44:43,650 --> 00:44:45,400 So as long as you have this kind of-- it's 894 00:44:45,400 --> 00:44:46,600 not exactly monotonicity. 895 00:44:46,600 --> 00:44:48,760 It's just that, in order to compute max or min, 896 00:44:48,760 --> 00:44:53,950 it suffices to know the max and min of the two parts. 897 00:44:53,950 --> 00:44:55,280 It's like interval arithmetic. 898 00:44:55,280 --> 00:44:56,530 You know, interval arithmetic? 899 00:44:56,530 --> 00:44:58,960 I want to know, what are the extremes I 900 00:44:58,960 --> 00:45:01,180 can get on the output of a division 901 00:45:01,180 --> 00:45:03,340 if I'm given that a number is in some interval here 902 00:45:03,340 --> 00:45:04,420 and some interval here? 903 00:45:04,420 --> 00:45:07,232 If the answer is always, use one of the extreme endpoints 904 00:45:07,232 --> 00:45:09,190 here and use one of the extreme endpoints here, 905 00:45:09,190 --> 00:45:10,440 then this algorithm will work. 906 00:45:10,440 --> 00:45:13,690 Otherwise, all bets are off. 907 00:45:13,690 --> 00:45:14,770 Cool. 908 00:45:14,770 --> 00:45:16,210 So if you negate-- 909 00:45:16,210 --> 00:45:18,130 if you put a minus here, that will work fine, 910 00:45:18,130 --> 00:45:19,520 because it's negating this range. 911 00:45:19,520 --> 00:45:21,320 And then it's just like sum. 912 00:45:21,320 --> 00:45:21,820 But-- 913 00:45:21,820 --> 00:45:22,987 AUDIENCE: [INAUDIBLE] 914 00:45:22,987 --> 00:45:25,570 ERIK DEMAINE: Oh, a divider-- if you're careful about 0, yeah. 915 00:45:25,570 --> 00:45:27,970 Actually, it doesn't work, because we 916 00:45:27,970 --> 00:45:31,780 care about how close this can get to 0 for division. 917 00:45:31,780 --> 00:45:35,170 It might be enough to consider those. 918 00:45:35,170 --> 00:45:40,760 It's like, instead of minimizing and-- instead of computing this 919 00:45:40,760 --> 00:45:43,280 entire interval, if this interval spans 0, 920 00:45:43,280 --> 00:45:45,080 maybe I need to know-- 921 00:45:45,080 --> 00:45:48,350 if 0 is here, I need to know how close to 0 922 00:45:48,350 --> 00:45:50,300 I can get on the left side and how close to 0 923 00:45:50,300 --> 00:45:51,467 I can get on the right side. 924 00:45:51,467 --> 00:45:53,280 Still just four quantities I need to know. 925 00:45:53,280 --> 00:45:55,072 I would guess, for division, that's enough. 926 00:45:55,072 --> 00:45:55,930 Yeah. 927 00:45:55,930 --> 00:45:56,920 Nice. 928 00:45:56,920 --> 00:45:57,920 Solved a little problem. 929 00:45:57,920 --> 00:46:00,045 Then, we would be multiplying the subproblem space, 930 00:46:00,045 --> 00:46:01,858 instead of by 2, by 4. 931 00:46:01,858 --> 00:46:03,650 Hey, maybe we should put this on the final. 932 00:46:03,650 --> 00:46:04,673 No, just kidding. 933 00:46:04,673 --> 00:46:07,310 Now it's in lecture, so we can't use it. 934 00:46:07,310 --> 00:46:10,970 But it's a cool set of problems, right? 935 00:46:10,970 --> 00:46:14,060 You can do a lot with dynamic programming. 936 00:46:14,060 --> 00:46:16,340 You don't need to be that clever, just brute force 937 00:46:16,340 --> 00:46:17,870 anything that seems hard. 938 00:46:17,870 --> 00:46:19,880 And when it works, it works great. 939 00:46:22,490 --> 00:46:25,370 And this class is all about understanding when it works 940 00:46:25,370 --> 00:46:27,110 and when it doesn't work. 941 00:46:27,110 --> 00:46:31,330 Of course, we will only give you problems where it works. 942 00:46:31,330 --> 00:46:33,660 But it's important to understand when it doesn't work. 943 00:46:33,660 --> 00:46:36,420 For example, DAG shortest paths-- that algorithm 944 00:46:36,420 --> 00:46:38,430 on a non-DAG, very bad. 945 00:46:38,430 --> 00:46:40,470 Infinite time. 946 00:46:40,470 --> 00:46:41,770 OK. 947 00:46:41,770 --> 00:46:45,400 Our last example is piano fingering. 948 00:46:54,030 --> 00:47:05,730 Here, we're given a sequence of notes t 0, t 1-- 949 00:47:05,730 --> 00:47:11,280 t for note-- up to t n minus 1. 950 00:47:11,280 --> 00:47:12,765 These are single notes. 951 00:47:15,390 --> 00:47:18,060 And all of the single notes-- 952 00:47:18,060 --> 00:47:19,830 all of the single notes, right? 953 00:47:19,830 --> 00:47:24,040 And we have fingers on our hands. 954 00:47:24,040 --> 00:47:25,860 This is not like two-finger algorithm. 955 00:47:25,860 --> 00:47:29,830 This is the five-finger algorithm. 956 00:47:29,830 --> 00:47:31,470 So in general, I'm going to assume 957 00:47:31,470 --> 00:47:38,260 an arbitrary anthropomorphic object. 958 00:47:38,260 --> 00:47:40,290 So this is 5 for humans-- 959 00:47:40,290 --> 00:47:41,130 most humans. 960 00:47:41,130 --> 00:47:45,570 Some humans-- I think the maximum on each hand is 7. 961 00:47:45,570 --> 00:47:46,470 Could be smaller. 962 00:47:46,470 --> 00:47:48,330 Maybe you've had an accident. 963 00:47:48,330 --> 00:47:52,560 I'll solve it for arbitrary F. And what we would like to do 964 00:47:52,560 --> 00:47:58,530 is assign fingers to notes to tell our pianist which 965 00:47:58,530 --> 00:48:00,103 finger to use for each note. 966 00:48:00,103 --> 00:48:01,770 Normally, when you're given sheet music, 967 00:48:01,770 --> 00:48:04,260 it just gives you a sequence of notes you want to play. 968 00:48:04,260 --> 00:48:07,050 It doesn't tell you which finger you want to play it with, 969 00:48:07,050 --> 00:48:10,980 unless you have some nice training booklets 970 00:48:10,980 --> 00:48:13,230 and they have a little number on top of each. 971 00:48:13,230 --> 00:48:15,840 And I number them 1, 2, 3, 4 or 5, 972 00:48:15,840 --> 00:48:19,530 and symmetrically, 1, 2, 3, 4, 5. 973 00:48:19,530 --> 00:48:25,050 Here's a giant piano for my giant hands. 974 00:48:25,050 --> 00:48:27,180 If Jason were here, he could sing these notes. 975 00:48:27,180 --> 00:48:29,475 So maybe I play this with my first finger, 976 00:48:29,475 --> 00:48:30,600 this with my second finger. 977 00:48:30,600 --> 00:48:32,100 Let's just say I'm doing a scale. 978 00:48:32,100 --> 00:48:33,035 So I can walk. 979 00:48:33,035 --> 00:48:34,410 And now, I think, the typical way 980 00:48:34,410 --> 00:48:37,410 to do a scale is to reach over with your first finger-- 981 00:48:37,410 --> 00:48:39,990 second finger, I guess, and then do something like this. 982 00:48:39,990 --> 00:48:40,830 No? 983 00:48:40,830 --> 00:48:42,060 OK. 984 00:48:42,060 --> 00:48:45,420 Clearly, I don't know scales or how to play a piano. 985 00:48:45,420 --> 00:48:47,200 But there's limits here. 986 00:48:47,200 --> 00:48:49,200 I can-- if I'm going from this note 987 00:48:49,200 --> 00:48:52,560 and I want to go to another note over here, 988 00:48:52,560 --> 00:48:55,590 OK, maybe I have a decent span from first finger 989 00:48:55,590 --> 00:48:58,090 to fifth finger, but my span for my first finger 990 00:48:58,090 --> 00:49:00,030 to my second finger is not as big. 991 00:49:00,030 --> 00:49:01,037 I can't reach as far. 992 00:49:01,037 --> 00:49:03,120 So if I want to play this note and then this note, 993 00:49:03,120 --> 00:49:06,480 I would like to start here with a very extreme figure 994 00:49:06,480 --> 00:49:08,940 on the left and then go to at a very extreme figure 995 00:49:08,940 --> 00:49:10,650 on the right. 996 00:49:10,650 --> 00:49:14,070 I'm going to formalize this problem pretty abstractly, 997 00:49:14,070 --> 00:49:18,360 because I don't want to get into music performance. 998 00:49:18,360 --> 00:49:23,760 I'm going to say that there is a metric d for, 999 00:49:23,760 --> 00:49:26,760 if I'm at note t with finger f, and I 1000 00:49:26,760 --> 00:49:28,620 want to go to note t prime with finger 1001 00:49:28,620 --> 00:49:34,980 f prime, then this function, d of t, f, t prime, f prime, 1002 00:49:34,980 --> 00:49:36,930 gives me the difficulty of doing that-- 1003 00:49:42,530 --> 00:49:50,870 the difficulty of playing note t with finger f 1004 00:49:50,870 --> 00:49:58,390 and then playing note t prime with finger f prime. 1005 00:49:58,390 --> 00:50:01,390 This w is "with." 1006 00:50:01,390 --> 00:50:03,030 So this is a transition difficulty. 1007 00:50:03,030 --> 00:50:06,063 I'm not going to worry about the difficulty of the whole piece 1008 00:50:06,063 --> 00:50:08,230 other than saying, well, I've got to play this note, 1009 00:50:08,230 --> 00:50:09,250 then I've got to play this note. 1010 00:50:09,250 --> 00:50:10,660 And for now, just single notes. 1011 00:50:10,660 --> 00:50:12,585 You play a single note with your right hand, 1012 00:50:12,585 --> 00:50:13,960 then you play another single note 1013 00:50:13,960 --> 00:50:15,190 with your right hand, then another single note 1014 00:50:15,190 --> 00:50:16,070 with your right hand. 1015 00:50:16,070 --> 00:50:18,280 Let's assume no pauses for now-- no rests. 1016 00:50:20,960 --> 00:50:21,460 Great. 1017 00:50:21,460 --> 00:50:25,720 So we have this difficulty from going from the ith note 1018 00:50:25,720 --> 00:50:27,490 to the i plus first note. 1019 00:50:27,490 --> 00:50:32,470 And then our goal is to minimize the sum of difficulties. 1020 00:50:32,470 --> 00:50:43,390 Minimum sum of d ti fi ti plus 1, plus 1. 1021 00:50:43,390 --> 00:50:48,622 And these-- f i's and f i plus 1 is what we want to compute. 1022 00:50:48,622 --> 00:50:50,080 We don't know which fingers to use. 1023 00:50:50,080 --> 00:50:53,642 We're only given which notes to play. 1024 00:50:53,642 --> 00:50:55,100 This is actually a natural problem. 1025 00:50:55,100 --> 00:50:56,540 There are lots of papers about this problem. 1026 00:50:56,540 --> 00:50:57,665 I've read a bunch of them-- 1027 00:50:57,665 --> 00:51:00,920 obviously not super well, but how to play scales. 1028 00:51:00,920 --> 00:51:03,590 But there are notes like-- 1029 00:51:03,590 --> 00:51:06,080 there are constraints in this-- usually, 1030 00:51:06,080 --> 00:51:10,945 people write this metric as a sum of different penalty terms, 1031 00:51:10,945 --> 00:51:12,320 if I want to minimize difficulty. 1032 00:51:12,320 --> 00:51:18,720 Difficulty is high if I play a note far on the left. 1033 00:51:18,720 --> 00:51:22,670 So if I go from a low note to a high note, 1034 00:51:22,670 --> 00:51:25,892 that's easier to do if I use a lower-numbered finger 1035 00:51:25,892 --> 00:51:27,350 and go to a higher-numbered finger. 1036 00:51:27,350 --> 00:51:31,280 You don't want to go, like I was doing, 1037 00:51:31,280 --> 00:51:35,840 from a high-numbered finger to a low-numbered finger 1038 00:51:35,840 --> 00:51:37,010 to play a note on the right. 1039 00:51:37,010 --> 00:51:37,880 That's annoying. 1040 00:51:37,880 --> 00:51:39,410 I would like to do an assignment, if I can, 1041 00:51:39,410 --> 00:51:40,130 that avoids that. 1042 00:51:40,130 --> 00:51:43,100 So I'll just have some penalty of, like, 100 if that happens, 1043 00:51:43,100 --> 00:51:46,520 and 0 if it doesn't happen, sum up a bunch of terms like that. 1044 00:51:46,520 --> 00:51:49,720 Other examples are, avoid the fourth and fifth fingers-- 1045 00:51:49,720 --> 00:51:50,690 weak fingers-- 1046 00:51:50,690 --> 00:51:55,370 or, if I'm playing a portion of the song that is legato, 1047 00:51:55,370 --> 00:51:57,500 then I don't want to use the same finger 1048 00:51:57,500 --> 00:52:00,590 to play two notes right after the other. 1049 00:52:00,590 --> 00:52:02,640 I've got to use two different fingers for that. 1050 00:52:02,640 --> 00:52:06,290 So you have a penalty if f i equals f i plus 1 and these two 1051 00:52:06,290 --> 00:52:08,220 notes are not the same. 1052 00:52:08,220 --> 00:52:10,520 Then-- and we're in legato mode-- 1053 00:52:10,520 --> 00:52:12,465 then we add a penalty term. 1054 00:52:12,465 --> 00:52:13,340 And things like that. 1055 00:52:13,340 --> 00:52:17,480 I would prefer-- if I'm going from a very low note to a very 1056 00:52:17,480 --> 00:52:20,000 high note, I would like to use more extreme fingers. 1057 00:52:20,000 --> 00:52:21,900 Things like that. 1058 00:52:21,900 --> 00:52:25,530 But we're just going to assume this d function is given to us. 1059 00:52:25,530 --> 00:52:30,710 It's some polynomial size. 1060 00:52:30,710 --> 00:52:32,930 If you imagine the notes on your keyboard 1061 00:52:32,930 --> 00:52:37,592 are end notes or m notes, then some polynomial and m size 1062 00:52:37,592 --> 00:52:38,300 to this function. 1063 00:52:43,430 --> 00:52:46,130 How do we solve this problem? 1064 00:52:46,130 --> 00:52:57,600 I'm running low on time, so let me give you the idea. 1065 00:53:01,360 --> 00:53:03,810 And this is going to use subproblem expansion. 1066 00:53:07,100 --> 00:53:12,320 So the subproblems are going to be x of i, comma f-- 1067 00:53:12,320 --> 00:53:21,520 this is the minimum total difficulty to play suffix-- 1068 00:53:21,520 --> 00:53:23,120 because I like suffixes-- 1069 00:53:23,120 --> 00:53:43,290 t i up to t n minus 1, starting with finger f on note t i. 1070 00:53:43,290 --> 00:53:46,620 The obvious subproblems would be without this constraint. 1071 00:53:46,620 --> 00:53:50,350 This here is a problem constraint. 1072 00:53:50,350 --> 00:53:52,690 And you could try to define the subproblems just as, 1073 00:53:52,690 --> 00:53:55,060 what's the best way to play a suffix? 1074 00:53:55,060 --> 00:53:56,590 But I claim it's important to know 1075 00:53:56,590 --> 00:53:57,880 which finger we start with. 1076 00:53:57,880 --> 00:54:00,250 So we're going to multiply the number of subproblems 1077 00:54:00,250 --> 00:54:02,320 by capital F, which is just 5. 1078 00:54:02,320 --> 00:54:04,845 So a very small subproblem expansion. 1079 00:54:04,845 --> 00:54:06,220 And then we're going to constrain 1080 00:54:06,220 --> 00:54:07,690 these subproblems to say, well, what if I 1081 00:54:07,690 --> 00:54:08,680 started with my first finger? 1082 00:54:08,680 --> 00:54:10,347 What if I started with my second finger? 1083 00:54:10,347 --> 00:54:11,740 What if-- up to the fifth finger. 1084 00:54:11,740 --> 00:54:14,050 Try them all. 1085 00:54:14,050 --> 00:54:18,820 Then, it turns out, I can write a relation, which 1086 00:54:18,820 --> 00:54:24,760 is X of i f equals the min. 1087 00:54:24,760 --> 00:54:26,440 What should I min over? 1088 00:54:26,440 --> 00:54:29,410 I'll just guess this-- 1089 00:54:29,410 --> 00:54:33,370 I'm already told what my first finger is to use-- 1090 00:54:33,370 --> 00:54:35,387 which finger I should use for t i. 1091 00:54:35,387 --> 00:54:36,970 So what's the next thing that matters? 1092 00:54:36,970 --> 00:54:40,210 Well, I guess what finger to use for the t i plus 1, 1093 00:54:40,210 --> 00:54:41,470 the very next note. 1094 00:54:41,470 --> 00:54:43,210 What is the next finger I use? 1095 00:54:43,210 --> 00:54:47,830 I will call that f prime and minimize over 1096 00:54:47,830 --> 00:54:49,900 f prime, between one and capital, 1097 00:54:49,900 --> 00:54:55,060 F of the remaining suffix, starting 1098 00:54:55,060 --> 00:55:01,060 with f prime, plus my difficulty function from t i, comma f, 1099 00:55:01,060 --> 00:55:05,200 to t i plus 1, comma f prime. 1100 00:55:05,200 --> 00:55:07,300 End of bracket. 1101 00:55:07,300 --> 00:55:08,410 OK. 1102 00:55:08,410 --> 00:55:10,780 So there's kind of a lot going on here. 1103 00:55:10,780 --> 00:55:15,478 This is a lowercase f prime. 1104 00:55:15,478 --> 00:55:17,020 But actually, if you think about what 1105 00:55:17,020 --> 00:55:18,687 I would like to write the recurrence on, 1106 00:55:18,687 --> 00:55:20,767 well, I start with the suffix i, I 1107 00:55:20,767 --> 00:55:22,600 would like to recurse on the smaller suffix, 1108 00:55:22,600 --> 00:55:24,040 so that's X of i plus 1. 1109 00:55:27,030 --> 00:55:30,270 So here, if I know that I'm prioritizing my finger 1110 00:55:30,270 --> 00:55:33,450 number for i, will then I'm in order 1111 00:55:33,450 --> 00:55:34,980 to even call this function, I need 1112 00:55:34,980 --> 00:55:36,618 to know what finger I'm using 4 plus 1. 1113 00:55:36,618 --> 00:55:38,160 Once you decide on these subproblems, 1114 00:55:38,160 --> 00:55:41,550 it's really obvious you need to guess, what is the next finger, 1115 00:55:41,550 --> 00:55:44,610 and then recurse on that finger-- 1116 00:55:44,610 --> 00:55:46,620 recurse on the remaining suffix of that finger. 1117 00:55:46,620 --> 00:55:51,120 Now, why did we need to know what these fingers were? 1118 00:55:51,120 --> 00:55:54,210 Why not just guess what the first finger is? 1119 00:55:54,210 --> 00:55:56,340 Well, it has to do with this difficulty function. 1120 00:55:56,340 --> 00:55:57,840 For this difficulty function, I know 1121 00:55:57,840 --> 00:55:59,757 that I want to measure the difficulty from t i 1122 00:55:59,757 --> 00:56:01,420 to t i plus 1. 1123 00:56:01,420 --> 00:56:04,510 And to do that, because this function is parameterized 1124 00:56:04,510 --> 00:56:07,540 by four things, I need to know both the finger for t i 1125 00:56:07,540 --> 00:56:10,660 and, at the same time, the finger for t i plus 1. 1126 00:56:10,660 --> 00:56:14,770 If I remove this f, I could add a min over one finger, 1127 00:56:14,770 --> 00:56:17,590 but I can't really add a min over two fingers. 1128 00:56:17,590 --> 00:56:20,860 So what this does, by parameterizing by f here 1129 00:56:20,860 --> 00:56:25,300 and writing down the optimal for each starting finger f, 1130 00:56:25,300 --> 00:56:29,020 I can-- in some sense, I'm remembering, 1131 00:56:29,020 --> 00:56:32,830 in this call, what finger I started with. 1132 00:56:32,830 --> 00:56:35,500 Because I told it, you have to start with finger f prime. 1133 00:56:35,500 --> 00:56:42,240 And so locally to X i, f, I know what finger f prime 1134 00:56:42,240 --> 00:56:43,500 is being used for t i plus 1. 1135 00:56:43,500 --> 00:56:45,780 And also, because of the definition of X i, f, 1136 00:56:45,780 --> 00:56:48,150 I know what finger I'm using for t i. 1137 00:56:48,150 --> 00:56:50,280 And so I get to know both of these fingers. 1138 00:56:50,280 --> 00:56:52,800 One comes out of this min and the other 1139 00:56:52,800 --> 00:56:55,510 is given to me as this parameter. 1140 00:56:55,510 --> 00:56:57,810 And then, of course, if I can solve these problems, 1141 00:56:57,810 --> 00:57:04,110 I can solve the original problem by just one more min of 1 1142 00:57:04,110 --> 00:57:10,913 up to capital F of x 0 little f. 1143 00:57:10,913 --> 00:57:12,580 I don't know which finger to start with, 1144 00:57:12,580 --> 00:57:14,560 but that's just f choices. 1145 00:57:14,560 --> 00:57:18,440 And so then, this recurrence gives me the overall solution. 1146 00:57:18,440 --> 00:57:20,750 And I'll just jump to the time. 1147 00:57:20,750 --> 00:57:24,800 We need a base case and topological order. 1148 00:57:24,800 --> 00:57:28,660 But it is n f squared time. 1149 00:57:28,660 --> 00:57:31,240 There are n times f subproblems here. 1150 00:57:31,240 --> 00:57:34,960 And for each one, I'm doing an optimization over f choices, 1151 00:57:34,960 --> 00:57:37,270 so I get n times f squared. 1152 00:57:37,270 --> 00:57:38,160 It's a polynomial. 1153 00:57:38,160 --> 00:57:40,390 And if f is a constant, this is actually linear time. 1154 00:57:40,390 --> 00:57:42,280 Very fast DP. 1155 00:57:42,280 --> 00:57:44,800 Now, what I described here is for one hand, 1156 00:57:44,800 --> 00:57:46,120 one note at a time. 1157 00:57:46,120 --> 00:57:49,230 But you can generalize this to two hands, each with one note. 1158 00:57:49,230 --> 00:57:50,480 Well, that's just ten fingers. 1159 00:57:50,480 --> 00:57:53,260 So you could solve this separately for the right hand 1160 00:57:53,260 --> 00:57:55,550 and left hand if you know which notes are being played 1161 00:57:55,550 --> 00:57:56,800 with left hand and right hand. 1162 00:57:56,800 --> 00:58:01,040 But some pieces, that's not obvious. 1163 00:58:01,040 --> 00:58:03,910 So to make it more interesting, what if you have multiple notes 1164 00:58:03,910 --> 00:58:04,720 at the same time? 1165 00:58:04,720 --> 00:58:05,590 And let's say-- 1166 00:58:05,590 --> 00:58:09,310 I think it's reasonable to say you can only play up to f notes 1167 00:58:09,310 --> 00:58:12,457 at a time, 1 for each finger. 1168 00:58:12,457 --> 00:58:14,290 And so you have an upper bound on the number 1169 00:58:14,290 --> 00:58:18,730 of notes at a time that we're playing, which is good. 1170 00:58:18,730 --> 00:58:22,480 Oh, I have a drawing of this DP, by the way, 1171 00:58:22,480 --> 00:58:25,570 as a subproblem DAG. 1172 00:58:25,570 --> 00:58:27,340 This is the original problem, which 1173 00:58:27,340 --> 00:58:30,680 is, we don't know which finger to start with. 1174 00:58:30,680 --> 00:58:33,310 But then we just have a complete bipartite graph here, 1175 00:58:33,310 --> 00:58:35,440 where we write on each of these edges, what 1176 00:58:35,440 --> 00:58:38,410 is the difficulty of this transition? 1177 00:58:38,410 --> 00:58:41,170 The y-axis here is which finger I'm using-- 1178 00:58:41,170 --> 00:58:43,330 1, 2, 3, 4, 5-- and the x-axis is 1179 00:58:43,330 --> 00:58:45,160 which suffix I'm considering. 1180 00:58:45,160 --> 00:58:47,470 Which note do I start on? 1181 00:58:47,470 --> 00:58:50,320 And so you could solve this with shortest paths in a DAG, 1182 00:58:50,320 --> 00:58:52,150 or you could just solve it directly 1183 00:58:52,150 --> 00:58:54,770 as DP, either top-down or bottom-up. 1184 00:58:54,770 --> 00:58:56,690 OK. 1185 00:58:56,690 --> 00:59:01,340 Jumping ahead, if you do multiple notes at a time, 1186 00:59:01,340 --> 00:59:04,760 instead of this finger choice, which just had f choices, 1187 00:59:04,760 --> 00:59:05,510 we have-- 1188 00:59:08,312 --> 00:59:10,980 what do I write here? 1189 00:59:10,980 --> 00:59:19,370 t to the f possible states, where 1190 00:59:19,370 --> 00:59:23,630 t is the maximum number of notes that I could play at once. 1191 00:59:28,110 --> 00:59:30,810 And usually, this is at most f, 1 for finger. 1192 00:59:30,810 --> 00:59:32,790 But we could generalize. 1193 00:59:32,790 --> 00:59:34,455 And this is number of fingers. 1194 00:59:37,230 --> 00:59:42,690 So I could deal with all 10 fingers of a typical human set 1195 00:59:42,690 --> 00:59:43,530 of arms-- 1196 00:59:43,530 --> 00:59:46,080 hands-- and say there's at most 10. 1197 00:59:46,080 --> 00:59:47,520 And so this is 10 to the 10. 1198 00:59:47,520 --> 00:59:50,220 It's a big constant, but it's constant-- 1199 00:59:50,220 --> 00:59:52,260 like 1 billion right? 1200 00:59:52,260 --> 00:59:54,340 10 billion? 1201 00:59:54,340 --> 00:59:56,630 But then it's that times n. 1202 00:59:56,630 --> 00:59:59,090 And maybe that squared times n will 1203 00:59:59,090 --> 01:00:01,640 let me exhaustively enumerate all of the possible things 1204 01:00:01,640 --> 01:00:05,240 I could do be doing with all of my hands. 1205 01:00:05,240 --> 01:00:08,240 You can apply this not only to piano fingering, 1206 01:00:08,240 --> 01:00:11,193 but also to guitar fingering-- also to Rock Band. 1207 01:00:11,193 --> 01:00:12,860 Rock Band is an easy case where you just 1208 01:00:12,860 --> 01:00:17,385 have five buttons, and usually only four fingers that you use. 1209 01:00:17,385 --> 01:00:19,010 And this doesn't really make any sound, 1210 01:00:19,010 --> 01:00:20,820 so it's not that exciting. 1211 01:00:20,820 --> 01:00:26,390 So the case where f equals 4 you can apply to optimally figure 1212 01:00:26,390 --> 01:00:29,300 out which finger-- once you have a difficulty function of what 1213 01:00:29,300 --> 01:00:33,320 transitions are easy and hard for Rock Band, 1214 01:00:33,320 --> 01:00:35,750 then you can optimally figure out your fingering 1215 01:00:35,750 --> 01:00:37,520 for Rock Band songs. 1216 01:00:37,520 --> 01:00:43,700 With a real guitar, this is a little bit harder 1217 01:00:43,700 --> 01:00:45,620 because there are actually multiple ways 1218 01:00:45,620 --> 01:00:46,850 to play the same note. 1219 01:00:46,850 --> 01:00:53,990 For example, I can play the note of this string like this. 1220 01:00:53,990 --> 01:00:55,880 These should both sound the same-- 1221 01:00:55,880 --> 01:01:00,590 if my guitar were perfectly tuned, which it's not. 1222 01:01:00,590 --> 01:01:02,600 And that's properties of strings and the way 1223 01:01:02,600 --> 01:01:04,700 these things are played. 1224 01:01:04,700 --> 01:01:06,770 So in addition to what finger I use, 1225 01:01:06,770 --> 01:01:09,560 I should also decide which string to play that note on. 1226 01:01:09,560 --> 01:01:12,200 If all I'm given is sheet music, different notes to play, 1227 01:01:12,200 --> 01:01:14,570 another thing I could guess is which 1228 01:01:14,570 --> 01:01:16,700 string to play that note on. 1229 01:01:16,700 --> 01:01:21,218 So for example, maybe I want to play my favorite song here. 1230 01:01:21,218 --> 01:01:25,664 [PLAYING MUSIC] 1231 01:01:25,664 --> 01:01:27,600 AUDIENCE: [APPLAUSE] 1232 01:01:27,600 --> 01:01:29,990 ERIK DEMAINE: Super Mario Brothers, my favorite song. 1233 01:01:29,990 --> 01:01:32,157 I could keep going, but I actually can't keep going. 1234 01:01:32,157 --> 01:01:34,040 It won't be as impressive. 1235 01:01:34,040 --> 01:01:36,200 I don't actually know how to play guitar. 1236 01:01:36,200 --> 01:01:38,870 But there are a lot of choices there, right? 1237 01:01:38,870 --> 01:01:45,380 I started with playing this note down on this string. 1238 01:01:45,380 --> 01:01:46,190 That's good. 1239 01:01:46,190 --> 01:01:49,240 I could have also played it on this string. 1240 01:01:49,240 --> 01:01:50,870 But that's more work for my finger, 1241 01:01:50,870 --> 01:01:52,570 so I have a penalty function that 1242 01:01:52,570 --> 01:01:55,970 says, well, if I play an open string, that's a lot easier. 1243 01:01:55,970 --> 01:01:58,300 And then I had a transition from here-- 1244 01:01:58,300 --> 01:02:01,390 this note [PLAYING A NOTE] to this note [PLAYING A NOTE] 1245 01:02:01,390 --> 01:02:02,080 to this note. 1246 01:02:02,080 --> 01:02:05,740 [PLAYING A NOTE] And if you focus on my fingering here, 1247 01:02:05,740 --> 01:02:09,490 I chose to use my index finger for the first one, 1248 01:02:09,490 --> 01:02:11,830 because that index finger is always the easiest to use, 1249 01:02:11,830 --> 01:02:13,205 but it also gives me lots of room 1250 01:02:13,205 --> 01:02:14,950 to move my pinky over to here. 1251 01:02:14,950 --> 01:02:18,320 And then I like to use my middle finger to come up here. 1252 01:02:18,320 --> 01:02:20,050 You could also use your index finger. 1253 01:02:20,050 --> 01:02:21,740 It's just a little bit more of a reach. 1254 01:02:21,740 --> 01:02:23,830 So you have to define some difficulty function. 1255 01:02:23,830 --> 01:02:26,650 It might depend on how big your fingers are. 1256 01:02:26,650 --> 01:02:28,660 But you can do that, and then optimize, 1257 01:02:28,660 --> 01:02:31,360 using these algorithms, what is the best guitar 1258 01:02:31,360 --> 01:02:33,790 fingering for a given piece-- 1259 01:02:33,790 --> 01:02:36,070 one note a time or several notes at a time. 1260 01:02:36,070 --> 01:02:38,170 You could even add in parameters like, 1261 01:02:38,170 --> 01:02:41,200 oh, maybe I want to play a bar. 1262 01:02:41,200 --> 01:02:43,090 That's not a perfect bar. 1263 01:02:43,090 --> 01:02:46,000 But this would be great for my playing this note 1264 01:02:46,000 --> 01:02:49,780 down here and this note here-- 1265 01:02:49,780 --> 01:02:51,690 bad example. 1266 01:02:51,690 --> 01:02:53,440 So you could do other things with a guitar 1267 01:02:53,440 --> 01:02:57,430 to make it more interesting and generalize this dynamic program 1268 01:02:57,430 --> 01:02:58,390 suitably. 1269 01:02:58,390 --> 01:02:59,920 But I think this gives you a flavor 1270 01:02:59,920 --> 01:03:03,700 how, with subproblem expansion, I 1271 01:03:03,700 --> 01:03:06,700 can capture almost any aspect of a problem that I want. 1272 01:03:06,700 --> 01:03:09,670 As long as the number of states that I need to keep track of 1273 01:03:09,670 --> 01:03:13,090 is small, I can just multiply the number of subproblems 1274 01:03:13,090 --> 01:03:16,480 by that state, and I can keep track of any kind of transition 1275 01:03:16,480 --> 01:03:20,260 from one state to another, which I could also do with taking 1276 01:03:20,260 --> 01:03:22,060 the product of a graph. 1277 01:03:22,060 --> 01:03:24,700 But dynamic programming gives you a kind of methodical way 1278 01:03:24,700 --> 01:03:28,300 to think about this, by figuring out some property-- 1279 01:03:28,300 --> 01:03:32,530 in this case, the state of how my fingers are applied 1280 01:03:32,530 --> 01:03:35,770 to the instrument-- and then just sort of brute forcing 1281 01:03:35,770 --> 01:03:36,620 the rest-- 1282 01:03:36,620 --> 01:03:39,600 a very powerful framework.