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);
}