Data Structures, Algorithms, & Applications in C++
Chapter 54, Exercise 4
To get the candidate heights, we first compute all
hsum(i,k) values. Then, these values are
sorted using the merge sort method. Following the sort, duplicate
values are eliminated by making a left to right sweep over the
sorted candidate heights. Next, we make a binary search for the minimum
height for which a folding into a rectangle of given width
is possible.
If no folding is possible for a trial candidate height tHeight,
then
candidate heights smaller than tHeight
are eliminated because no stack folding
for these smaller heights is possible either.
When a folding is possible for a trial candidate height tHeight,
then
candidate heights larger than tHeight
are eliminated because these
larger heights cannot result in the minimum height folding.
The code is given below.
// global variables
int n; // number of components;
int widthSum; // sum of widths of all components;
int *h; // component heights
int *w; // component widths
int *r; // space to be left at column ends
int **hsum; // hsum(i,k)
int *theW; // W_i for current height choice
int *kay; // kay values for current height choice;
int minimumHeightFolding(int theWidth, int bestW[], int bestKay[])
{// Fold components with heights h[1 .. n] and widths
// w[1 .. n] into a rectangle of width theWidth and
// minimum height.
// r is array of space to be left at column ends
// length of r must exceed that of h
// theW[i] is W_i
// hsum[i][k] is hsum(i,k)
// Values of bestW[1..n+1] and bestKay[1..n] are computed
// by this method.
// Return minimum folding height.
// Return 0 if folding into a theWidth rectangle is not possible.
theW = new int [n + 2];
theW[n + 1] = 0;
kay = new int [n + 1];
// determine sum of widths
widthSum = 0;
for (int i = 1; i <= n; i++)
widthSum += w[i];
// determine hsum(i,k)
hsum = new int [n + 1][n + 1];
for (int i = 1; i <= n; i++)
{
hsum[i][i] = h[i];
for (int k = i + 1; k <= n; k++)
hsum[i][k] = hsum[i][k - 1] + h[k];
}
r[0] = r[n + 1] = 0;
// collect possible rectangle height values into a 1D array
int *height = new int [n * n];
int k = 0; // cursor for height[]
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
height[k++] = hsum[i][j] + r[i] + r[j + 1];
// sort the possible heights
mergeSort(height, n * n);
// eliminate duplicates
k = 0;
for (int i = 1; i < n * n; i++)
if (height[k] < height[i])
height[++k] = height[i];
// do a binary search over the k + 1 distinct heights
int minHeight = 0;
int left = 0;
int right = k;
while (left <= right)
{
int middle = (left + right)/2;
variableWidthFolding(height[middle]);
if (theW[1] <= theWidth)
{// height[middle] is feasible
minHeight = height[middle];
// save theW and kay
for (int i = 1; i <= n; i++)
{
bestW[i] = theW[i];
bestKay[i] = kay[i];
}
right = middle - 1; // do not examine larger heights
}
else
// height[middle] is infeasible, do not examine smaller heights
left = middle + 1;
}
return minHeight;
}
void variableWidthFolding(int theHeight)
{// Fold components into a minimum width rectangle of height theHeight.
// Values of theW[1..n+1] and kay[1..n] are computed
// by this method.
for (int i = n; i > 0; i--)
{// compute theW[i] using Eq. 54.5
int wmax = 0, // wmax(i,k)
minW = widthSum + 1; // min value for W_i so far
for (int k = i; k <= n; k++)
{
if (hsum[i][k] > theHeight)
// infeasible
break;
if (w[k] > wmax)
wmax = w[k];
if (hsum[i][k] + r[i] + r[k + 1] <= theHeight &&
wmax + theW[k + 1] < minW)
{
minW = wmax + theW[k + 1];
kay[i] = k;
}
}
theW[i] = minW;
}
return;
}
void traceback(int kay[])
{// Output fold points.
if (kay[1] >= n)
cout << "There are no fold points" << endl;
else
{// there is at least one fold point
int i = 1;
cout << "The fold points are " << endl;
while (kay[i] < n)
{
i = kay[i] + 1;
cout << i + " ";
}
cout << endl;
}
}