ECS 110: Data Structures and Programming Discussion Section Notes -- Week 7 John Black (blackj@cs.ucdavis.edu) Announcements: We STRONGLY recommend you start on HW4 before the 9th week of classes. It is quite a challenging problem and you'll be getting far fewer details on how to attack the problem than in previous assignments. 1. Map Coloring --------------- The 4-color theorem was one of the several famous longstanding problems which were settled this century. The problem is to color a map with only 4 colors such that no two adjacent regions have the same color. After all, this would make it hard to distinguish different countries on a map at a glance. (Note that sharing a border means that there is a line segment between them, not just an intersection point, so in the diagram below, A and B share a border, but A and D do not.) +---+---+ | A | B | +---+---+ | C | D | +---+---+ Now just because we MAY use 4 colors does not mean we MUST use them. In fact, the map above can be colored with only 2 colors: color A and D red and color B and C blue. Now of course it's easy to see maps which require three colors, for example this one: +-------+ | A | +---+---+ | B | C | +---+---+ Since every pair of regions share a border, we MUST use a different color for each of the three regions. We could extend this idea arbitrarily far, except for one restriction: since the regions must be planar (i.e. they must be able to be drawn on a piece of paper), configurations requiring more than 4 colors are not possible. (This was the theorem that was proved a few years ago.) So what's an example of a map which requires 4 colors? Let's all take a minute and see if we can construct one (pause...) Ok, the simplest example I could come up with was this: +-------+ | A | | +---+ | +-+ B +-+ | +---+ | | C | D | +-------+ again, every pair of regions shares a border so we must have 4 different colors in order to color this map. You might try and spend some time trying to construct an example which takes 5 colors. The 4-color theorem says you won't be able to do it, however. But if you do find one, or if you find a nice clever way to show that it's not possible, you'd make the cover of the New York Times. Well, finding a 4-coloring of a given map is not really too bad. In fact, there is an algorithm which runs in polynomial-time which accomplishes this. So of course, HW4 will impose an added requirement to change this program from doable to intractable. We are given these four colors: red, white, blue, and gold (R, W, B, and G), and we must use the absolute minimum amount of gold. This problem has been shown to be very hard; in fact, no one knows any method of solving it in polynomial-time. An important note about HW4: your job is to color a map with the colors R, W, B, and G, and use the minimum number of G's. This means that if you output a solution with 5 G's and there was a way to do it with 4 G's, then your solution is wrong. In other words, there is no estimating going on here... your solution must find a coloring with the EXACT minimum number of G's. Note that there are potentially many correct solutions overall, of course, since R, W, and B are all essentially equivalent, and there may be several ways to color the non-Gold regions. The maps we're dealing with can be viewed as a graph. For example, we can draw the map above as a graph like this: A --- B | \ / | | X | | / \ | C --- D As you can see, we make a vertex for each region, and then add an edge between two regions if and only if they share a border. Any graph which represents a map will always be drawable in the plane (i.e. you can lay it out such that none of the edges cross). Let's try and draw the above graph without crossing lines. (pause...) Here's a simple way to draw it: A /|\ / | \ / B \ /_-- --_\ C---------D Now the problem is to assign colors to the vertices without ever having two adjacent vertices (i.e. two vertices which share an edge) share the same color. It's clear that this is equivalent to the original problem, yes? So in HW4 we have to color the United States (at least for the contest... there may be other maps provided as well). One good way to approach the problem is to print out the sample maps from the web page and take some colored pencils and try and color it in. This will undoubtledly lead to several insights which will help you solve your homework. An approach to combinatorial problem-solving mentioned in the HW4 spec is "backtracking", so we discuss that next. 2. Backtracking --------------- Backtracking is a general method of problem solving; the idea is kind of like trying to solve a maze: when presented with a choice for which you do not know the answer (e.g. the intersection point of a maze), you choose one and continue searching. If you ever hit a dead-end, you back up to the place where more unexplored choices still exist and try again from there. In general, this approach takes exponential time. In fact, we could have used a backtracking algorithm to solve the 3-CNF SAT problems; the advantage would have been that no random numbers would have been involved, and therefore the algorithm's upper bound would be finite (but huge). Remember that our WalkSAT algorithm could theoretically run forever. The general scheme for backtracking goes like this: { k = 0; do k++; select k-th candidate; if acceptable { record it; if (i < n) { recursively try(i+1); if (!successful) cancel recording; } } } while (!successful && k < total_candidates) } Today we're going to solve a different problem using backtracking; the problem is called "N queens." The problem is to place N queens on an N by N chessboard such that no two queens attack each other. C.F. Gauss first investigated this problem for N=8 in 1850 but wasn't able to completely solve it. But computers are patient and often can solve these problems better than people, even geniuses. Let's try N=4 with backtracking. +---------------+ | Q | | | | |---+---+---+---| | | | | | |---+---+---+---| | | Q | | | |---+---+---+---| | | | | | +---------------+ and here it's clear we can't place the 3rd queen in the 3rd column in a nonattacking position, so we give up and try moving the 2nd queen down one: +---------------+ | Q | | | | |---+---+---+---| | | | Q | | |---+---+---+---| | | | | | |---+---+---+---| | | Q | | | +---------------+ and again we see no solution, so we pick up the 3rd and 2nd queens and move the 1st queen down one: +---------------+ | | | Q | | |---+---+---+---| | Q | | | | |---+---+---+---| | | | | Q | |---+---+---+---| | | Q | | | +---------------+ and a solution is found!! So you see the essential idea here: we try each possible solution in sequence and as soon as we see we are doomed to failure, we give up and change some earlier decision we had made. Then we try again from there. Ok, let's write a C++ program to solve the n-queens problem for N=8: #include #include int x[8]; // x[i] is row of i-th queen int a[8]; // a[i] true if i-th row free int b[15]; // b[i] true if i-th down-left diag free int c[15]; // c[i] true if i-th down-right diag free void print(int *x) { for (int i=0; i < 8; i++) cout << setw(4) << x[i]; cout << endl; } void try(int i) { for (int j=0; j < 8; j++) if (a[j] && b[i+j] && c[i-j+7]) { x[i] = j; a[j] = b[i+j] = c[i-j+7] = 0; if (i < 7) try(i+1); else print(x); a[j] = b[i+j] = c[i-j+7] = 1; } } int main() { int i; for (i=0; i < 8; i++) a[i] = 1; for (i=0; i < 15; i++) b[i] = 1; for (i=0; i < 15; i++) c[i] = 1; try(0); }