I've been practicing a few problems here and there, and I notice that my mind kind of freaks out whenever I encounter a problem that might involve some sort of brute force solution (even if it doesn't). The Pancakes problem from the qualifying round is a good example - it didn't even require brute force, but from the structure of the problem, I didn't catch on to the fact that there's a systematic way to make progress and move forward.
Moving forward is particularly difficult for me in these types of problems. It's easy to setup some sort of enumeration of states so that I can do a breadth first search or depth first search, for example. But then there's the fear of encountering cycles.
An easy example is the classic Towers of Hanoi (
https://en.wikipedia.org/wiki/Tower_of_Hanoi) problem. Obviously, I can look at the solution to see what they did, but without doing that, my thought process goes like this:
1.) Think of a couple of examples (using numbers to represent the size of the disk - smaller number is a smaller disk).
1
2
3 _ _
Valid moves? I can move "1" to either of the empty slots. Doesn't matter which, since it's symmetrical.
2
3 1 _
Valid moves?
a.) I could move "1" to the empty spot (silly, though, since it's symmetrical).
b.) I could move "2" to the empty spot.
c.) I could move "1" back to on top of number 2.
Obviously "c" isn't making progress toward a solution, and it's stupid. If I were playing the game myself, I can easily tell that moving "1" back to "2" is not making progress toward finding a solution.
But how do I express this so that the algorithm knows this?
--
So in short, my mind tries to think of a way to iterate through all possible "next states". But I get into trouble when I realize that I might end up going back to a "previous state". Then I get a little flustered about how to proceed.
--
Solution:
Looking at the solution, it says that the key to solving the problem is to realize that it can be "broken down into a collection of smaller sub-problems, to each of which that same general solving procedure that we are seeking applies".
So I guess the procedure is something like:
1.) Realize that, "Hey, if there were n-1 disks already stacked on a different peg, I can move the nth disk to the empty peg. Then I can use that same procedure to move the n-1 disks onto the nth disk."
2.) Then realize that the process will end when n gets low.
---
Looking at the solution, it's a systematic procedure. There's an observation that the problem can be broken up into smaller subproblems that, when combined, form a complete solution.
It's sometimes tricky for me to make this observation. It's sometimes difficult to prove in my mind that the smaller problems do, in fact, form the larger solution. As you can see from my convoluted thought process above, I don't make any observation about breaking the problem into subproblems.
Instead, I start with the big problem, then see what valid "moves" I have at each step. Then I get into trouble when I realize that I'm not systematically moving forward toward a solution.
How can I improve my ability to identify subproblems, and realize properties of the problem that allow for it to be build from these smaller subproblems? I guess the solution is to just do more of these types of problems?