Data Structure Practice - For Collegiate Programming Contests and Education
Data Structure Practice - For Collegiate Programming Contests and Education
by Yonghui Wu
and Jiande Wang
CRC Press
Taylor & Francis Group
6000 Broken Sound Parkway NW, Suite 300
Boca Raton, FL 33487-2742
© 2019 by Taylor & Francis Group, LLC
CRC Press is an imprint of Taylor & Francis Group, an Informa business
No claim to original U.S. Government works
Printed on acid-free paper
International Standard Book Number-13: 978-1-4987-7663-9 (Hardback)
This book contains information obtained from authentic and highly regarded sources.
Reasonable efforts have been made to publish reliable data and information, but the author
and publisher cannot assume responsibility for the validity of all materials or the consequences
of their use. The authors and publishers have attempted to trace the copyright holders of all
material reproduced in this publication and apologize to copyright holders if permission
to publish in this form has not been obtained. If any copyright material has not been
acknowledged, please write and let us know so we may rectify in any future reprint.
Except as permitted under U.S. Copyright Law, no part of this book may be reprinted,
reproduced, transmitted, or utilized in any form by any electronic, mechanical, or other
means, now known or hereafter invented, including photocopying, microfilming, and
recording, or in any information storage or retrieval system, without written permission from
the publishers.
For permission to photocopy or use material electronically from this work, please access www.
copyright.com (http://www.copyright.com/) or contact the Copyright Clearance Center, Inc.
(CCC), 222 Rosewood Drive, Danvers, MA 01923, 978-750-8400. CCC is a not-for-profit
organization that provides licenses and registration for a variety of users. For organizations
that have been granted a photocopy license by the CCC, a separate system of payment has
been arranged.
Trademark Notice: Product or corporate names may be trademarks or registered trademarks,
and are used only for identification and explanation without intent to infringe.
Library of Congress Cataloging‑in‑Publication Data
A catalog record has been requested for this book
Visit the Taylor & Francis Web site at
http://www.taylorandfrancis.com
and the CRC Press Web site at
http://www.crcpress.com
Contents
Preface.............................................................................................................ix
Author Biographical Information................................................................ xiii
1 Practice for Ad Hoc Problems.................................................................1
1.1 Solving Problems by Mechanism Analysis..........................................1
1.1.1 Factstone Benchmark............................................................ 1
1.1.2 Bridge....................................................................................3
1.2 Solving Problems by Statistical Analysis.............................................6
1.2.1 Ants.......................................................................................6
1.2.2 Matches Game.......................................................................9
1.3 Problems...........................................................................................12
2 Practice for Simulation Problems..........................................................45
2.1 Simulation of Direct Statement........................................................45
2.1.1 The Hardest Problem Ever.................................................. 46
2.1.2 Rock-Paper-Scissors Tournament.........................................48
2.1.3 Robocode.............................................................................50
2.1.4 Eurodiffusion.......................................................................56
2.2 Simulation by Sieve Method.............................................................63
2.2.1 The Game........................................................................... 64
2.2.2 Game Schedule Required.....................................................68
2.3 Construction Simulation..................................................................72
2.3.1 Packets.................................................................................72
2.3.2 Paper Cutting......................................................................75
2.4 Problems...........................................................................................78
3 Practice for Number Theory..................................................................99
3.1 Practice for Prime Numbers.............................................................99
3.1.1 Calculating Prime Numbers by a Sieve................................99
3.1.2 Testing the Primality of Large Numbers............................109
3.2 Practice for Indeterminate Equations and Congruence...................113
3.2.1 Greatest Common Divisors and Indeterminate Equations.... 113
3.2.2 Congruences and Congruence Equations.......................... 117
v
vi ◾ Contents
8.4 Convex Hull and Finding the Farthest Pair of Points.................... 500
8.4.1 Convex Hull..................................................................... 500
8.4.2 Finding the Farthest Pair of Points.................................... 505
8.5 Problems......................................................................................... 511
9 Practice for State Space Search............................................................591
9.1 Constructing a State Space Tree.....................................................592
9.1.1 Robot.................................................................................594
9.1.2 The New Villa................................................................... 600
9.2 Optimizing State Space Search...................................................... 606
9.2.1 Be Wary of Rose................................................................607
9.2.2 Fill.....................................................................................612
9.2.3 Package Pricing.................................................................. 616
9.2.4 Eight..................................................................................624
9.2.5 Remmarguts’ Date.............................................................632
9.2.6 Jaguar King........................................................................637
9.3 A Game Tree Used to Solve a Game Problem................................ 642
9.3.1 Find the Winning Move................................................... 643
9.3.2 The Pawn Chess.................................................................650
9.4 Problems.........................................................................................654
Bibliography........................................................................................677
Index���������������������������������������������������������������������������������������������������679
Preface
ix
x ◾ Preface
Contest and Education. There are 9 chapters and 247 programming contest prob-
lems in this book.
Chapter 1, “Practice for Ad Hoc Problems”, focuses on solving problems that
there are no classical algorithms to solve. There are two methods to solve such
problems: the mechanism analysis method and the statistical analysis method. In
Chapter 2, “Practice for Simulation Problems”, experiments and practices for simu-
lation problems are shown. In problem descriptions, solution procedures or rules are
shown. Simulation problems are solved by implementing rules or simulating solu-
tion procedures. Chapter 3, “Practice for Number Theory”, Chapter 4, “Practice
for Combinatorics”, and Chapter 8, “Practice for Computational Geometry”, intro-
duce the mathematical background for number theory, combinatorics, and com-
putational geometry, respectively, and then show problems solved by mathematical
methods. Greedy algorithms and dynamic programming are used to solve opti-
mization problems. Chapter 5, “Practice for Greedy Algorithms”, and Chapter 6,
“Practice for Dynamic Programming”, introduce greedy algorithms and dynamic
programming respectively, and show problems solved by greedy algorithms and
dynamic programming. Chapter 7, “Practice for Advanced Data Structures”,
describes using suffix arrays, segment trees, and some graph algorithms to solve
problems. Search technologies are fundamental to computer science and technol-
ogy. Chapter 9, “Practice for State Space Search”, describes the implementation of
state space search through solving contest problems.
The features of the book are as follows:
The book can be used not only as an experiment book, but also for training for
systematic programming contests.
We appreciate Professors Steven Skiena and Rezaul Chowdhury, from Stony
Brook University; C. Jinshong Hwang, Ziliang Zong, and Hongchi Shi, from Texas
State University; Normaziah Abdul Aziz, from International Islamic University
Malaysia; Abul L. Haque, from North South University; Jiannong Cao, from
Preface ◾ xi
The Hong Kong Polytechnic University; and Rudolf Fleischer, from German
University of Technology in Oman. They provided us platforms in which English
is the native language that improved our manuscript. We also appreciate Miss Jiaqi
Chen, an undergraduate student from the Georgia Institute of Technology, who
reviewed and used several chapters in the manuscript, and pointed out some errors.
Online Judge systems for problems in this book are as follows:
Yonghui Wu, P h.D., Associate Professor, Fudan University. He acted as the coach
of Fudan University Programming Contest teams from 2001 to 2011. Under his
guidance, Fudan University qualified for ACM-ICPC World Finals every year and
won three medals (bronze medal in 2002, silver medal in 2005, and bronze medal
in 2010) in ACM-ICPC World Finals. Since 2012, he has published a series of books
for programming contest and education in simplified and traditional Chinese and
English. Since 2013, he has given lectures in Oman, Taiwan, HongKong, Macau,
Malaysia, Bangladesh, Mainland China, and the United States for program-
ming contest training. He is the chair of ACM-ICPC Asia Programming Contest
Training Committee now.
Jiande Wang, High School Senior Teacher. He is a famous coach for Olympiad in
Informatics in China. He has published 24 books for programming contests since
1990s. Under his guidance, his students won seven gold medals, three silver med-
als, and two bronze medals in International Olympiad in Informatics for China.
xiii
Chapter 1
Practice for Ad
Hoc Problems
Ad hoc means “for the special purpose or end presently under consideration.” There
are no classical algorithms that can solve these ad hoc problems. Programmers need to
design specific algorithms to solve ad hoc problems. There are two strategies to design
algorithms for solving ad hoc problems: mechanism analysis and statistical analysis.
To solve an ad hoc problem, we need to see past its appearance and understand
its essence.
In this chapter, two kinds of analyses solving ad hoc problems are shown:
◾◾ Mechanism Analysis;
◾◾ Statistical Analysis.
1
2 ◾ Algorithm Design Practice for Collegiate Programming
a 16-bit computer in 1980, an 8-bit computer in 1970, and a 4-bit computer, its first,
in 1960.)
Amtel will use a new benchmark—the Factstone—to advertise the vastly
improved capacity of its new chips. The Factstone rating is defined to be the largest
integer n such that n! can be represented as an unsigned integer in a computer word.
Given a year 1960≤y≤2160, what will be the Factstone rating of Amtel’s most
recently released chip?
Input
There are several test cases. For each test case, there is one line of input containing y.
A line containing 0 follows the last test case.
Output
For each test case, output a line giving the Factstone rating.
1960 3
1981 8
0
Source: Waterloo local 2005.09.24
IDs for Online Judges: POJ 2661, UVA 10916
Analysis
For a given year, first the number of bits for the computer in this year is calculated,
and then the largest integer n (the Factstone rating) that n! can be represented as an
unsigned integer in a computer word is calculated.
The computer was a 4-bit computer in 1960. Amtel doubles the word size every
Y −1960
2+
ten years. That is, the number of bits for the computer in year Y is K = 2 10 .
The largest unsigned integer for K-bit is 2K−1. If n! is the largest unsigned integer
not greater than 2K−1, then n is the Factstone rating in year Y. There are two cal-
culation methods.
Method 1: Calculate n! directly. This method is slow and easily leads to overflow.
Method 2: Logarithms are used to calculate n!. Based on the following formula:
n can be calculated. Initially i is 1, repeat i++, and log2i is accumulated until the
sum is larger than K. Then i−1 is the Factstone rating.
Program
#include <stdio.h>
#include <math.h>
int y,Y,i,j,m; // Year y
double f,w; // f: the sum of accumulation for log2 i
main(){
while (1 == scanf("%d",&y) && y){ //Input test cases
w = log(4);
for (Y=1960; Y<=y; Y+=10){
w *= 2;
}
i = 1; //accumulation log2 i until larger than w
f = 0;
while (f < w) {
f += log((double)++i);
}
printf("%d\n",i-1); //Output the Factstone rating
}
if (y) printf("fishy ending %d\n",y);
}
1.1.2 Bridge
Consider that n people wish to cross a bridge at night. A group of at most two
people may cross at any time, and each group must have a flashlight. Only one
flashlight is available among the n people, so some sort of shuttle arrangement
must be arranged in order to return the flashlight so that more people may
cross.
Each person has a different crossing speed; the speed of a group is determined
by the speed of the slower member. Your job is to determine a strategy that gets all
n people across the bridge in the minimum time.
Input
The first line of input contains n, followed by n lines giving the crossing times for
each of the people. There are not more than 1000 people, and nobody takes more
than 100 seconds to cross the bridge.
4 ◾ Algorithm Design Practice for Collegiate Programming
Output
The first line of output must contain the total number of seconds required for all
n people to cross the bridge. The following lines give a strategy for achieving
this time. Each line contains either one or two integers, indicating which person or
people form the next group to cross. (Each person is indicated by the crossing time
specified in the input. Although many people may have the same crossing time, the
ambiguity is of no consequence.) Note that the crossings alternate directions, as it is
necessary to return the flashlight so that more may cross. If more than one strategy
yields the minimal time, any one will do.
4 17
1 1 2
2 1
5 5 10
10 2
1 2
Source: POJ 2573, ZOJ 1877, UVA 10037
IDs for Online Judge: Waterloo local 2000.09.30
Analysis
The strategy that gets all n people across the bridge in the minimum time is: fast
people should return the flashlight to help slow people.
Because a group of at most two people may cross the bridge each time, we solve the
problem by analyzing members of groups. First, n people’s crossing times are sorted in
descending order. Suppose that in the current sequence, A is the current fastest person’s
crossing time, B is the current second fastest person’s crossing time, a is the current
slowest person’s crossing time, and b is the current second slowest person’s crossing time.
There are two methods for making the current slowest person and the current
second slowest person to cross the bridge:
Method 1: The fastest person helps the slowest person and the second slowest
person to cross the bridge. The steps are as follows:
Step 1: The fastest person and the slowest person cross the bridge;
Step 2: The fastest person is back;
Step 3: The fastest person and the second slowest person cross the bridge;
Step 4: The fastest person is back.
It takes time 2×A+a+b.
Practice for Ad Hoc Problems ◾ 5
Method 2: The fastest person and the second fastest person help the current
slowest person and the current second slowest person to cross the bridge.
Step 1: The fastest person and the second fastest person cross the bridge;
Step 2: The fastest person is back and returns the flashlight to the slowest
person and the second slowest person;
Step 3: The slowest person and the second slowest person cross the bridge and
give the flashlight to the second fastest person;
Step 4: The second fastest person is back.
It takes time 2×B+A+a.
Case 1: If there are only two persons who need to cross the bridge, then the two
persons cross the bridge. It takes time B.
Case 2: There are three persons who need to cross the bridge. First, the fastest
person and the slowest person cross the bridge. Then, the fastest person is
back. Finally, the last two persons cross the bridge. It takes time a+A+b.
Program
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<string>
using namespace std;
int n,i,j,k,a[111111]; //n: the number of persons, a[ ]: n
people’s crossing times
int ans=0; // ans: the total number of seconds for all n
people to cross the bridge
int main () {
scanf("%d",&n); //Input
for(i=1;i<=n;i++)scanf("%d",a+i);
if(n==1){ //only 1 person
printf("%d\n%d\n",a[1],a[1]);return 0;
}
6 ◾ Algorithm Design Practice for Collegiate Programming
int nn=n;
sort(a+1,a+n+1); //n people’s crossing times are sorted
in descending order
while(n>3){ //calculate the total number of seconds for
all n people to cross the bridge
if(a[1]+a[n-1]<2*a[2]){ //Method 1
ans+=a[n]+a[1]*2+a[n-1];
}else{ //Method 2
ans+=a[2]+a[1]+a[2]+a[n];
}
n-=2; //the two slowest persons cross the bridge
}
if(n==2)ans+=a[2]; //only two persons need to cross the
bridge
else ans+=a[1]+a[2]+a[3]; //three persons need to
cross the bridge
printf("%d\n",ans); //the total number of seconds for
all n people to cross the bridge
n=nn;
while(n>3){ //output the strategy for achieving this
time
if(a[1]+a[n-1]<2*a[2]) //Method 1
printf("%d%d\n%d\n%d%d\n%d\n",a[1],a[n],a[1],
a[1],a[n-1],a[1]);
else //Method 2
printf("%d%d\n%d\n%d%d\n%d\n",a[1],a[2],a[1],
a[n-1],a[n],a[2]);
n-=2; //the two slowest persons cross the bridge
}
if(n==2)printf("%d %d\n",a[1],a[2]); //only two persons
need to cross the bridge
else //three persons need to cross the bridge
printf("%d %d\n%d\n%d %d\n",a[1],a[3],a[1],a[1],a[2]);
return 0;
}
1.2.1 Ants
An army of ants walk on a horizontal pole of length l cm, each with a constant
speed of 1 cm/s. When a walking ant reaches an end of the pole, it immediately falls
off it. When two ants meet, they turn back and start walking in opposite directions.
Practice for Ad Hoc Problems ◾ 7
We know the original positions of ants on the pole; unfortunately, we do not know
the directions in which the ants are walking. Your task is to compute the earliest
and the latest possible times needed for all ants to fall off the pole.
Input
The first line of input contains one integer giving the number of cases that follow.
The data for each case start with two integer numbers: the length of the pole (in cm)
and n, the number of ants residing on the pole. These two numbers are followed by
n integers giving the position of each ant on the pole as the distance measured from
the left end of the pole, in no particular order. All input integers are not bigger than
1000000, and they are separated by whitespace.
Output
For each case of input, output two numbers separated by a single space. The first num-
ber is the earliest possible time when all ants fall off the pole (if the directions of their
walks are chosen appropriately), and the second number is the latest possible such time.
2 4 8
10 3 38 207
2 6 7
214 7
11 12 7 13 176 23 191
Source: Waterloo local 2004.09.19
IDs for Online judges: POJ 1852, ZOJ 2376, UVA 10714
Analysis
The upper limit of the number of ants is 1000000. The upper limit of the number
of combinations for ants’ walking is 21000000. Therefore, the problem can’t be solved
by enumerating ants walking.
First, we analyze the case that a few ants walk on a horizontal pole (Figure 1.1).
In Figure 1.1, when two ants meet, that is, “ ”, they’ll turn back
and start walking in opposite directions, that is, “ ”. All ants are the
same. Therefore, all ants walk in their original directions no matter whether they
meet or not. There are two values for the time that an ant falls off the pole: the ant
walks to the left, or the ant walks to the right.
8 ◾ Algorithm Design Practice for Collegiate Programming
Figure 1.1
Suppose li is the position of ant i on the pole, that is, the distance measured
from the left end of the pole, 1≤i≤n; little is the earliest possible time when all ants
fall off the pole; and big is the latest possible time when all ants fall off the pole.
Based on these facts, the algorithm is as follows:
Program
#include <stdio.h>
int c,big,little,L,i,j,k,n; //c: number of test cases; L:
the length of the pole; n: number of ants on the pole
main(){
scanf("%d",&c); // input the number of test cases
while (c-- && (2 == scanf("%d%d",&L,&n))) { //Input the
length of the pole and the number of ants on the pole
Practice for Ad Hoc Problems ◾ 9
Input
The input consists of several lines, and in each line there is a test case. At the begin-
ning of a line, there is an integer M (1≤M≤20), which is the number of piles. Then
come M positive integers, which are not larger than 10000000. These M integers
represent the number of matches in each pile.
Output
For each test case, output “Yes” in a single line, if the player who play first will win;
otherwise output “No.”
2 45 45 No
3 3 6 9 Yes
Source: POJ Monthly, readchild
ID for Online Judge: POJ 2234
10 ◾ Algorithm Design Practice for Collegiate Programming
Analysis
The problem is a Nimm’s Game problem. Cases for the game are analyzed as
follows:
Case 1: There is only one pile of matches. The player who plays first will take
away all matches from the pile and win the game.
Case 2: There are two piles of matches. Numbers of matches in the two piles are
N1 and N2 respectively.
If N1≠N2, the player who plays first will take away some matches from the
larger pile to make the two piles have the same number of matches. Then,
by mimicking the player who plays second and taking the same number
of matches that he takes, just from the opposite pile, the player who plays
first will win the game.
If N1=N2, the player who plays second will take the same number of matches
as the player who plays first takes, just from the opposite pile, and then
the player who plays second will win the game.
Case 3: There are more than two piles of matches.
The player who plays first will win the game if the initial state is unbalanced.
And the player who plays second will win the game if the initial state is
balanced.
Practice for Ad Hoc Problems ◾ 11
For example, there are four piles of matches. There are 7, 9, 12, and 15 matches
in the four piles respectively. 7, 9, 12, and 15 can be represented as binary numbers
0111, 1001, 1100, and 1111. This is shown in the following list.
Size of a Pile 23 = 8 22 = 4 21 = 2 20 = 1
7 0 1 1 1
9 1 0 0 1
12 1 1 0 0
15 1 1 1 1
The initial state for the game is unbalanced. The player who plays first takes
away some matches from a pile to make the state become a balanced state. There are
many choices. For example, the player who plays first takes away 11 matches from
a pile with 12 matches to make the state become a balanced state. This is shown in
the following list.
Size of a Pile 23 = 8 22 = 4 21 = 2 20 = 1
7 0 1 1 1
9 1 0 0 1
12⇒1 0 0 0 1
15 1 1 1 1
The method that the player who plays first takes away some matches from a pile
to make the state become a balanced state is to select a row (a pile), and to flip val-
ues of bits in odd columns in the row. After flipping values of bits in odd columns,
the number of matches is less than the original number of matches in the row. The
number of matches that the player who plays first takes away from the correspond-
ing pile is the difference between the original number of matches and the new
number of matches. Then, the player who plays second takes away matches under
a balanced state. The state will become an unbalanced state. And the player who
plays first can make the state balance no matter how the player who plays second
takes away matches. The process is repeated until the player who plays second takes
away some matches under a balanced state last time, and then the player who plays
first can take away all remainder matches.
For the same reason, the player who plays second will win the game when the
initial state is a balanced game.
12 ◾ Algorithm Design Practice for Collegiate Programming
Program
# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <string>
# include <cmath>
# include <algorithm>
using namespace std;
int main(){
int n;
while(~scanf("%d",&n)){ //number of piles
int a=0,b; //a: result, b: number of matches in the
current pile
for(int i=0;i<n;i++){ //input numbers of matches in
all piles
scanf("%d",&b);
a^=b; //XOR operations
}
printf("%s\n",a?"Yes":"No"); //if a isn’t balanced,
output “Yes”, else output “No”
}
return 0;
}
1.3 Problems
1.3.1 Perfection
From the article Number Theory in the 1994 Microsoft Encarta: “If a, b, c are inte-
gers such that a = bc, a is called a multiple of b or of c, and b or c is called a divisor
or factor of a. If c is not ±1, b is called a proper divisor of a. Even integers, which
include 0, are multiples of 2, for example, −4, 0, 2, 10; an odd integer is an integer
that is not even, for example, −5, 1, 3, 9. A perfect number is a positive integer that
is equal to the sum of all its positive, proper divisors; for example, 6, which equals
1 + 2 + 3, and 28, which equals 1 + 2 + 4 + 7 + 14, are perfect numbers. A positive
Practice for Ad Hoc Problems ◾ 13
Input
A list of N positive integers (none greater than 60,000), with 1<N<100. A 0 will
mark the end of the list.
Output
The first line of output should read PERFECTION OUTPUT. The next N lines of
output should list for each input integer whether it is perfect, deficient, or abundant,
as shown in the following example. Format counts: the echoed integers should be
right-justified within the first five spaces of the output line, followed by two blank
spaces, followed by the description of the integer. The final line of output should
read END OF OUTPUT.
Hint
First, all proper divisors of the current integer are calculated. Then the sum of all
proper divisors is calculated.
If the current integer > the sum of all proper divisors, then output “DEFICIENT”;
If the current integer < the sum of all proper divisors, then output “ABUNDANT”;
If the current integer = the sum of all proper divisors, then output “PERFECT”.
14 ◾ Algorithm Design Practice for Collegiate Programming
seed ( x +1) = seed ( x )+ STEP % MOD where “%” is the modulus operator.
Input
Each line of input will contain a pair of integers for STEP and MOD in that order
(1≤STEP,MOD≤100000).
Output
For each line of input, your program should print the STEP value right-justified in
columns 1 through 10, the MOD value right-justified in columns 11 through 20,
and either “Good Choice” or “Bad Choice” left-justified starting in column 25.
The “Good Choice” message should be printed when the selection of STEP and
MOD will generate all the numbers between and including 0 and MOD-1 when
MOD numbers are generated. Otherwise, your program should print the mes-
sage “Bad Choice.” After each output test set, your program should print exactly
one blank line.
Practice for Ad Hoc Problems ◾ 15
3 5 3 5 Good Choice
15 20 15 20 Bad Choice
Hint
Suppose seedi is the i-th pseudo-random number. Based on the problem descrip-
tion, the next pseudo-random number (the (i+1)-th pseudo-random number) is
seedi+1=(seedi+step)%MOD.
From seed0, the function is iterated MOD-1 times. If produced MOD-1 pseudo-
random numbers are all the numbers between 1 and MOD-1, it generates a uni-
form distribution of pseudo-random numbers; else it doesn’t generate a uniform
distribution of pseudo-random numbers.
1.3.3 WERTYU
A common typing error is to place the hands on the keyboard one row to the right
of the correct position (see Figure 1.2). So “Q” is typed as “W” and “J” is typed as
“K” and so on. You are to decode a message typed in this manner.
Input
Input consists of several lines of text. Each line may contain digits, spaces, uppercase
letters (except Q, A, Z), or punctuation shown above (except back-quote [`]). Keys
labelled with words (Tab, BackSp, Control, etc.) are not represented in the input.
` 1 2 3 4 5 6 7 8 9 0 - = BackSp
Tab Q W E R T Y U I O P [ ] \
A S D F G H J K L ; ‘ Enter
Z X C V B N M , . /
Control Alt Alt Control
Figure 1.2
16 ◾ Algorithm Design Practice for Collegiate Programming
Output
You are to replace each letter or punctuation symbol by the one immediately to its
left on the QWERTY keyboard shown above. Spaces in the input should be echoed
in the output.
Hint
First, the offline method is used to calculate the conversion table based on the key-
board figure. Then, for each letter, the corresponding letter in the conversion table
is output.
1.3.4 Soundex
Soundex coding groups together words that appear to sound alike based on their
spelling. For example, “can” and “khawn”, “con” and “gone” would be equivalent
under Soundex coding.
Soundex coding involves translating each word into a series of digits in which
each digit represents a letter:
1 represents B, F, P, or V
2 represents C, G, J, K, Q, S, X, or Z
3 represents D or T
4 represents L
5 represents M or N
6 represents R
Input
Each line of input contains a single word, all uppercase, less than 20 letters long.
Practice for Ad Hoc Problems ◾ 17
Output
For each line of input, produce a line of output giving the Soundex code.
KHAWN 25
PFISTER 1236
BOBBY 11
Source: Waterloo local 1999.09.25
IDs for Online Judges: POJ 2608, ZOJ 1858, UVA 10260
Hint
For each word, letters are transferred into corresponding digits from left to right.
And based on the problem description, letters A, E, I, O, U, H, W, and Y are not
represented in Soundex coding, and repeated letters with the same code digit are
represented by a single instance of that digit.
1.3.5 Minesweeper
The game Minesweeper is played on an n by n grid. In this grid are hidden m mines,
each at a distinct grid location. The player repeatedly touches grid positions. If a
position with a mine is touched, the mine explodes and the player loses. If a position
not containing a mine is touched, an integer between 0 and 8 appears, denoting
the number of adjacent or diagonally adjacent grid positions that contain a mine.
A sequence of moves in a partially played game is illustrated below in Figure 1.3.
Here, n is 8, m is 10, blank squares represent the integer 0, raised squares represent
unplayed positions, and the figures resembling asterisks represent mines. The left-
most image represents the partially played game. From the first image to the second,
Figure 1.3
18 ◾ Algorithm Design Practice for Collegiate Programming
the player has played two moves, each time choosing a safe grid position. From the
second image to the third, the player is not so lucky; he chooses a position with a
mine and therefore loses. The player wins if he continues to make safe moves until
only m unplayed positions remain; these must necessarily contain the mines.
Your job is to read the information for a partially played game and to print the
corresponding board.
Input
The first line of input contains a single positive integer n≤10. The next n lines rep-
resent the positions of the mines. Each line represents the contents of a row using
n characters: a period indicates an unmined positon, while an asterisk indicates a
mined position. The next n lines are each n characters long: touched positions are
denoted by an x, and untouched positions by a period. The sample input corre-
sponds to the middle section of Figure 1.3.
Output
Your output should represent the board, with each position filled in appropriately.
Positions that have been touched and do not contain a mine should contain an inte-
ger between 0 and 8. If a mine has been touched, all positions with a mine should
contain an asterisk. All other positions should contain a period.
8 001.....
...**..* 0013....
......*. 0001....
....*... 00011...
........ 00001...
........ 00123...
.....*.. 001.....
...**.*. 00123...
.....*..
xxx.....
xxxx....
xxxx....
xxxxx...
xxxxx...
xxxxx...
xxx.....
xxxxx...
Source: Waterloo local 1999.10.02
IDs for Online Judges: POJ 2612, ZOJ 1862, UVA 10279
Practice for Ad Hoc Problems ◾ 19
Hint
Suppose g[i][j] is the matrix for mines, and try[i][j] is the touch matrix, 1≤i, j≤n.
First we need to determine whether a mine is touched or not, that is, whether
there exists such a grid that (try[i][j]=='x'&&g[i][j]=='*'). The mark mc=
' *' There exists a touched mine.
shows whether there is a touched mine or not.
'.' There is no touched mine.
Then calculate and output the state for every grid (i,j) from left to right, and
from top to bottom, 1≤i, j≤n.
If grid (i,j) is touched and doesn’t contain a mine (try[i][j]== 'x'&&g[i][j]== '.'),
then the number of adjacent or diagonally adjacent grid positions that contain a
mine x is calculated and is filled into (i,j); else (i.e., try[i][j]== '.'||g[i][j]== '*'), if grid
(i,j) contains a mine, mc is filled into (i,j); else ‘.’ is filled into (i,j).
Input
The first line of input contains N, the number of test cases. 4N−1 lines follow,
specifying N grid configurations separated by empty lines.
... X .. X .O X .O X .O X .O X .O X .O
... ... ... ... .O . .O . OO . OO .
... ... ... .. X .. X X .X X .X XXX
Figure 1.4
20 ◾ Algorithm Design Practice for Collegiate Programming
Output
For each case, print “yes” or “no” on a line by itself, indicating whether or not the
configuration could be part of a Tic Tac Toe game.
2 yes
X.O no
OO.
XXX
O.X
XX.
OOO
Source: POJ 2361, ZOJ 1908, UVA 10363
IDs for Online Judges: Waterloo local 2002.09.21
Hint
Based on the problem description, a configuration for part of a valid Tic Tac Toe
game must satisfy the following properties:
1. The number of Os must be one less than or equal to the number of Xs;
2. If the number of Os is one less than the number of Xs, O doesn’t win the
game;
3. If the number of Os is equal to the number of Xs, X doesn’t win the game.
That is to say, if a configuration isn’t part of a valid Tic Tac Toe game, it must
satisfy the following properties:
or Papers. Each day, differing life forms occupying horizontally or vertically adja-
cent grid locations wage war. In each war, Rocks always defeat Scissors, Scissors
always defeat Papers, and Papers always defeat Rocks. At the end of the day, the
victor expands its territory to include the loser’s grid position. The loser vacates
the position.
Your job is to determine the territory occupied by each life form after n days.
Input
The first line of input contains t, the number of test cases. Each test case begins
with three integers not greater than 100: r and c, the number of rows and columns
in the grid, and n. The grid is represented by the r lines that follow, each with c
characters. Each character in the grid is R, S, or P, indicating that it is occupied by
Rocks, Scissors, or Papers respectively.
Output
For each test case, print the grid as it appears at the end of the nth day. Leave an
empty line between the output for successive test cases.
2 RRR
3 3 1 RRR
RRR RRR
RSR
RRR RRRS
3 4 2 RRSP
RSPR RSPR
SPRS
PRSP
Source: POJ 2339, ZOJ 1921, UVA 10443
IDs for Online Judges: Waterloo local 2003.01.25
Hint
Because the two-dimensional grid is changed at the end of the day, two matrices
are used to represent yesterday’s two-dimensional grid and today’s two-dimensional
22 ◾ Algorithm Design Practice for Collegiate Programming
◾◾ An ‘R’ will be changed into a ‘P’ if and only if the ‘R’ is adjacent to a ‘P’
in yesterday’s two-dimensional grid. That is, if an ‘R’ is adjacent to a ‘P’ in
yesterday’s two-dimensional grid, then the ‘R’ is changed into ‘P’ in today’s
two-dimensional grid.
◾◾ An ‘S’ will be changed into an ‘R’ if and only if the ‘S’ is adjacent to an ‘R’
in yesterday’s two-dimensional grid. That is, if an ‘S’ is adjacent to an ‘R’ in
yesterday’s two-dimensional grid, then the ‘S’ is changed into ‘R’ in today’s
two-dimensional grid.
◾◾ A ‘P’ will be changed into an ‘S’ if and only if the ‘P’ is adjacent to an ‘S’
in yesterday’s two-dimensional grid. That is, if a ‘P’ is adjacent to an ‘S’ in
yesterday’s two-dimensional grid, then the ‘P’ is changed into ‘S’ in today’s
two-dimensional grid.
For example,
R S P R R R S P R R R S
S P R S ⇒ R S P R ⇒ R R S P ⇒
P R S P S P R S R S P R
R R R R
R R R S
R R S P
The grid as it appears at the end of the nth day is calculated based on the above rules.
1.3.8 Prerequisites?
Freddie the freshman has chosen to take k courses. To meet the degree require-
ments, he must take courses from each of several categories. Can you assure Freddie
that he will graduate, based on his course selection?
Input
Input consists of several test cases. For each case, the first line of input contains
1≤k≤100, the number of courses Freddie has chosen, and 0≤m≤100, the number
of categories. One or more lines containing k four-digit integers follow; each is
the number of a course selected by Freddie. Each category is represented by a line
containing 1≤c≤100, the number of courses in the category; 0≤r≤c, the minimum
number of courses from the category that must be taken; and the c course numbers
Practice for Ad Hoc Problems ◾ 23
in the category. Each course number is a four-digit integer. The same course may
fulfil several category requirements. Freddie’s selections, and the course numbers in
any particular category, are distinct. A line containing 0 follows the last test case.
Output
For each test case, output a line containing “yes” if Freddie's course selection meets
the degree requirements; otherwise output “no.”
3 2 yes
0123 9876 2222 no
2 1 8888 2222
3 2 9876 2222 7654
3 2
0123 9876 2222
2 2 8888 2222
3 2 7654 9876 2222
0
Source: Waterloo local 2005.09.24
IDs for Online Judges: POJ 2664, UVA 10919
Hint
Suppose ci is the number of courses in the i-th category, donei is the set of courses in
the i-th category, and ri is the minimum number of courses from the i-th category
that must be taken, 1≤i≤m.
First, k courses that Freddie has chosen to take are put into a set take[ ].
Then courses that Freddie has chosen to take are analyzed. For courses in the
i-th category, if ri ≤|take[ ]∩ donei|, the number of courses in the i-th category that
Freddie has chosen to take is larger than or equal to the minimum number of
courses from the i-th category that must be taken, and set the mark yesi=true.
Finally, if ∩ { yesi } ==true, then Freddie’s course selection meets the degree
1≤i ≤ m
requirements, else Freddie’s course selection doesn’t meet the degree requirements.
In this problem, the program-generated banners will contain the text “SAVE
HRIDOY”. We will make this banner with different text sizes and two possible
types of orientations: horizontal and vertical (see Figure 1.5). As we will make ban-
ners of different size in plain monochrome text, we will use two different ASCII
characters to denote black-and-white pixels. In this process, the smallest possible
banner (font size 1) for us in horizontal orientation is:
Figure 1.5
You can see that here black pixels are formed with the “*” character and white
pixels are marked with the “.” character. In this banner, each character is repre-
sented in a (5 × 5) grid, two consecutive characters in a single word are separated
by a single vertical dotted line, and the two words are separated by three vertical
dotted lines. In the case of vertical banners (of font size 1), two consecutive letters in
a single word are separated by a horizontal dotted line, and two words are separated
by three horizontal dotted lines. Look at the second output for sample input to
know how vertical banners are formed. In the case of a banner of font size 2, each
pixel is represented by a (2 × 2) grid of pixels. So actually a banner of font size two
has double the width and double the height of a banner of font size 1.
Input
The input file contains at most 30 lines of inputs. Each line contains an integer
N (0<N<51). This value of N denotes the font size and orientation of a banner. Input
is terminated by a line containing a single zero. This line should not be processed.
Output
If N is positive, then you have to draw a banner of horizontal orientation, and if
N is negative, then you have to draw a banner of vertical orientation. The detailed
description of output for these two types of cases is given below:
After the output of each test case, print two blank lines.
- *****
1 *....
2 *****
0 ....*
*****
.....
.***.
*...*
*****
*...*
*...*
.....
*...*
*...*
*...*
.*.*.
..*..
.....
*****
*....
***..
*....
*****
.....
.....
.....
*...*
*...*
*****
*...*
*...*
.....
*****
*...*
*****
*.*..
*..**
.....
*****
..*..
..*..
(continued)
26 ◾ Algorithm Design Practice for Collegiate Programming
..*..
*****
.....
***..
*..*.
*...*
*..*.
***..
.....
*****
*...*
*...*
*...*
*****
.....
*...*
.*.*.
..*..
..*..
..*..
**********....******....**......**..**********......**......**..**********..
**********..******......**********..**......**
**********....******....**......**..**********......**......**..**********..
**********..******......**********..**......**
**..........**......**..**......**..**..............**......**..**......**......**......
**....**....**......**....**..**..
**..........**......**..**......**..**..............**......**..**......**......**......
**....**....**......**....**..**..
**********..**********..**......**..******..........**********..********
**......**......**......**..**......**......**....
**********..**********..**......**..******..........**********..********
**......**......**......**..**......**......**....
........**..**......**....**..**....**..............**......**..**..**..........**......
**....**....**......**......**....
........**..**......**....**..**....**..............**......**..**..**..........**......
**....**....**......**......**....
**********..**......**......**......**********......**......**..**....****..**
********..******......**********......**....
**********..**......**......**......**********......**......**..**....****..**
********..******......**********......**....
Hint
First, the offline method is used to construct a matrix F[][], representing a ban-
ner of horizontal orientation, and a matrix G[][], representing a banner of vertical
orientation (font size 1).
Then, for each test case N, F[][], or G[][] is magnified. If N is positive, then
F[][] is magnified N times. That is, a horizontal banner with 5N×61N is produced,
i − 1 j − 1
where (i,j) is F + 1 + 1 . If N is negative, then G[][] is magni-
N N
fied |N| times. That is, a horizontal banner with 61N×5N is produced, where (i,j) is
i − 1 j − 1
G + 1 + 1 .
− N − N
Letters Number
ABC 2
DEF 3
GHI 4
JKL 5
MNO 6
PQRS 7
TUV 8
WXYZ 9
Input
The input consists of a set of expressions. Each expression is in a line by itself and
has C characters, where 1≤C≤30. The input is terminated by end of file (EOF).
28 ◾ Algorithm Design Practice for Collegiate Programming
Output
For each expression, you should print the corresponding phone number.
1-HOME-SWEET-HOME 1-4663-79338-4663
MY-MISERABLE-JOB 69-647372253-562
Source: UFRN-2005 Contest 1
ID for Online Judge: UVA 10921
Hint
In an expression, characters are analyzed from left to right. If a character is a
hyphen, ‘1’, or ‘0’, the character is output directly; else the number that the charac-
ter corresponds to is output.
1.3.11 2 the 9s
A well-known trick to know if an integer N is a multiple of nine is to compute the sum
S of its digits. If S is a multiple of nine, then so is N. This is a recursive test, and the
depth of the recursion needed to obtain the answer on N is called the 9-degree of N.
Your job is, given a positive number N, to determine if it is a multiple of nine
and, if it is, its 9-degree.
Input
The input is a file such that each line contains a positive number. A line containing the
number 0 is the end of the input. The given numbers can contain up to 1000 digits.
Output
The output of the program shall indicate, for each input number, if it is a multiple
of nine, and in case it is, the value of its 9-degree. See the sample output for an
example of the expected formatting of the output.
Sample Input Sample Output
Hint
For this problem, the statistical analysis method is used. First, two sample test cases
are analyzed.
1. N = 999999999999999999999
a. The first level for the recursion: There are 21 digits for
999999999999999999999.
The sum of 21 digits is 9×21=189;
The second level for the recursion: The sum of three digits for 189 is
1+8+9=18;
The third level for the recursion: The sum of two digits for 18 is 9. The
recursion ends.
Therefore, 999999999999999999999 is a multiple of nine and has
9-degree 3.
2. N = 9999999999999999999999999999998
b. The first level for the recursion: There are 31 digits for 99999999999999
99999999999999998. The sum of 31 digits is 30×9+8=278;
The second level for the recursion: The sum of three digits for 278 is
2+7+8=17;
The third level for the recursion: The sum of two digits for 17 is 8. 8 isn’t
a multiple of 9. The recursion ends.
Input
The input is a file such that each line contains a positive number. A line contain-
ing the number 0 is the end of the input. The given numbers can contain up to
1000 digits.
30 ◾ Algorithm Design Practice for Collegiate Programming
Output
The output of the program shall indicate, for each input number, if it is a multiple
of eleven or not.
Hint
Suppose the given large positive number can be represented as a high precision
number A=a0…al -1. From right to left, sums of odd positions and even posi-
tions for the number are calculated respectively. Then the difference for the two
sums is calculated. If the difference is a multiple of 11 (including 0), that is,
l l
2 2
∑ a −∑ a
i =0
2*i
i =1
2*i −1 =11*k , then A is a multiple of 11. Otherwise, A is not a multiple
of 11.
Another method is to simply shift and mod. A number A is divisible by 11 if A
mod 11 is 0. We can shift and mod with primitive types.
1.3.13 Parity
We define the parity of an integer n as the sum of the bits in binary representation
computed in modulo two. As an example, the number 21=101012 has three 1s in its
binary representation, so it has parity 3 (mod 2), or 1.
In this problem, you have to calculate the parity of an integer 1≤I≤2147483647.
Input
Each line of the input has an integer I and the end of the input is indicated by a line
where I=0 that should not be processed.
Practice for Ad Hoc Problems ◾ 31
Output
For each integer I in the input, you should print a line “The parity of B is P (mod 2).”,
where B is the binary representation of I.
Hint
The problem requires you to figure out how many 1’s are in a binary number for the
decimal number they give you. This is most easily done by keeping track of the 1’s
and continuously bitshifting until the number is 0. The constraints are 31 bits of all
1’s 2^31−1, so just an integer will suffice.
Input
The first line of input gives the number of cases, N. N test cases follow. Each one
contains a string of at least 1 and at most 50 uppercase characters (R, F, or C).
Output
For each test case, output the line “Case #x:”, where x is the number of the test
case. Then print the graph, as shown in the sample output, including the x- and
y-axes. The x-axis should be one character longer than the graph, and there should
be one space between the y-axis and the start of the graph. There should be no
32 ◾ Algorithm Design Practice for Collegiate Programming
trailing spaces on any line. Do not print unnecessary lines. The x-axis should
always appear directly below the graph. Finally, print an empty line after each
test case.
Hint
The problem explanation covers the problem with enough detail to solve it without
really needing much insight. We are given a string of characters, each of which
is R (rise), C (constant), or F (fall), and we have to draw the corresponding line.
Just make a 2D matrix of characters and draw to the matrix, and then output
the matrix.
For the problem, the two points should be noted. The stock price does not nec-
essarily start at its minimum. Don’t output spaces at the end of the line.
Input
The input will contain one tape.
Output
Output the message that is written on the tape.
Practice for Ad Hoc Problems ◾ 33
Hint
From the sample input, there are 10 characters a0…a9 in a line in a tape, where a0 is
leading flag ‘|’, a6 is a space, spaces in other positions represent 0, and ‘o’ represents 1.
29−i 7 ≤i ≤ 9
That is, if the i-th is ‘o’, the position represents an integer ai = 8−i . A line
2 2 ≤i ≤ 5
corresponds to an ASCII code representing a character. The character string is the
message that is written on the tape.
Input
Input contains no more than 100 lines, each giving a value of k (0<k≤10000).
Output
For each k, output the number of corresponding (x, y) pairs, followed by a sorted
list of the values of x and y, as shown in the sample output.
2 2
12 1/2 = 1/6 + 1/3
1/2 = 1/4 + 1/4
8
1/12 = 1/156 + 1/13
1/12 = 1/84 + 1/14
1/12 = 1/60 + 1/15
1/12 = 1/48 + 1/16
1/12 = 1/36 + 1/18
1/12 = 1/30 + 1/20
1/12 = 1/28 + 1/21
1/12 = 1/24 + 1/24
Source: Return of the Newbies 2005
ID for Online Judge: UVA 10976
Practice for Ad Hoc Problems ◾ 35
Hint
For a given positive integer k, find all pairs of positive integers x and y, x≥y,
1 1 1
such that = + . Obviously k+1≤y≤2k. For every possible y, check whether
k x y
y −k 1 k* y
the corresponding x is an integer or not. That is, because = , x= . If
(k×y)%(y−k)==0, then x is an integer. k* y x y −k
Input
The input file contains several lines of input. Each line contains a single integer n.
No integer has more than 6 digits. Input is terminated by end of file.
Output
For each line of input, you should output a single line. This line will contain a single
integer n! if the value of n! fits within the unsigned long integer of Arif’s computer.
Otherwise, the line will contain one of the following two words:
2 Underflow!
10 3628800
100 Overflow!
Source: GWCF Contest 4 - The Decider
ID for Online Judge: UVA 10323
Hint
The concept behind the problem is quite simple: given n, if n! is greater than
6227020800, then print “Overflow!”; if n! is less than 10000, print “Underflow!”;
otherwise print n!.
Though a negative factorial is normally undefined, this problem stretches the
limit of well-known definitions.
For this problem, we have F(n)=n×F(n−1), and F(0)=1. With some manip-
F (0)
ulations, for negative factorials, we can get: F(0)=0×F(−1), or F (−1)= =∞.
0
Continuing with this logic: F(−1)=−1×F(−2), or F(−2)=−F(−1). Similarly,
F (−1)= F (−3)=− F (−2) .
First, the offline method is used to calculate f [i]=i!, 8≤i≤13. Then, for each n:
1.3.18 Squares
A children’s board game consists of a square array of dots that contains lines con-
necting some of the pairs of adjacent dots. One part of the game requires that the
players count the number of squares of certain sizes that are formed by these lines.
For example, in Figure 1.6, there are three squares, two of size 1 and one of size 2.
(The “size” of a square is the number of line segments required to form a side.)
Your problem is to write a program that automates the process of counting all
the possible squares.
Input
The input file represents a series of game boards. Each board consists of a descrip-
tion of a square array of n2 dots (where 2≤n≤9) and some interconnecting horizontal
Practice for Ad Hoc Problems ◾ 37
Figure 1.6
and vertical lines. A record for a single board with n2 dots and m interconnecting
lines is formatted as follows:
Each of the next m lines are of one of two types: Hij, indicates a horizontal line
in row i which connects the dot in column j to the one to its right in column j+1;
or Vij, indicates a vertical line in column i which connects the dot in row j to the
one below in row j+1.
Information for each line begins in column 1. The end of input is indicated by
end of file. The first record of the sample input below represents the board of the
square above.
Output
For each record, label the corresponding output with “Problem #1”, “Problem #2”,
and so forth. Output for a record consists of the number of squares of each size
on the board, from the smallest to the largest. lf no squares of any size exist, your
program should print an appropriate message indicating this. Separate output for
successive input records by a line of asterisks between two blank lines, as shown in
the sample below.
4 Problem #1
16
H 1 1 2 square (s) of size 1
H 1 3 1 square (s) of size 2
H 2 1
(continued)
38 ◾ Algorithm Design Practice for Collegiate Programming
H 2 2 **********************************
H 2 3
H 3 2 Problem #2
H 4 2
H 4 3 No completed squares can be found.
V 1 1
V 2 1
V 2 2
V 2 3
V 3 2
V 4 1
V 4 2
V 4 3
2
3
H 1 1
H 2 1
V 2 1
Source: ACM World Finals 1989
ID for Online Judge: UVA 201
Hint
Since N≤9, we can simply iterate all the possible squares.
We can think of vertical or horizontal lines as edges between two adjacent
points. After that, we can take a three-dimensional array (say a[N ][N ][2]) to store
the count of horizontal (a[i][j][0]) edges and vertical (a[i][j][1]) edges. a[i][j][0] con-
tains the number of horizontal edges at row i up to column j. And a[i][j][1] contains
the number of vertical edges at column j up to row i. Next you use a O(n2) loop to
find a square. A square of size 1 is found if there is an edge from (i, j) to (i, j+1) and
(i, j+1) to (i+1, j+1) and (i, j) to (i+1, j) and (i+1, j) to (i+1, j+1). We can get this
just by subtracting the values calculated above.
two runner-up states combined: there are only 6.65 million cows in Kansas and
6.35 million cows in Nebraska.
There are several diseases that can threaten a herd of cows, the most feared
being “Mad Cow Disease” or Bovine Spongiform Encephalopathy (BSE); there-
fore, it is very important to be able to diagnose certain illnesses. Fortunately, there
are many tests available that can be used to detect these diseases.
A test is performed as follows. First, a blood sample is taken from the cow, and
then the sample is mixed with a test material. Each test material detects a certain
number of diseases. If the test material is mixed with a blood sample having any of
these diseases, then a reaction takes place that is easy to observe. However, if a test
material can detect several diseases, then we have no way to decide which of these
diseases is present in the blood sample, as all of them produce the same reaction.
There are materials that detect many diseases (such tests can be used to rule out
several diseases at once), and there are tests that detect only a few diseases (they can
be used to make an accurate diagnosis of the problem).
The test materials can be mixed to create new tests. If we have a test material
that detects diseases A and B, and there is another test material that detects diseases
B and C, then they can be mixed to obtain a test that detects diseases A, B, and
C. This means that if we have these two test materials, then there is no need for a
test material that tests diseases A, B, and C—such a material can be obtained by
mixing these two.
Producing, distributing, and storing many different types of test materials is
very expensive, and in most cases, unnecessary. Your task is to eliminate as many
unnecessary test materials as possible. It has to be done in such a way that if a test
material is eliminated, then it should be possible to mix an equivalent test from
the remaining materials. (“Equivalent” means that the mix tests exactly the same
diseases as the eliminated material, not more, not less.)
Input
The input contains several blocks of test cases. Each case begins with a line con-
taining two integers: the number 1≤n≤300 of diseases, and the number 1≤m≤200
of test materials. The next m lines correspond to the m test materials. Each line
begins with an integer, the number 1≤k≤300 of diseases that the material can
detect. This is followed by k integers describing the k diseases. These integers are
between 1 and n.
The input is terminated by a block with n=m=0.
Output
For each test case, you have to output a line containing a single integer: the maxi-
mum number of test materials that can be eliminated.
40 ◾ Algorithm Design Practice for Collegiate Programming
10 5 2
2 1 2 4
2 2 3
3 1 2 3
4 1 2 3 4
1 4
3 7
1 1
1 2
1 3
2 1 2
2 1 3
2 3 2
3 1 2 3
0 0
Source: ACM Central Europe 2005
IDs for Online Judges: POJ 2943, UVA 3524
There is one problem, however: Transporting wine from one house to another
results in work. Since all wines are equally good, the inhabitants of Gergovia don’t
care which persons they are doing trade with; they are only interested in selling or
buying a specific amount of wine. They are clever enough to figure out a way of
trading so that the overall amount of work needed for transports is minimized.
In this problem, you are asked to reconstruct the trading during one day in
Gergovia. For simplicity, we will assume that the houses are built along a straight
line with equal distance between adjacent houses. Transporting one bottle of wine
from one house to an adjacent house results in one unit of work.
Input
The input consists of several test cases.
Each test case starts with the number of inhabitants n (2≤n≤100000). The
following line contains n integers ai (−1000≤ai ≤1000). If ai ≥0, it means that the
inhabitant living in the i-th house wants to buy ai bottles of wine, otherwise if ai <0,
he wants to sell −ai bottles of wine. You may assume that the numbers ai sum up
to 0.
The last test case is followed by a line containing 0.
Output
For each test case, print the minimum number of work units needed so that every
inhabitant has his demand fulfilled. You may assume that this number fits into a
signed 64-bit integer (in C/C++ you can use the data type “long long”, or in JAVA
the data type “long”).
5 9
5 -4 1 -3 1 9000
6
-1000 -1000 -1000 1000 1000 1000
0
Source: Ulm Local 2006
ID for Online Judge: POJ 2940
Go through the values from left to right, and try to reduce them to 0 by using
greedily the closest values. To get the required linear time complexity, notice that
only values to the right can be used to reduce the current value to 0 (since all values
to the left are already 0). Therefore, we can add the current value to the next value
and add the absolute value to the number of work units needed.
Judges’ test data consists of 25 test cases, and most of them are random-generated.
Input
The input file contains less than 100000 lines. Each line contains two integers m
and n (less than 10101). Input is terminated by a line containing two zeros. This line
should not be processed.
Output
For each set of input, you must produce one line of output, which contains a single
digit. This digit is the last digit of mn.
2 2 4
2 5 2
0 0
Source: June 2003 Monthly Contest
IDs for Online Judge: UVA 10515
Hint
First, the regularity of the last digit of 8n is analyzed. And through it, the regularity
of the last digit of mn is obtained.
The last digit of 81 is 8. The last digit of 82 is 4. The last digit of 83 is 2. The last
digit of 84 is 6. The last digit of 85 is 8. The last digit of 86 is 4. ……. That is, there
are four times for one cycle. For example, for 81998, because 1998 mod 4=2, the last
digit of 81998 is 6.
Practice for Ad Hoc Problems ◾ 43
Likewise, for 2, 3, and 7, there are also four times for one cycle; for 4 and 9,
there are also two times for one cycle; and the last digit of any power of 5 and 6
is itself.
Therefore, the algorithm is as follows:
Suppose the last digit of m is k, and the last two digits of n is d. The last digit of
4 d %4 == 0
mn ans = (kp)%10, where p = .
d %4 d %4 ≠ 0
Example: If there are two houses, then three combinations are possible, as shown
in Figure 1.7.
Input
Each line of input contains a positive integer N (N≤2000). The meaning of N is
described in the above paragraph. A value of 0 for N indicates the end of input
which should not be processed.
Figure 1.7 Circles represent the transmission center and the small rectangles
represent the houses.
44 ◾ Algorithm Design Practice for Collegiate Programming
Output
For each line of input you have to output, on a single line, the number of possible
arrangements. You can safely assume that this number will have less than 1000
digits.
1 1
2 3
3 8
0
Hint
Let f(n) be the number of ways to connect the main transmission center and n
houses. By removing the main transmission center and its cables to the houses,
there will be one or more connected components of houses. Let k be the number
of houses of the rightmost connected component. Then, there are k ways to con-
nect one cable from the main transmission center to this component, and there are
f(n−k) ways to connect the main transmission center to the rest n−k houses.
So, there are k×f(n−k) ways to connect them all. Since the range of k is from
1 to n inclusive, by setting f(0)=1, we then have f(n)=1×f(n−1)+2×f(n−2)+...+
(n−1)×f(1)+n×f(0). fib(2×n)=fib(n+1)×fib(n)+fib(n)×f(n−1) (Fibonacci). Therefore,
f(n)=fib(2×n).
Chapter 2
In the real world, there are many problems that we can solve by simulating their
processes. Such problems are called simulation problems. For these problems, solu-
tion procedures or rules are shown in problem descriptions. Programs must simu-
late procedures or implement rules based on descriptions.
In this chapter, three kinds of simulations are introduced:
45
46 ◾ Algorithm Design Practice for Collegiate Programming
Cipher text: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
Plain text: V W X Y Z A B C D E F G H I J K L M N O P Q R S T U
Only letters are shifted in this cipher. Any non-alphabetical character should
remain the same, and all alphabetical characters will be uppercase.
Input
Input to this problem will consist of a (non-empty) series of up to 100 data sets.
Each data set will be formatted according to the following description, and there
will be no blank lines separating data sets. All characters will be uppercase.
A single data set has three components:
Output
For each data set, there will be exactly one line of output. This is the original mes-
sage by Caesar.
Analysis
Obviously, the problem is solved by strictly implementing the rule in the problem
description. The rule creating plain text out of Caesar’s messages is as follows:
A letter in the plain text = ‘A’+(A letter in the cipher text−‘A’+21)%26.
Program
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str; //Caesar's message
int i;
while (cin >> str) //Input Caesar's message
{
cin.ignore(INT_MAX, '\n');
if (str == "ENDOFINPUT") break;
getline(cin, str, '\n');
for (i = 0; i < str.length(); i++) // The rule
creating plain text
if (isalpha(str[i]))
str[i] = 'A' + (str[i] - 'A' + 21) % 26;
cout << str << endl; // Output the original message by
Caesar
48 ◾ Algorithm Design Practice for Collegiate Programming
Input
Input consists of several test cases. The first line of input for each case contains
1≤n≤100, 1≤k≤100 as defined above. For each game, a line follows containing p1,
m1, p2, m2. 1≤p1≤n and 1≤p2≤n are distinct integers identifying two players; m1 and
m2 are their respective moves (“rock”, “scissors”, or “paper”). A line containing 0
follows the last test case.
Output
Output one line each for player 1, player 2, and so on, through player n, giving the
player’s win average rounded to three decimal places. If the win average is unde-
fined, output “-”. Output an empty line between cases.
2 4 0.333
1 rock 2 paper 0.667
1 scissors 2 paper
1 rock 2 rock 0.000
2 rock 1 scissors 1.000
2 1
1 rock 2 paper
0
Source: Waterloo local 2005.09.17
IDs for Online Judges: POJ 2654, UVA 10903
Practice for Simulation Problems ◾ 49
Analysis
This is a problem for simulation of direct statement. In the problem description, a
player choosing paper wins over a player choosing rock; a player choosing scissors wins
over a player choosing paper; and a player choosing rock wins over a player choosing
scissors. A player choosing the same thing as the other player neither wins nor loses. A
tournament has been organized in which each of n players plays k rock-scissors-paper
games with each of the other players—k n(n − 1) games in total. For each test case,
2
cases are input one by one; and for each player, the number of games won and the
number of games lost are accumulated. Finally, the win average for each player is cal-
culated. For a player, if the number of games won and the number of games lost are
w
all 0, then the win average is undefined; else the win average for the player is .
w +l
Program
#include <stdio.h>
#include <string.h>
int w[200], l[200]; //For player i, the number of games won
w[i], and the number of games lost l[i]
int p1,p2,i,j,k,m,n; // n players, m test cases, k games
for each player, p1 and p2 play a game
char m1[10], m2[10]; //player p1 chooses m1[]; player p2
chooses m2[]
main(){
for (m=0; 1<=scanf("%d%d",&n,&k)&& n; m++) {//n players
play k rock-scissors-paper games with each of the other
players
if (m) {
printf("\n");
memset(w,0,sizeof(w)); //initialization
memset(l,0,sizeof(l));
}
for(i=0; i<k*n*(n-1)/2;i++){//Input players and moves
scanf("%d%s%d%s",&p1,m1,&p2,m2);
if (!strcmp(m1,"rock") && !strcmp(m2,"scissors") ||
!strcmp(m1,"scissors") && !strcmp(m2,"paper") ||
!strcmp(m1,"paper") && !strcmp(m2,"rock")) {
w[p1]++; l[p2]++; //p1 wins and p2 loses
}
50 ◾ Algorithm Design Practice for Collegiate Programming
2.1.3 Robocode
Robocode is an educational game designed to help learn Java. The players write
programs that control tanks fighting with each other on a battlefield. The idea of
this game may seem simple, but it takes a lot of effort to write a winning tank’s
program. Today we are not going to write an intelligent tank, but design a simpli-
fied Robocode game engine.
Assume that the whole battlefield is 120×120 (pixels). Each tank can only move
in the vertical and horizontal directions on the fixed path. (There are paths every
10 pixels in the battlefield in both vertical and horizontal directions. In all, there
are 13 vertical and 13 horizontal paths available for tanks, as shown in Figure 2.1.)
The shape and size of the tank are negligible, and one tank has (x, y) (x, y ∈ [0,
120]) representing its coordinate position and α (α ∈ {0, 90, 180, 270}) represent-
ing its facing direction (α = 0, 90, 180, or 270 means facing right, up, left, or down,
respectively). They have a constant speed of 10 pixels/second when they move and
they can’t move out of the boundary (on touching any boundary of the battlefield,
Y
0, 120
0, 0 120, 0 X
Figure 2.1
Practice for Simulation Problems ◾ 51
the tanks will stop moving, staying in the direction that they are currently facing).
The tank can shoot in the direction it’s facing whether it’s moving or still. The shot
moves at the constant speed of 20 pixels/second, and the size of the shot is also neg-
ligible. It will explode when it meets a tank on the path. It’s possible for more than
one shot to explode in the same place if they all reach a tank at the exact same time.
The tank being hit by the explosion will be destroyed and removed from the battle-
field at once. A shot exploding or flying out of the boundary will also be removed.
When the game begins, all the tanks are stopped at different crosses of the verti-
cal and horizontal paths. Given the initial information of all the tanks and several
commands, your job is to find the winner—the last living tank when all the com-
mands are executed (or omitted) and no shot exists in the battlefield (meaning that
no tank may die in the future).
Input
There are several test cases. The battlefield and paths are all the same for all test
cases as shown in Figure 2.1. Each test case starts with integers N (1≤N≤10) and
M (1≤M≤1000), separated by a blank. N represents the number of the tanks play-
ing in the battlefield, and M represents the number of commands to control the
movement of the tanks. The following N lines give the initial information (at time
0) of each tank, in the format:
Name x y α
The Name of a tank consists of no more than 10 letters. x, y, α are integers and
x, y∈{0, 10, 20, ..., 120}, α∈{0, 90, 180, 270}. Each field is separated by a blank.
The following M lines give commands in this format:
Time Name Content
Each field is separated by a blank. All the commands are given in the ascend-
ing order of Time (0≤Time≤30), which is a positive integer meaning the timestamp
when the commands are sent. Name points out which tank will receive the com-
mand. The Content has different types as follows:
MOVE When receiving the MOVE command, the tank starts to move in its facing
direction. If the tank is already moving, the command takes no effect.
STOP When receiving the STOP command, the tank stops moving. If the tank
has already stopped, the command takes no effect.
TURN When receiving the TURN command, the tank changes the facing
angle direction α to be ((α + angle + 360) mod 360), regardless of whether it is
moving or not. You are guaranteed that ((α + angle + 360) mod 360)
∈{0, 90, 180, 270}. The TURN command doesn’t affect the moving state
of the tank.
SHOOT When receiving the SHOOT command, the tank will shoot one shot in
the direction it’s facing.
52 ◾ Algorithm Design Practice for Collegiate Programming
Tanks take the corresponding action as soon as they receive the commands. For
example, if the tank at (0, 0), α=90, receives the command MOVE at time 1, it will
start moving at once and will reach (0, 1) at time 2. Notice that a tank could receive
multiple commands in one second and take the action one by one. For example, if
the tank at (0, 0), α=90, receives a command sequence of “TURN 90; SHOOT;
TURN −90”, it will turn to the direction α=180, shoot, and then turn back. If
the tank receives a command sequence of “MOVE; STOP”, it will remain in the
original position.
Some more notes you need to pay attention to:
If a tank is hit by an explosion, it will take not act on any of the commands
received at that moment. Of course, all the commands sent to the already
destroyed tank should also be omitted.
Although the commands are sent at discrete seconds, the movement and explo-
sions of tanks and shots happen in the continuous time domain.
No two tanks will meet on the path guaranteed by the input data, so you don’t
need to consider that situation.
All the input contents will be legal for you.
A test case with N=M=0 ends the input, and should not be processed.
Output
For each test case, output the winner’s name in one line. The winner is defined as
the last living tank. If there is no tank, or more than one tank living at the end,
output “NO WINNER!” in one line.
22 A
A 0 0 90 NO WINNER!
B 0 120 180 B
1 A MOVE
2 A SHOOT
22
A 0 0 90
B 0 120 270
1 A SHOOT
2 B SHOOT
26
A 0 0 90
B 0 120 0
1 A MOVE
2 A SHOOT
6 B MOVE
Practice for Simulation Problems ◾ 53
30 B STOP
30 B TURN 180
30 B SHOOT
00
Analysis
The problem is a simulation problem based on a sequence of time intervals. For
each command, 0≤Time≤30 (seconds), and states may be changed after the last
command is sent. Therefore, Robocode must be simulated for 45 seconds at most.
If a tank at (0, 0) shoots at a tank at (0, 1), and the tank at (0, 1) moves to the
tank at (0, 0), then the moving tank is shot after it moves 10/3 pixels, and after
0.5 seconds. Therefore, the map should be enlarged six times, and states should be
simulated every 1/6 seconds.
Attributes for tanks and shots are as follows: positions, directions, move (or
stop), and removed (or unremoved).
Starting at Time 0, commands are processed one by one. If the timestamp when
the current command is sent is t2, and the timestamp when the last command is
sent is t1, states from t1 to t2 must be simulated. Then attributes for the tank receiv-
ing the current command are set as follows:
If the command is the “MOVE” command, the tank receiving the command
moves in its facing direction;
If the command is the “STOP” command, the tank receiving the command
stops moving;
If the command is the “SHOOT” command and the tank receiving the com-
mand isn’t removed, then a shot is added, and its attributes are same as the
attributes of a tank, except MOVE;
If the command is TURN angle, then the tank receiving the command adjusts
angle
its facing direction as (the original number of direction + % 4 + 4 ) % 4,
90
angle
where the number of direction is .
90
After all commands are processed, states are simulated for 15 seconds continuously.
Finally, the number of living tanks at the end is calculated. If all tanks are
removed, or more than one tank lives, then output “NO WINNER!”; else output
the last living tank.
54 ◾ Algorithm Design Practice for Collegiate Programming
Program
#include <iostream>
#include <map>
#include <cstdio>
#include <cstring>
#include <string.h>
#include <string>
using namespace std ;
const int DirX[4] = { 10 , 0 , -10 , 0 } ; // Horizontal
increment and vertical increment
const int DirY[4] = { 0 , 10 , 0 , -10 } ;
#define mp make_pair
int N , M , Shoot ; //N: number of tanks, M: number of
commands, N+1..Shoot: Shots
int x[1050] , y[1050] , d[1050] ; // (x[ ], y[ ]) :
positions for tanks and shots; d[ ]: their directions
bool run[1050],die[1050] ; // run[ ]: flags for tanks'
moving, die[ ]: flags for tanks' or shots' removing
string symbol[1050] ; // symbol[i]: the i-th tank's name
map<string,int> Name ; // Name[s]: the sequence number of
the tank whose name is s
void Init()
{
Name.clear() ;
for ( int i = 1 ; i <= N ; i ++ ) //Initialization
{
cin >> symbol[i] >> x[i] >> y[i] >> d[i] ;
x[i] *= 6 ; y[i] *= 6 ;d[i] /= 90 ; // the map is
enlarged six times, direction numbers are calculated
run[i] = false ;die[i] = false ;
Name[symbol[i]] = i ;
}
Shoot = N ;
}
bool In( int x , int y ) //whether (x,y) is in the
boundary or not
{
if ( x >= 0 && x <= 6*120 && y >= 0 && y <= 6*120 )
return true ;
return false ;
}
void RunAll() // Situation in 1 time unit is simulated
{
for ( int i = 1 ; i <= N ; i ++ ) // All tanks are
simulated
Practice for Simulation Problems ◾ 55
{
if ( run[i] && !die[i] )
{
if ( In( x[i] + DirX[d[i]] , y[i] + DirY[d[i]]
) )
{
x[i] += DirX[d[i]] ;y[i] += DirY[d[i]] ;
}
else run[i] = false ;
}
}
for ( int i=N+1 ; i <= Shoot ; i ++ ) //All shots are
simulated
{
if ( !die[i] )
{
if ( In( x[i] + DirX[d[i]] * 2 , y[i] +
DirY[d[i]] * 2 ) )
{
x[i] += DirX[d[i]] * 2 ;y[i] += DirY[d[i]]
* 2 ;
}
else die[i] = true ;
}
}
for ( int i = 1 ; i <= N ; i ++ ) //unremoved tank i
{
if ( die[i] ) continue ;
for ( int j = N+1 ; j <= Shoot ; j ++ ) if ( !die[j] )
//if tank i is shot by shot j
{
if ( x[i] == x[j] && y[i] == y[j] )
{
die[j] = true ; die[i] = true ;
}
}
}
}
void Solve() //Process commands and output results
{
int now = 0 ; // Since Time 0
for ( int i = 1 ; i <= M ; i ++ ) //Time, Tank,
Content for each command
{
int t ; string sym , s ; int th ;
cin >> t >> sym >> s ;
t *= 6 ; // Time *6
while ( t > now ) { RunAll() ; now ++ ; }
//Simulating situations now ..t
56 ◾ Algorithm Design Practice for Collegiate Programming
2.1.4 Eurodiffusion
On January 1, 2002, 12 European countries abandoned their national currency
for a new currency, the euro. No more francs, marks, lires, guldens, kroner, ... only
euros, all over the eurozone. The same banknotes are used in all countries. And the
same coins? Well, not quite. Each country has limited freedom to create its own
euro coins.
Practice for Simulation Problems ◾ 57
“Every euro coin carries a common European face. On the obverse, member
states decorate the coins with their own motif. No matter which motif is on the
coin, it can be used anywhere in the 12 member states. For example, a French citi-
zen is able to buy a hot dog in Berlin using a euro coin with the imprint of the King
of Spain.” (Source: http://europa.eu.int/euro/html/entry.html.)
On January 1, 2002, the only euro coins available in Paris were French coins.
Soon the first non-French coins appeared in Paris. Eventually, one may expect all
types of coins to be evenly distributed over the 12 participating countries. (Actually
this will not be true. All countries continue minting and distributing coins with
their own motifs. So even in a stable situation, there should be an excess of German
coins in Berlin.) So, how long will it be before the first Finnish or Irish coins are in
circulation in the south of Italy? How long will it be before coins of each motif are
available everywhere?
You must write a program to simulate the dissemination of euro coins through-
out Europe, using a highly simplified model. Restrict your attention to a single euro
denomination. Represent European cities as points in a rectangular grid. Each city
may have up to four neighbors (one to the north, east, south, and west). Each city
belongs to a country, and a country is a rectangular part of the plane. Figure 2.2
shows a map with three countries and 28 cities. The graph of countries is con-
nected, but countries may border holes that represent seas, or non-euro countries,
such as Switzerland or Denmark. Initially, each city has one million (1000000)
coins in its country’s motif. Every day a representative portion of coins, based on
the city’s beginning day balance, is transported to each neighbor of the city. A
representative portion is defined as one coin for every full 1000 coins of a motif.
Figure 2.2
58 ◾ Algorithm Design Practice for Collegiate Programming
A city is complete when at least one coin of each motif is present in that city. A
country is complete when all of its cities are complete. Your program must deter-
mine the time required for each country to become complete.
Input
The input consists of several test cases. The first line of each test case is the number
of countries (1≤c≤20). The next c lines describe each country. The country descrip-
tion has the format: name xl yl xh yh, where name is a single word with 25 characters
at the most; xl yl are the lower-left city coordinates of that country (most south-
westward city) and xh yh are the upper-right city coordinates of that country (most
northeastward city): 1≤xl≤xh≤10 and 1≤yl≤yh≤10.
The last case in the input is followed by a single zero.
Output
For each test case, print a line indicating the case number, followed by a line for
each country with the country’s name and the number of days for that country to
become complete. Order the countries by days to completion. If two countries have
identical days to completion, order them alphabetically by name.
Use the output format shown in the example.
3 Case Number 1
France 1 4 4 6 Spain 382
Spain 3 1 6 3 Portugal 416
Portugal 1 1 2 2 France 1325
1 Case Number 2
Luxembourg 1 1 1 1 Luxembourg 0
2 Case Number 3
Netherlands 1 3 2 4 Belgium 2
Belgium 1 1 2 2 Netherlands 2
0
Analysis
In Europe there are n countries (1≤n≤20). Each country is a rectangular part of
the plane. Each city belongs to a country and is a point in the corresponding rect-
angular grid. Initially, each city has one million (1000000) coins in its country’s
Practice for Simulation Problems ◾ 59
motif. Every day a representative portion of coins, based on the city’s beginning
day balance, is transported to each neighbor of the city. In a day, if a city has
From day 0 (ans←0), the dissemination of coins is simulated day by day until
cnt==m:
++ans;
The current state o2 is calculated based on the precursor
state o1(f[o2]=f[o1], st[o2]=st[o1]);
Each city i(0≤i≤m−1) is enumerated:
{ The binary digit k whose value is 1 in st[o1][i] is
enumerated:
The number of motif k transported to each neighborhood of
f[o1][i][k ]
city i d is calculated d = ;
103
if (d≠0)
{ f[o2][i][k]−=g[i]*d;
}
}
o1 ↔ o2;
After the above simulation, number of days for m cities to become complete is
day[ ]. Based on that, a[k].ans=maxy∈country kday[y]; 0≤k≤n−1.
Finally, a[ ] is sorted: a[ ].ans is as the first key, and a[ ].name is as the second
key. And a[i].name and a[i].ans (0≤i≤n−1) are output line by line.
Practice for Simulation Problems ◾ 61
Program
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define ms(x, y) memset(x, y, sizeof(x))
#define mc(x, y) memcpy(x, y, sizeof(x))
const int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
// shift for 4 directions
struct city { // city
char name[30]; // city name
int ans; // the number of days for the city to become
complete
};
int cs(0);
int log2[1 << 21]; // log2[2i]=i
int n, tot, full; //n: the number of countries, tot: the
number of cities, full: the mark that n countries become
complete
city a[22]; //the sequence of countries
int bl[22], br[22]; // for country i, bl[i]: the first
city, br[i]: the last city
int num[11][11], belong[122]; //num[x][y]: the number of
the city at (x, y), belong[t]: the country that city t belongs
to
int g[122]; //g[i]: the number of neighboring cities for
city i
int edge[122][4]; // edge[i][l] is the number of lth
neighboring vertex for vertex i
int o1, o2, f[2][122][22]; // precursor state o1 and
current state o2; f[o][i][j] is the number of coins in motif j
in city i in state o
int day[122], st[2][122]; // day[y]: Number of days for
city y to become complete, st[o][i] are marks for all motifs
in city i, represented as a binary number with n digits: if
the k-th digit is 1, city i has the coin in motif k;
otherwise, city i does not have the coin in motif k; 0≤k≤n−1.
bool cmp(const city &a, const city &b) { // Compare country
a and b (the first key is the number of days for a country to
become complete, and the second key is names of countries)
return a.ans < b.ans || a.ans == b.ans && strcmp(a.name,
b.name) < 0;
}
void print() { //Output the solution to the current
test case
62 ◾ Algorithm Design Practice for Collegiate Programming
method. The structure and idea for the simulation by sieve method is concise and
clear, but it is also blind. Therefore, its time efficiency may not be good. The key to
the simulation by sieve method is to find the constraints. Any errors and omissions
will lead to failure. Because filtering rules do not need complex algorithm design,
such problems are usually simple simulation problems.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Figure 2.3
Practice for Simulation Problems ◾ 65
where the black and the white both win at the same time. Also, there will be no
input data where the white or the black wins in more than one place.
Input
The first line of the input file contains a single integer t (1≤t≤11), the number of
test cases, followed by the input data for each test case. Each test case consists of
19 lines, each having 19 numbers. A black stone is denoted by 1, a white stone is
denoted by 2, and 0 denotes no stone.
Output
There should be one or two line(s) per test case. In the first line of the test case
output, you should print 1 if black wins, 2 if white wins, and 0 if nobody wins
yet. If black or white won, in the second line print the horizontal line number
and the vertical line number of the leftmost stone among the five consecutive
stones. (Select the uppermost stone if the five consecutive stones are located
vertically.)
1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 2 0 0 2 2 2 1 0 0 0 0 0 0 0 0 0 0
0 0 1 2 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 2 2 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 2 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Direction 2: Right up
Figure 2.4
Analysis
Initially all stones on the 19×19 board constitute a sieve. Every stone is scanned
from top to down and from left to right. If there is a stone at position (i, j), its adja-
cent stones in direction k are analyzed (0≤k≤3, 0≤i, j≤18), as shown in Figure 2.4.
The objective of this game is to put five stones of the same color consecutively
along a horizontal, vertical, or diagonal line. Therefore, the constraint conditions
for winning a game are as follows:
1. The number at position (i, j) is different from the number at the adjacent posi-
tion in the opposite direction for direction k;
2. From (i, j) and along direction k, five positions are in the board;
3. From (i, j) and along direction k, numbers at five continuous positions are the
same, and the number at the sixth position is different, or the sixth position
is out of the board.
If the above constraint conditions hold, the stone at position (i, j) wins the
game. If four directions are examined and the above constraint conditions don't
hold, the stone at position (i, j) is filtered out.
If all stones are filtered out, nobody wins the game.
Program
#include <iostream>
using namespace std;
const int d[4][2] = {{0, 1}, {1, 0}, {1, 1}, {-1, 1}};
//displacements for 4 directions
Practice for Simulation Problems ◾ 67
Input
The input contains several test cases. Each test case starts with an integer n (2≤n≤1000),
the number of teams participating in the tournament. The following n lines
contain the names of the teams participating in the tournament. You can assume
that each team name consists of up to 25 letters of the English alphabet (‘a’ to ‘z’ or
‘A’ to ‘Z’).
Then follow n−1 lines, describing the games that Sheikh Abdul would like to see
(in any order). Each line consists of the two names of the teams which take part in
that game. You can assume that it is always possible to find a tournament schedule
consisting of the given games.
The last test case is followed by a zero.
Output
For each test case, write the game schedule, distributed in rounds.
For each round, first write “Round #X ” (where X is the round number) in a line
by itself. Then write the games scheduled in this round in the form: “A defeats B”,
where A is the name of the advancing team and B is the name of the team being
eliminated. You may write the games of a round in any order. If a wildcard is needed
Practice for Simulation Problems ◾ 69
for the round, write “A advances with wildcard” after the last game of the round,
where A is the name of the team which gets the wildcard. After the last round, write
the winner in the format shown below. Print a blank line after each test case.
3 Round #1
A B defeats A
B C advances with wildcard
C Round #2
AB C defeats B
BC Winner: C
5
A Round #1
B A defeats B
C C defeats D
D E advances with wildcard
E Round #2
AB E defeats A
CD C advances with wildcard
AE Round #3
CE E defeats C
0 Winner: E
Analysis
There are n teams and n−1 games. For n−1 games that Sheikh Abdul would like to
see, the two names of the teams which take part in the game are stored in a[i] and
b[i] respectively, 1≤i≤n−1. Numbers of games that teams take part in are stored in
cnt[i], 1≤i≤n.
Constraints in the problem description constitute a sieve. Initially all teams are
put on the sieve.
Sheikh Abdul would like to see every game in each round. In a round, a team
which will take part in other games will win the game. Constraints constituting a
sieve are as follows:
In each round, the number of games is the number of teams in the current round
divided by 2.
In each round, n−1 games that Sheikh Abdul would like to see are searched
sequentially. For game i, 1≤i≤n−1, if a[i] and b[i] are in the sieve, and one
70 ◾ Algorithm Design Practice for Collegiate Programming
team can only take part in one game, then the game that a[i] and b[i] take
part in is in the round, and the team that has only one game is defeated and
filtered out. After n−1 games are searched, teams in the sieve enter the next
round.
Program
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
using namespace std;
const int maxN=1010;
int n,a[maxN],b[maxN],cnt[maxN]; //n: the number of teams;
teams taking part in game i are a[i] and b[i], 1≤i≤n−1; the
number of games that team k is taking part in is cnt[k], 1≤k≤n
char name[maxN][30]; //teams' names
bool flag[maxN]; //the flag indicates whether a team is in
the sieve or not
map<string,int> que;
bool cmp(int a,string s) //determine whether the name for
team a is s or not
{
for (int i=0;i<s.size();i++)
if (name[a][i]!=s[i]) return false;
return true;
}
void init() //Input a test case: n teams and n−1 games
{
que.clear();
for (int i=1;i<=n;i++) //team's name
{
scanf("%s",name[i]);
que.insert(map<string,int>::value_type(name[i],i));
//teams' numbers
}
string s;
int p;
char ch;scanf("%c",&ch);
for (int i=1;i<n;i++) // n−1 games
Practice for Simulation Problems ◾ 71
{
scanf("%c",&ch);s="";
while (ch!=' ') { s+=ch;scanf("%c",&ch);}
p=que[s];
cnt[p]++;a[i]=p;
scanf("%c",&ch);s="";
while (ch!='\n') { s+=ch;scanf("%c",&ch);}
p=que[s];
cnt[p]++;b[i]=p;
}
}
void work() // calculate and output the game schedule,
distributed in rounds
{
int rnd=1,tm=n,s=n/2,now=0; //rnd: the number of the
current round, tm: the number of teams in the sieve, s: the
number of games in a round, now: the number of hold games in a
round
memset(flag,1,sizeof(flag)); // Initially all teams are
put on the sieve
while (tm!=1) // only one team left
for (int i=1;i<n;i++) // n−1 games are searched
sequentially
if (flag[a[i]]&&flag[b[i]]&&((cnt[a[i]]==1)||(cnt
[b[i]]==1)))//two teams are on the sieve, at least one team
can only take part in a game
{
if (now==0)printf("Round #%d\n",rnd);// the round
number
now++;tm--; //number of hold games in the current
round +1,
cnt[a[i]]--;cnt[b[i]]--;
// if only b[i] take part in one game, b[i] is defeated; if
only a[i] take part in one game, a[i] is defeated; and if a[i]
and b[i] take part in one game, b[i] wins
if (cnt[a[i]]) printf("%s defeats %s\n",name[a[i]],
name[b[i]]);
else if (cnt[b[i]]) printf("%s defeats %s\n",
name[b[i]],name[a[i]]);
else{
printf("%s defeats %s\n",name[b[i]],
name[a[i]]);
printf("Winner: %s\n",name[b[i]]);}
flag[a[i]]=false;flag[b[i]]=false;
if (now==s)
{
now=0;rnd++;s=tm/2;
for (int i=1;i<=n;i++) // wildcard for the team
that doesn't take part in a game in the round
{
72 ◾ Algorithm Design Practice for Collegiate Programming
2.3.1 Packets
A factory produces products packed in square packets of the same height h and of the
sizes 1×1, 2×2, 3×3, 4×4, 5×5, and 6×6. These products are always delivered to cus-
tomers in the square parcels of the same height h as the products have and of the size
6×6. Because of the expenses, it is in the interest of the factory as well as of the cus-
tomer to minimize the number of parcels necessary to deliver the ordered products
from the factory to the customer. A good program, solving the problem of finding
the minimum number of parcels necessary to deliver the given products according
to an order, would save a lot of money. You are asked to create such a program.
Input
The input file consists of several lines specifying orders. Each line specifies one
order. Orders are described by six integers separated by one space, representing
successively the number of packets of individual size from the smallest size 1×1 to
the biggest size 6×6. The end of the input file is indicated by the line containing
six zeros.
Practice for Simulation Problems ◾ 73
Output
The output file contains one line for each line in the input file. This line contains
the minimal number of parcels into which the order from the corresponding line
of the input file can be packed. There is no line in the output file corresponding to
the last “null” line of the input file.
0 0 4 0 0 1 2
7 5 1 0 0 0 1
0 0 0 0 0 0
Analysis
The simulation problem is solved by the construction method. The greedy method
is also used. Packets are packed in parcels in descending order by size. Because the
parcels’ size is 6×6, each packet sized 4×4, 5×5, or 6×6 is packed in a parcel. The
strategy is as follows:
The number of packets sized 1×1 and which can be packed in above M par-
cels is L1=M×36−a6×36−a5×25−a4×16−a3×9−a 2×4. If there are remain-
ing packets sized 1×1 (a1>L1), they are packed in new a1 − L1 parcels.
36
a − L
And M + = 1 1 .
36
Obviously, M is the minimum number of parcels.
Program
#include <iostream>
using namespace std;
int main()
{
int a[10],i,j,sum,m,left1,left2; // the number of packets
whose size are i*i is a[i], the number of packets is sum, the
minimal number of parcels is m; the number of parcels in which
2*2 can be packed is left2, the number of parcels in which 1*1
can be packed is left1
int u[4]={0,5,3,1}; // u[a[3]% 4]
while (1)
{
sum=0;
for(i=1;i<=6;i++) //Input the number of packets
{
cin>>a[i];
sum+=a[i];
}
if(sum==0) break;
m=a[6]+a[5]+a[4]+(3+a[3])/4; // The number of parcels
in which packets whose size are 6*6, 5*5, 4*4, and 3*3 are
packed
left2=a[4]*5+u[a[3]%4]; // the number of parcels in
which 2*2 can be packed is left2
if(a[2]>left2) //If there are remaining 2*2 packets,
new parcels are needed
m+=(a[2]-left2+8)/9;
left1=m*36-a[6]*36-a[5]*25-a[4]*16-a[3]*9-a[2]*4; //
the number of parcels in which 1*1 can be packed is left1
if(a[1]>left1) // If there are remaining 1*1 packets,
new parcels are needed
m+=(a[1]-left1+35)/36;
cout<<m<<endl; // the minimal number of parcels
}
return 0;
}
Practice for Simulation Problems ◾ 75
Input
The input consists of several test cases. Each of them is specified by six positive inte-
ger numbers, A, B, C, D, E, and F, on one line separated by a space. The numbers
are:
A and B are the size of a rectangular grid, 1≤A, B≤1000; C and D are the dimen-
sions of a card in cms, 1≤C, D≤1000; and E and F are the dimensions of a
paper sheet in cms, 1≤E, F ≤1000000.
The input is terminated by a line containing six zeros.
8 × 3 cm
6 × 4 cm
4 × 6 cm
3 × 8 cm
Figure 2.5
76 ◾ Algorithm Design Practice for Collegiate Programming
Output
For each of the test cases, output a single line. The line should contain the text:
“The minimum number of cuts is X.”, where X is the minimum number of cuts
required. If it is not possible to fit the card grid onto the sheet, output the sentence
“The paper is too small.” instead.
Analysis
First, the cutting machine cuts the paper to produce grids. Then it cuts grids to pro-
duce cards. Suppose A×B is the size of a rectangular grid; C×D is the size of a card;
and E×F is the size of a paper sheet. In the longitudinal direction, there are A cards
whose length is C. That is, the length is A×C in the longitudinal direction. In the
horizontal direction, there are B cards whose length is D. That is, the length is B×D
in the horizontal direction. The constraint condition is (A×C≤E)&&(B×D≤F).
In order to produce A×B rectangular grids, at least A×B−1 cuts are needed.
If A×C<E in the longitudinal direction, a cut is needed. And if B×D<F in the
horizontal direction, a cut is added. Therefore, the minimal number of cuts
C0 =A×B−1+(A×C<E)+(B×D<F).
Grids can be turned 90°, 180°,, and 270°. Cases are as follows:
1. B×A is the size of a rectangular grid; C×D is the size of a card; and E×F is the
size of a paper sheet.
2. A×B is the size of a rectangular grid; D×C is the size of a card; and E×F is the
size of a paper sheet.
3. B×A is the size of a rectangular grid; D×C is the size of a card; and E×F is the
size of a paper sheet.
Based on the above method, the minimum numbers of cuts are C1, C 2 ,
and C3, respectively. If the constraint condition doesn’t hold, the minimum
Practice for Simulation Problems ◾ 77
Program
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define TOOBIG INT_MAX
int ncuts(int a,int b,int c,int d,int e,int f) ;
void do_solve(int a,int b,int c,int d,int e,int f)
//enumerate four cases and calculate the minimal numbers of
cuts
{
int x,m ;
m=ncuts(a,b,c,d,e,f) ; //Case 0: C0
if ((x=ncuts(b,a,c,d,e,f))<m) m=x ; // Case 1: C1
if ((x=ncuts(a,b,d,c,e,f))<m) m=x ; // Case 2: C2
if ((x=ncuts(b,a,d,c,e,f))<m) m=x; // Case 3: C3
if (m==TOOBIG)
puts("The paper is too small.") ;
else
printf("The minimum number of cuts is " "%d.\n",m) ;
}
int ncuts(int a,int b,int c,int d,int e,int f)
{
if (a*c>e || b*d>f) return TOOBIG ; // constraint
condition
return a*b-1+(a*c<e)+(b*d<f) ; // the minimal number of
cuts
}
int main()
{ int a,b,c,d,e,f ;
for(;;) {
a=0 ; b=0 ; c=0 ; d=0 ; e=0 ; f=0 ;
scanf("%d %d %d %d %d %d",&a,&b,&c,&d,&e,&f) ; //a test
case
if (!a && !b && !c && !d && !e && !f) break ;
do_solve(a,b,c,d,e,f) ;
}
return 0 ;
}
78 ◾ Algorithm Design Practice for Collegiate Programming
2.4 Problems
2.4.1 Mileage Bank
The Mileage program of ACM (Airline of Charming Merlion) is good for travelers
who fly frequently. Once you complete a flight with ACM, you can earn ACMPerk
miles in your ACM Mileage Bank, depending on the mileage you actually fly. In
addition, you can use the ACMPerk mileage in your Mileage Bank to exchange for
a free flight ticket from ACM in the future.
The following table helps you calculate how many ACMPerk miles you can earn
when you fly on ACM.
Economy Class Y
1–500 miles 500 miles
500+ miles Actual mileage
The ACMPerk mileage consists of two parts. One is the actual flight mile-
age (the minimum ACMPerk mileage for the economy class for one flight is
500 miles), and the other is the mileage bonus (its accuracy is up to one mile)
when a traveller flies in business class and first class. For example, one can earn
1329 ACMPerk miles, 1994 ACMPerk miles, and 2658 ACMPerk miles for Y, B,
or F class, respectively, for the flight from Beijing to Tokyo (the actual mileage
between Beijing and Tokyo is 1329 miles). When one flies from Shanghai to
Wuhan, one can earn ACMPerk 500 miles for economy class and ACMPerk
650 miles for business class (the actual mileage between Shanghai and Wuhan
is 433 miles).
Your task is to help ACM build a program for automatic calculation of ACMPerk
mileage.
Input
The input file contains several data cases. Each case has many flight records, each
per line. The flight record is in the following format:
OriginalCity DistanceCity ActualMiles ClassCode
Output
Output the summary of ACMPerk mileages for each test case, one per line.
Hint
The problem is a simple, straightforward simulation problem. First, flight records
are input one by one. Then, based on the rule in the problem description, the sum-
mary of ACMPerk mileages is calculated.
2.4.2 Cola
You see the following special offer by a convenience store:
“A bottle of Choco Cola for every 3 empty bottles returned”
Now you decide to buy some (say N) bottles of cola from the store. You would
like to know how you can get the most cola from them.
Figure 2.6 shows the case where N=8. Method 1 is the standard way: after
finishing your eight bottles of cola, you have eight empty bottles. Take six of them
and you get two new bottles of cola. Now after drinking them, you have four empty
8 8
2 3
+ 1 + 1
11 12
Figure 2.6
80 ◾ Algorithm Design Practice for Collegiate Programming
bottles, so you take three of them to get yet another new cola. Finally, you have
only two bottles in hand, so you cannot get a new cola any more. Hence, you have
enjoyed 8 + 2 + 1 = 11 bottles of cola.
You can actually do better! In method 2, you first borrow an empty bottle from
your friend (or the storekeeper??), and then you can enjoy 8 + 3 + 1 = 12 bottles of cola!
Of course, you will have to return your remaining empty bottle back to your friend.
Input
Input consists of several lines, each containing an integer N (1≤N≤200).
Output
For each case, your program should output the maximum number of bottles of cola
you can enjoy. You may borrow empty bottles from others, but if you do that, make
sure that you have enough bottles afterward to return to them.
8 12
Hint
Suppose n is the number of bottles of cola you buy from the store initially; i is the
number of empty bottles you borrow; cnt is the total number of bottles, initially
cnt=n+i; tot is the number of bottles of cola you can enjoy, initially tot=n; and ans
is the maximum number of bottles of cola you can enjoy, initially ans=0.
The “trick” is that borrowing more than two bottles does not help—you would
have to return the extra bottles without trading them in, and the borrowing should
be done in the beginning, since it would cascade down otherwise. Therefore, the
program only needs to simulate borrowing either 0, 1, or 2 bottles. For each case,
we simulate the process as follows:
Repeat the process until cnt<3:
The number of produced empty bottles tmp=cnt%3;
The number of increased bottles of cola cnt/=3;
The number of bottles of cola you can enjoy tot+=cnt;
The number of increased empty bottles cnt+=tmp;
if (cnt≥i && tot>ans) ans=tot; // you can return remaining
empty bottles back to your friend, and drink more.
Step 1: Choose an arbitrary positive integer A as the first item in the sequence.
Step 2: If A = 1 then stop.
Step 3: If A is even, then replace A by A/2 and go to Step 2.
Step 4: If A is odd, then replace A by 3×A+1 and go to Step 2.
It has been shown that this algorithm will always stop (in Step 2) for initial
values of A as large as 109, but some values of A encountered in the sequence may
exceed the size of an integer on many computers. In this problem, we want to
determine the length of the sequence that includes all values produced until either
the algorithm stops (in Step 2), or a value larger than some specified limit would be
produced (in Step 4).
Input
The input for this problem consists of multiple test cases. For each case, the input
contains a single line with two positive integers, the first giving the initial value of
A (for Step 1) and the second giving L, the limiting value for terms in the sequence.
Neither of these, A or L, is larger than 2147483647 (the largest value that can be
stored in a 32-bit signed integer). The initial value of A is always less than L. A line
that contains two negative integers follows the last case.
Output
For each input case, display the case number (sequentially numbered starting with
1), a colon, the initial value for A, the limiting value L, and the number of terms
computed.
Hint
This is a “follow the instructions” problem. Given the initial value of a (for Step 1)
and the limiting value for terms in the sequence l, the number of terms ans is
calculated as follows:
ans=0;
while(a<=l&&a!=1){
ans++;
a=a&1?3*a+1:a/2;
}
if(a==1) ans++;
Start
here!
A Count
this
C way
E
. . .
. . . T
W
O
Figure 2.7
Practice for Simulation Problems ◾ 83
Input
Input consists of several test cases. Each case begins with an integer N (1≤N≤52),
the number of cards to be used in the magic trick. The following N lines show the
order of the turning over of the cards and the words to be spelled. None of the
words will have more than 20 characters. The format for each card is a string with
two characters: first the value, and second, the suit.
Input ends with a test case where N=0. This test case should not be processed.
Output
For each case, your program should output the initial arrangement of the cards.
13 QH 4C AS 8D KH 2S 7D 5C TH JH 3S 6C 9D
AS ACE
2S TWO
3S THREE
4C FOUR
5C FIVE
6C SIX
7D SEVEN
8D EIGHT
9D NINE
TH TEN
JH JACK
QH QUEEN
KH KING
0
Hint
N cards are arranged in a circle. Starting from a certain card, the magician counts
cards in a clockwise direction and spells N words. When the last letter of a word is
pronounced, he turns over the card and removes it from the circle.
Given the sequence of words, and the order in which the cards are removed,
find the initial arrangement of cards in the circle.
The algorithm simulates the magician’s actions and recovers the arrangement
of cards.
84 ◾ Algorithm Design Practice for Collegiate Programming
Input
Each line of input (except the last) contains a number n≤50. The last line contains
0, and this line should not be processed.
Output
For each number from the input, produce two lines of output. The first line presents
the sequence of discarded cards, and the second line reports the last remaining card.
No line will have leading or trailing spaces. See the sample for the expected format.
7 Discarded cards: 1, 3, 5, 7, 4, 2
19 Remaining card: 6
10 Discarded cards: 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 4, 8, 12, 16, 2, 10, 18, 14
6 Remaining card: 6
0 Discarded cards: 1, 3, 5, 7, 9, 2, 6, 10, 8
Remaining card: 4
Discarded cards: 1, 3, 5, 2, 6
Remaining card: 4
Hint
Simulate the problem as described. A queue is used to simulate efficiently.
2.4.6 Gift?!
There is a beautiful river in a small village. There are n rocks arranged in a straight
line numbered 1 to n from the left bank to the right bank, as shown below:
[Left Bank] - [Rock1] - [Rock2] - [Rock3] - [Rock4] ... [Rock n] - [Right Bank]
Practice for Simulation Problems ◾ 85
The distance between two adjacent rocks is exactly 1 meter, while the distance
between the left bank and rock 1, and between rock n and the right bank, is also
1 meter.
Frog Frank was about to cross the river. His neighbor Frog Funny came to him
and said,
“Hello, Frank. Happy Children’s Day! I have a gift for you. See it? A little parcel
on Rock 5.”
“Oh, that's great! Thank you! I’ll get it.”
“Wait...This present is for smart frogs only. You can’t get it by jumping to it directly.”
“Oh? Then what should I do?”
“Jump more times. Your first jump must be from the left bank to Rock 1, then,
jump as many times as you like—no matter forward or backward, but
your i-th jump must cover 2×i−1 meters. What’s more, once you return
to the left bank or reach the right bank, the game ends, and no more
jumps are allowed.”
“Hmmm, not easy... let me think!” answered Frog Frank. “Should I give it a try?”
Input
The input will contain no more than 2000 test cases. Each test case contains a sin-
gle line. It contains two positive integers n (2≤n≤106), and m (2≤m≤n), m indicates
the number of the rock on which the gift is located. A test case in which n=0, m=0
will terminate the input and should not be regarded as a test case.
Output
For each test case, output a single line containing “Let me try!” if it’s possible to
get to rock m; otherwise, output a single line containing “Don’t make fun of me!”.
Hint
Suppose n rocks are arranged in a straight line numbered 1 to n from the left bank
to the right bank, and m indicates the number of the rock on which the gift is
located. It can be proved, if n>50, Frog Frank can reach each rock. If n≤50, we need
to determine whether Frog Frank can reach a rock or not. First, the offline method
is to determine whether Frog Frank can reach a rock or not.
Then, for each test case n and m, if n≤50, output the result based on ans[n][m].
2.4.7 A-Sequence
For this problem an A-sequence is a sequence of positive integers ai satisfying
1≤a1<a 2<a3<... and every ak of the sequence is not the sum of two or more distinct
earlier terms of the sequence.
You should write a program to determine if a given sequence is or is not an
A-sequence.
Input
The input consists of a set of lines; each line starts with an integer 2≤D≤30 that
indicates the number of integers that the current sequence has. Following this num-
ber there is the sequence itself. The sequence is composed by integers; each integer
is greater than or equal to 1 and less than or equal to 1000. The input is terminated
by end of file (EOF).
Output
For each test case in the input you should print two lines: the first line should
indicate the number of the test case and the test case itself; in the second line
you should print “This is an A-sequence.”, if the corresponding test case is an
A-sequence, or “This is not an A-sequence.”, if the corresponding test case is not
an A-sequence.
Practice for Simulation Problems ◾ 87
Hint
The problem requires you to determine whether a sequence of positive integers is
an A-sequence or not. If a sequence of positive integers is an A-sequence, then the
sequence of positive integers is in the ascending order, and every element of the
sequence is not the sum of two or more distinct earlier terms of the sequence.
For a test case, positive integers are input one by one. Suppose sums of two or
more distinct earlier terms of the sequence are stored in g[]; z is the current input
integer; and la is the previous integer.
For the current integer z, if z is the sum of two or more distinct earlier terms of
the sequence, or z≤la, then the sequence isn’t an A-sequence, and exit the process.
Else, first, elements in g[] and z are analyzed: if for all g[i], g[i]+z isn’t in g[], a new
element g[i]+z is added into g[]; then la=z, and the next integer z is input. After all
elements in the sequence are dealt with, the sequence is an A-sequence.
Input
The input file consists of a first line with the number p of cases to solve. The first line
of each case contains the number of available floors. Then, the size and color of each
floor appear in one line. Each floor is represented with an integer between −999999
and 999999. There is no floor with size 0. Negative numbers represent red floors
and positive numbers represent blue floors. The size of the floor is the absolute value
of the number. There are no two floors with the same size. The maximum number
of floors for a problem is 500000.
Output
For each case the output will consist of a line with the number of floors of the high-
est building with the mentioned conditions.
2 2
5 5
7
−2
6
9
−3
8
11
−9
2
5
18
17
−15
4
Hint
First, the sizes of the floors are sorted in descending order. Second, we set the low-
est floor for the building as blue, and design the highest possible building with the
restrictions in the problem description. The number of floors of the highest build-
ing is l1. Third, we set the lowest floor for the building as red, and design the highest
Practice for Simulation Problems ◾ 89
possible building with the restrictions in the problem description. The number of
floors of the highest building is l2.
Obviously, the number of floors of the highest building is max{l1, l2}.
First bulb Second bulb Third bulb (n – 1)st bulb nth bulb
Figure 2.8
90 ◾ Algorithm Design Practice for Collegiate Programming
You must write a program that determines the switches that must be flipped to
change a row of light bulbs from its initial state to its desired final state with minimal
cost. Some combinations of initial and final states may not be feasible. For compact-
ness of representation, decimal integers are used instead of binary for the bulb config-
urations. Thus, 01100 and 10000 are represented by the decimal integers 12 and 16.
Input
The input file contains several test cases. Each test case consists of one line. The line
contains two non-negative decimal integers, at least one of which is positive and
each of which contains at most 100 digits. The first integer represents the initial
state of the row of bulbs, and the second integer represents the final state of the row.
The binary equivalent of these integers represents the initial and final states of the
bulbs, where 1 means ON and 0 means OFF.
To avoid problems with leading zeros, assume that the first bulb in either the
initial or the final configuration (or both) is ON. There are no leading or trailing
blanks in the input lines, no leading zeros in the two decimal integers, and the
initial and final states are separated by a single blank.
The last test case is followed by a line containing two zeros.
Output
For each test case, print a line containing the case number and a decimal integer
representing a minimum-cost set of switches that need to be flipped to convert the
row of bulbs from initial state to final state. In the binary equivalent of this inte-
ger, the rightmost (least significant) bit represents the nth switch, 1 indicates that
a switch has been flipped, and 0 indicates that the switch has not been flipped. If
there is no solution, print “impossible”. If there is more than one solution, print the
one with the smallest decimal equivalent.
Print a blank line between cases. Use the output format shown in the example.
12 16 Case Number 1: 8
1 1 Case Number 2: 0
3 0 Case Number 3: 1
30 5 Case Number 4: 10
7038312 7427958190 Case Number 5: 2805591535
4253404109 657546225 Case Number 6: impossible
0 0
Hint
Every switch is either flipped or not, and can’t be flipped more. After the first
switch’s operation is determined, only the second switch’s operation can control
the first bulb. The second switch’s operation is determined. Therefore, all switches’
operation can be determined, and so on. The simulation algorithm is as follows.
First, determine whether the first switch should be flipped or not, and then every
switch is enumerated one by one to determine all operations. High precision num-
bers are used to represent the states of the row of bulbs.
A A B C H
E D E G
B E C F H
Figure 2.9
92 ◾ Algorithm Design Practice for Collegiate Programming
This continues until no more blocks can be moved to a new position following the
moving rules. Note that inside each turn of checking, each of the blocks is checked
and possibly moved only once. Blocks must not be checked and moved on its new
position in one turn of checking.
Robert felt that the game was very interesting. However, after some time of
playing, he found that when the size of the board is rather large, finding a pair of
blocks becomes a very tough job. Furthermore, he often gets a ‘Game Over’ because
no more blocks can be popped. Robert felt that it is not his fault that not all the
blocks are being popped. It is only that there is a great chance that the game cannot
be finished if the blocks are placed randomly at first. However, it will be very time-
consuming to prove this by playing the game many times. So, Robert asks you to
write a program for him that will simulate his behavior in the game and see if the
game can be finished.
In order to make such a program possible, Robert summarizes his rules of
selecting block pairs as follows. First, the pair of blocks that can be linked with
one straight line segment must be found and popped because such pairs are easy
to find. Next, if such a pair does not exist, the pairs that can be linked by two
straight line segments must be found and popped. Finally, if both the above
described pairs do not exist, the pairs that can be linked by three straight line
segments must be found and popped. If more than one pair that can be linked
with the same number of straight line segments exists, the pair that contains a
block, which is positioned at the topmost row (or leftmost if two more blocks are
positioned in the same row), will be selected first. If this rule still cannot break
the tie (more than one pair may share one block that is positioned at the most top,
left position), the other blocks in these pairs are compared according to the same
rules. Figure 2.10 shows a trace of a mini game of “Link and Pop” that follows
the above rules.
A A C A A C C C
H G H H G H H G H H G H
C F G C F G C F G C F G
C G C G C G C G
H H H H
C F G C F G C F G C F G
G G
F G F G F F
Figure 2.10
Practice for Simulation Problems ◾ 93
Input
The input contains no more than 30 test cases. The first line of each test case con-
tains two integers n, m(1≤n, m≤30), which is the size of the board. After this line,
there will be n more lines. Each of these lines contains m strings, separated by single
spaces. Each of these strings represents one block in the initial configuration. Each
string always consists of two capital letters. The first letter is the symbol of the block.
The second letter is always one of the letters ‘U’, ‘D’, ‘L’, ‘R’, and ‘S’, which shows the
block’s moving attribute, that is, up, down, left, right, and stand still, respectively.
There are no blank lines between test cases. The input ends with a line of two 0’s: ‘0 0’.
Output
For each test case, first output the test case number. After this line, you must output
the final configuration of the board with n lines, each containing m characters. If
there is a block on the position, output the symbol of the block. If there is no block on
the position, output a period instead. Do not output blank lines between test cases.
3 3 Case 1
AD AU CL ...
HS GU HL ...
CS FD GS .F.
1 2 Case 2
BS BL ..
0 0
Hint
This is a simulation problem. The time limit for the problem is ample. Therefore,
based on Robert’s rules of selecting block pairs, the solution can be obtained. The
simulation method is as follows.
First, we try to find whether there is a pair of blocks that can be linked with
one straight line segment. Second, if there is no such pair of blocks, we try to find
whether there is a pair of blocks that can be linked by two straight line segments.
Finally, if both of the above pairs do not exist, we try to find a pair that can be
linked by three straight line segments. If more than one pair that can be linked
with the same number of straight line segments exists, the pair that contains a
94 ◾ Algorithm Design Practice for Collegiate Programming
block, which is positioned at the topmost row (or leftmost if two more blocks are
positioned in the same row), will be selected first. If this rule still cannot break
the tie (more than one pair may share one block that is positioned at the most
top, left position), the other block in these pairs are compared according to the
same rules.
Each block has a static moving attribute, which is one of ‘up’, ‘down’, ‘left’,
‘right’, and ‘stand still’. After a pair of blocks is removed, the blocks are checked
one by one to see whether they can be moved toward the direction of its moving
attribute. The blocks in the top row are checked first. Inside the same row, the
blocks on the left are checked first. If the adjacent position at the direction of the
block’s moving attribute is not occupied, the block will be moved to that position.
No block can be moved beyond the boundary of the game board. Of course, a
block with attribute ‘stand still’ will always stay at its original position. After all the
blocks are checked, which is called a turn of checking, another turn of checking is
started. This continues until no more blocks can be moved to a new position fol-
lowing the moving rules.
BFS is used to find the popped pair every time. A dequeue is used in BFS: if a
pair of blocks is linked with one straight line segment, it is added at the front of the
queue; and if a pair of blocks is linked with more than one straight line segment, it
is added at the rear of the queue. A pair of blocks is popped based on rules in the
problem description.
Figure 2.11
Practice for Simulation Problems ◾ 95
Input
Your program is to read from standard input. The input consists of four lines. Each
line describes one given rectangle by two positive integers: the lengths of the sides
of the rectangle. Each side of a rectangle is at least 1 and at most 50.
Output
Your program is to write to standard output. The output should contain one line
more than the number of solutions. The first line contains a single integer: the
minimum area of the enclosing rectangles. Each of the following lines contains one
solution described by two numbers p and q, with p≤q. These lines must be sorted in
ascending order of p, and must all be different.
1 2 40
2 3 4 10
3 4 58
4 5
Hint
1. Calculating the length and width of the enclosing rectangle.
There are six ways to fit four rectangles together. These six ways are the only
possible basic layouts, since any other layout can be obtained from a basic
layout by rotation or reflection. Therefore, the key to the problem is to cal-
culate areas of rectangles for the six ways. Suppose the four rectangles are
as follows:
The first layout is as shown in Figure 2.12. The length of the enclosing
rectangle is MAX(w1, x1, y1, z1), and the width is w2+x 2+y2+z2.
96 ◾ Algorithm Design Practice for Collegiate Programming
Width
Length
z y x w
Figure 2.12
The second layout is as shown in Figure 2.13. The length of the enclosing
rectangle is MAX(w1, x1, y1)+z1, and the width is MAX(z2, w2+x 2+y2).
The third layout is as shown in Figure 2.14. The length of the enclosing
rectangle is MAX(w1, x1+MAX(z1, y1)), and the width is w2+MAX(x 2, z2+y2).
Width
w
x Length
y
Figure 2.13
Width
y
z
w Length
Figure 2.14
Practice for Simulation Problems ◾ 97
Width Width
Length z w x Length
w x
z y
Figure 2.15
Width Width
w z w
z Length Length
x x
y y
z2 ≤ y2 z2 > y2
Figure 2.16
The fourth and the fifth layout are as shown in Figure 2.15. The com-
mon character for the two layouts is that two rectangles are stacked, and the
other two rectangles aren’t. The length of both the enclosing rectangles is
MAX(MAX(w1, x1), y1+z1), and their width is w2+x 2+MAX(y2, z2).
The sixth layout is as shown in Figure 2.16. Every two rectangles are
stacked, where z1≥w1, x1≥y1, and there are two different ways. There are two
cases for the sixth layout.
Case 1: The length of both the enclosing rectangles is MAX(w1+x1, z1+y1), and
their width is MAX(w2+z2, x 2+y2).
Case 2: The length of both the enclosing rectangles is MAX(w1+x1, z1+x1), and
their width is MAX(w2+z2, x 2+y2).
Any other case for the sixth layout that every two rectangles are stacked
can be obtained from the above two cases by rotation or reflection.
2. The minimum area of the enclosing rectangle is calculated by
enumeration.
All cases of enclosing rectangles of the above six layouts are enumerated.
For the six layouts, there are seven enclosing rectangles. And for an enclos-
ing rectangle, another enclosing rectangle will be generated if a rectangle in
the enclosing rectangle is rotated 90°. Therefore, there are 4!×7×24 enclosing
rectangles. All of these enclosing rectangles are enumerated to calculate the
minimum area of the enclosing rectangle.
Chapter 3
Practice for
Number Theory
1. Prime Numbers;
2. Indeterminate Equations and Congruence;
3. Multiplicative Functions.
99
100 ◾ Algorithm Design Practice for Collegiate Programming
Suppose u[] is a sieve. Initially all numbers in the interval are in the sieve. In
the sieve, the smallest number is found in ascending order, multiples of the num-
ber are composite numbers, and the sieve will filter out these numbers. Finally,
only prime numbers are in the sieve. The algorithm for the sieve of Eratosthenes
is as follows:
int i, j, k;
for (i=2; i<=n; i++) u[i]=true; // all numbers in the
interval are in the sieve
for (i=2; i<=n; i++) // find the smallest number in the
sieve
if (u[i]){
for (j=2; j*i<=n; j++) // the sieve filters out
multiples of i
u[j*i]=false;
}
for (i=2; i<=n; i++) if (u[i]) { //prime numbers in the
sieve are put into su[]
su[++num]=i;
}
int i, j, num=1;
memset(u, true, sizeof(u));
for (i=2; i<=n; i++){ //for each number i in the integer
interval
if (u[i]) su[num++]=i; // the smallest number in the
sieve is put into the prime list
for (j=1; j<num; j++) { //for each number in the prime
list
if (i*su[j]>n) break; //if the product of i and the
current prime is greater than n, the next integer i is
analyzed
u[i*su[j]]=false; // the sieve filters out the product
of i and the current prime
if (i% su[j]==0) break; // if the current prime is the
divisor for i, the next integer i is analyzed
}
}
Today it is still unproven whether the conjecture is right. (I have the proof, of
course, but it is too long to write it on the margin of this page.)
Anyway, your task now is to verify Goldbach’s conjecture for all even numbers
less than a million.
Input
The input file will contain one or more test cases. Each test case consists of one even
integer n with 6≤n<1000000. Input will be terminated by a value of 0 for n.
Output
For each test case, print one line of the form n=a+b, where a and b are odd primes.
Numbers and operators should be separated by exactly one blank line as shown in
the sample output below. If there is more than one pair of odd primes adding up to
n, choose the pair where the difference b−a is maximized. If there is no such pair,
print a line saying “Goldbach’s conjecture is wrong.”
8 8=3+5
20 20 = 3 + 17
42 42 = 5 + 37
0
Source: Ulm Local 1998
IDs for Online Judges: POJ 2262, ZOJ 1951, UVA 543
Analysis
First, the offline method is used to calculate the prime list su[] and prime sieve
u[] in the interval [2, 1000000]. Then, for each test case (one even integer n),
for each prime number in su[] (2×su[i]≤n), if n−su[i] is also a prime number (i.e.,
u[n−su[i]]==true), then su[i] and n−su[i] is the solution to the problem.
102 ◾ Algorithm Design Practice for Collegiate Programming
Program
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<cstdio>
using namespace std;
bool u[1111111]; //sieve
int su[1111111],num; // prime list su[], num: the length of
the su[]
void prepare(){ //Construct su[], sieve of Eratosthenes
int i,j,k;
for(i=2;i<=1000000;i++)u[i]=true;
for(i=2;i<=1000000;i++)
if(u[i]){
for(j=2;j*i<=1000000;j++)
u[j*i]=false;
}
for(i=2;i<=1000000;i++)if(u[i]){
su[++num]=i;
}
}
int main () {
prepare(); // Construct su[]
int i,j,k,n;
while(scanf("%d",&n)>0&&n) //Input test cases
{
bool ok=false;
for(i=2;i<=num;i++) //search each prime number in
the prime list in ascending order
{
if(su[i]*2>n)break; //search ends
if(u[n-su[i]]){ // the even number can be
written as the sum of two odd prime numbers
ok=true;
break;
}
}
if(!ok)puts("Goldbach's conjecture is wrong.");
//Output result
else printf("%d = %d + %d\n",n,su[i],n-su[i]);
}
return 0;
}
Practice for Number Theory ◾ 103
Input
The input contains one integer number N (N≤10000000) in every line. This is the
number you will have to express as a summation of four primes. Input is terminated
by end of file.
Output
For each line of input, there is one line of output, which contains four prime num-
bers according to the given condition. If the number cannot be expressed as a sum-
mation of four prime numbers, print “Impossible.” in a single line. There can be
multiple solutions. Any good solution will be accepted.
24 3 11 3 7
36 3 7 13 13
46 11 11 17 7
Source: Regionals 2001 Warmup Contest
ID for Online Judge: UVA 10168
Analysis
The problem is solved based on Goldbach’s conjecture. The algorithm is as follows:
First, the prime list su[] and its length num in the integer interval [2, 9999999]
are calculated. Then, for each test case N,
1. if N≤12:
N<8, N can’t be expressed as a summation of four prime numbers;
N==8, N can be expressed as a summation of four prime numbers: 2 2 2 2;
N==9, N can be expressed as a summation of four prime numbers: 2 2 2 3;
104 ◾ Algorithm Design Practice for Collegiate Programming
2. if N>12:
First, two prime numbers are subtracted from N. If N is an even number
(N%2==0), the two prime numbers, 2 and 2, are subtracted from N, that
is, N−=4; else the two prime numbers, 2 and 3, are subtracted from N,
that is, N−=5. Obviously, N is an even number greater than four. Based on
Goldbach’s conjecture, every even number greater than four can be written
as the sum of two odd prime numbers. Search the prime list su[](1≤i≤num,
2×su[i]≤n). If su[n−su[i]]==true, N can be expressed as a summation of two
prime numbers: su[i] and n−su[i].
Finally, output the result.
Program
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
using namespace std;
bool u[10000001]; //sieve
int su[5000000],num; // the prime list su[] and its length
num
void prepare(){ //construct the prime list su[] in the
interval [2, 9999999]
int i,j,num;
memset(u,true,sizeof(u)); //initially all numbers in the
sieve
for (i=2; i<=9999999; i++){ //analyze all numbers in the
interval one by one
if (u[i]) su[++num]=i; //the least number is put into
the prime list
for (j=1; j<=num; j++) { //analyze every number in the
prime list
if (i*su[j]>n) break;
u[i*su[j]]=false;
if (i% su[j]==0) break;
}
Practice for Number Theory ◾ 105
}
}
int main ()
{
prepare(); // construct the prime list su[] in the
interval [2, 9999999]
int n,i,j,k;
while(scanf("%d",&n)>0){ // Input integer n
if(n==8){puts("2 2 2 2");continue;}
if(n==9){puts("2 2 2 3");continue;}
if(n==10){puts("2 2 3 3");continue;}
if(n==11){puts("2 3 3 3");continue;}
if(n==12){puts("3 3 3 3");continue;}
if(n<8){puts("Impossible.");continue;}
if(n%2==0){printf("2 2 ");n-=4;}
else{printf("2 3 ");n-=5;}
for(i=1;i<=num;i++) // based on Goldbach's
conjecture
{
if(su[i]*2>n)break;
if(u[n-su[i]]){ //if su[i] and n−su[i] are two
prime numbers
printf("%d %d\n",su[i],n-su[i]);
break;
}
}
}
}
Input
The first line of the input file contains a single integer N (0<N≤500000) that indi-
cates the total number of inputs. Each of the next N lines contains two integers t1
and t2 (0<t1≤t2<1000000).
Output
For each line of input except the first line, produce one line of output containing a
single integer that indicates the number of digit primes between t1 and t1 (inclusive).
106 ◾ Algorithm Design Practice for Collegiate Programming
3 1
10 20 10
10 100 576
100 10000
Note: You should at least use scanf() and printf() to take input and produce
output for this problem. cin and cout are too slow for this problem to get
it within the time limit.
Source: The Diamond Wedding Contest: Elite Panel’s 1st Contest 2003
ID for Online Judge: UVA 10533
Analysis
Suppose u[] is the prime sieve for the interval [2, 1100001]; u2[] are numbers
of digit primes, where u2[i] is the number of digit primes in the interval [2, i],
2≤i≤1100001.
First, the offline method is used to calculate u2[]. The prime sieve u[] for the
interval [2, 1100001] is calculated. For each number i in [2, 1100001], if i is a digit
prime, that is, u[i]&&u[the sum of digits for i]==true, then u2[i]=1. Then calculate
u2[i]: u2[i]+=u2[i−1] (2≤i≤1100001). Finally, based on u2[], calculate the number
of digit primes within a certain range [i,j]:u2[j]−u2[i−1].
Program
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
using namespace std;
bool u[1100001]; // prime sieve
int u2[1100001]; // numbers of digit primes
Practice for Number Theory ◾ 107
Input
The input is a sequence of lines each of which contains a single positive integer.
Each positive integer is greater than 1 and less than or equal to the 100000th prime
number, which is 1299709. The end of the input is indicated by a line containing
a single zero.
Output
The output should be composed of lines each of which contains a single non-
negative integer. It is the length of the prime gap that contains the corresponding
positive integer in the input if it is a composite number, or 0 otherwise. No other
characters should occur in the output.
10 4
11 0
27 6
2 0
492170 114
0
Source: ACM Japan 2007
IDs for Online Judges: POJ 3518, UVA 3883
Analysis
Suppose ans[k] is the length of the prime gap that contains k. If k is a prime
number, then ans[k]=0. For any two successive prime numbers p1 and p2,
ans[p1+1]=ans[p1+2]=…=ans[p2−1]=p2−p1. The algorithm is as follows:
1. Calculating ans[]:
Calculating the prime sieve u[] in the interval [2, 1299709];
Enumerate every number i in the interval [2, 1299709]. If i is a prime num-
ber (u[i]==true), then ans[i]=0. If i is a composite number, then find the
next prime number j(u[i]==u[i+1]==…==u[j−1]==false, u[j]==true),
ans[i]=ans[i+1]=ans[j−1]=j−i+1, and i=j.
2. For each test case k, output ans[k].
Practice for Number Theory ◾ 109
Program
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
using namespace std;
const int maxn=1299710;
bool u[maxn]; //prime sieve
int ans[maxn]; // the length of the prime gap
void prepare(){
int i,j,k;
for(i=2;i<maxn;i++)u[i]=1; //Calculate prime sieve u[]
in [2, 1299710]
for(i=2;i<maxn;i++)
if(u[i]) // i is a prime number
for(j=2;j*i<maxn;j++) u[i*j]=0;
for(i=2;i<maxn;i++) // Enumerate every number i in the
interval
if(!u[i]){ // i is a composite number
j=i;
while(j<maxn&&!u[j]) j++;
j--;
for(k=i;k<=j;k++) ans[k]=j-i+2; //calculate the
length of the prime gap
i=j;
}else ans[i]=0; // i is a prime number
}
int main ()
{
int i,j,k;
prepare();
while(scanf("%d",&k)>0&&k>0){
printf("%d\n",ans[k]);
}
}
of large numbers. There are two optimization methods for trial division: “Sieve +
Trial Division”, and the Miller–Rabin primality test.
“Sieve + Trial Division” is as follows. First, the prime sieve u[] and prime list
su[] for the interval [2, n ] are calculated. The length of su[] is num. x is a prime
number if and only if x is a prime number in the interval [2, n ] (u[x]==1), or x is
not a multiple of any integer between 2 and n (x%su[0]≠0, …, x%su[num−1]≠0).
The time complexity is O( n ).
Input
Input consists of a series of test cases. The first line consists of an integer t (1<t<21),
the number of test cases. Each test case consists of one line. The line begins with
the integer n, 0<n<10001, followed by n non-negative numbers less than 10000
comprising the sequence. You should note that 80 percent of the test cases will have
at most 1000 numbers in the sequence.
Output
For each sequence, print the “Shortest primed subsequence is length x:”, where x
is the length of the shortest primed subsequence, followed by the shortest primed
subsequence, separated by spaces. If there are multiple such sequences, print the one
that occurs first. If there are no such sequences, print “This sequence is anti-primed.”.
Analysis
There are n non-negative numbers less than 10000 comprising the sequence,
0<n<10001.
First, the prime sieve u[] and prime list su[] for the interval [2, 10010] are cal-
culated. The length of su[] is num. If x is a prime number in the interval [2, 10010]
(u[x]==1), or x isn’t a multiple of any integer in su[](x%su[0]≠0,…,x%su[num−1]≠0),
then x is a prime number.
Then, based on the above, the shortest primed subsequence is calculated.
Input a sequence whose length is n, and calculate the sum of the first i integers
s[i](1≤i≤n, s[i]+=s[i−1]):
Dynamic Programming is used to calculate the shortest primed subsequence:
Program
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
bool u[10010]; // prime sieve
int su[10010],num; //prime list and its length
void prepare(){ //construct the prime list su[] in the
interval [2, 10010]
int i,j,num;
memset(u,true,sizeof(u));
for(i=2;i<=10010;i++){
if(u[i]) su[++num]=i;
for(j=1;j<=num;j++) {
if (i*su[j]>n)break;
u[i*su[j]]=false;
if (i% su[j]==0) break;
}
112 ◾ Algorithm Design Practice for Collegiate Programming
}
}
bool pri(int x){ // If x is a prime number in the interval
[2, 10010] or (u[x]==1), or x isn't a multiple of any integer
in su[], return true; else return false
int i,j,k;
if(x<10010)return u[x];
for(i=1;i<=num;i++)
if(x%su[i]==0)return false;
return true;
}
int n,s[10010]; //the sum of the first i integers is s[i]
int main()
{
int i,j,k;
prepare(); // calculate the prime list su[]
int te;
scanf("%d",&te); //number of test cases
while(te--){
scanf("%d",&n); //the length of sequence
s[0]=0;
for(i=1;i<=n;i++) //calculate s[]
{
scanf("%d",&s[i]);
s[i]+=s[i-1];
}
bool ok=false;
for(i=2;i<=n;i++){ //enumerate lengths of
subsequence
for(j=1;j+i-1<=n;j++) //enumerate front pointers
{
k=s[i+j-1]-s[j-1]; //calculate the sum of
subsequences
if(pri(k)){ // if k is a prime number
ok=true;
printf("Shortest primed subsequence is length
%d:",i);
for(k=1;k<=i;k++)printf("
%d",s[j+k-1]-s[j+k-2]);
puts("");
break;
}
}
if(ok)break;
}
if(!ok)puts("This sequence is anti-primed.");
// there are no primed sequences
}
// system("pause");
}
Practice for Number Theory ◾ 113
b a=0 a b=0
GCD( a , b ) = = .
GCD (b mod a, a ) Otherwise GCD(b , a mod b ) Otherwise
Proof. The key to the proof is GCD(a, b) and GCD(b mod a,a) can be divided
by each other. b mod a can be represented as an integer linear combination of
b
a and b:b mod a = b − × a. Because a and b can be divided by GCD(a, b),
a
b
b − × a can also be divided by GCD(a, b). Therefore GCD(b mod a,a) can be
a
divided by GCD(a, b). Similarly, GCD(a, b) can also be divided by GCD(b mod
a,a). Therefore, GCD(a, b)=± GCD(b mod a,a).
Similarly, GCD(a, b) and GCD(b,a mod b) can be divided by each other.
For example, GCD(319, 377)=GCD(58, 319)=GCD(29, 58)=GCD(0, 29)=29.
Theorem 3.2.1.1 (Bezout’s Theorem). If a and b are integers, then there are
integers x and y, such that ax+by=GCD(a, b).
Corollary 3.2.1.1 Integers a and b are relatively prime integers if and only if
there are integers x and y such that ax+by=1.
Given an indeterminate equation ax+by=GCD(a, b), where a and b are integers,
the Extended Euclidean algorithm can be used to calculate integer roots (x, y) of
the equation.
Suppose ax1+by1=GCD(a, b), bx 2+(a mod b)y2=GCD(b,a mod b). Because
GCD(a, b)=GCD(b,a mod b), ax1+by1=bx 2+(a mod b)y2. Because a mod
a a a
b = a − × b, ax1 + by1 = bx 2 + a − × b y 2 = ay 2 + b x 2 − y 2 . Therefore
b b b
a
x1=y2 , and y1 = x 2 − × y 2 . Therefore (x1, y1) is based on (x 2 , y2). Repeat the
b
114 ◾ Algorithm Design Practice for Collegiate Programming
recursive process to calculate (x3, y3), (x4, y4), ......., until b==0. At that time x=1,
y=0. Therefore, the Extended Euclidean algorithm is as follows:
Method 1: Enumeration
Enumerate each pair of (x, y) and find integer roots. That is, the indeterminate
equation should be calculated (xr −xl+1)×(yr −yl+1) times.
Input
Input contains integer numbers a, b, c, x1, x2, y1, y2 delimited by spaces and line
breaks. All numbers are not greater than 108 by absolute value.
Practice for Number Theory ◾ 115
Output
Write the answer to the output.
1 1 -3 4
0 4
0 4
ID for Online Judge: SGU 106
Analysis
First, for the equation ax+by+c=0, several special cases for the problem are
considered.
1. If a==0, b==0, and c≠0, then there is no solution. If a==0, b==0, and c==0,
then the number of integer roots of an equation is ((x2−x1+1)×(y2−y1+1)).
2. If a==0, and b≠0, then by=c. If c isn’t a multiple of b, or c/b isn’t an element
in [y1,y2], then there is no solution; else for each number x in [x1,x2], (x,c/b)
is an integer root.
3. If b==0, and a≠0, it is the same as 2.
4. If c isn’t a multiple of GCD(a, b), there is no solution.
There is a problem in division: how to transfer reals into integers? For the upper
bound, floor( ) is used for round down; and for the lower bound, ceil( ) is used for
round up. For example, if 2.5≤k≤5.5, k can be 3, 4, and 5; and if −5.5≤k≤−2.5, k
can be −3, −4, and −5.
116 ◾ Algorithm Design Practice for Collegiate Programming
Program
#include<cstdio>
#include<cmath>
long long a,b,c,x1,x2,yy1,y2,x0,yy0; // an equation
ax+by+c=0, the interval for x is[x1, x2], the interval for y
is [yy1, y2], initial solution (x0, yy0)
inline long long cmin(const long long &x,const long long &y)
{return x<y?x:y;}
inline long long cmax(const long long &x,const long long &y)
{return x>y?x:y;}
long long gcd(long long a,long long b) //GCD(a, b)
{
if (b==0) return a;
return gcd(b, a % b);
}
void exgcd(long long a,long long b) // Extended Euclidean
algorithm is used to calculate the initial solution (x0, yy0)
for ax+by=1
{
if (b==0){x0=1;yy0=0;return;}
exgcd(b, a%b);
long long t=x0; x0=yy0; yy0=t-a/b*yy0;
return;
}
int main()
{
scanf("%I64d%I64d%I64d%I64d%I64d%I64d%I64d",&a,&b,&c,&x1,&
x2,&yy1,&y2);
// indeterminate equation: ax+by+c=0, x1≤x≤x2, yy1≤y≤y2
c=-c; // ax+by+c=0 is changed to ax+by=−c
if (c<0) {a=-a; b=-b; c=-c;}
if (a<0) {a=-a; long long t=x1; x1=-x2; x2=-t;} //adjust
intervals for x and y
if (b<0) {b=-b; long long t=yy1; yy1=-y2; y2=-t;}
if (a==0 && b==0) // special case: a==0 && b==0
{
if (c==0)
{
printf("%I64d",(x2-x1+1)*(y2-yy1+1));
return 0;
}
printf("0");return 0;
}
Practice for Number Theory ◾ 117
1. Congruence Equation
A congruence of the form ax≡b(mod m), where a and b are integers, m is a
positive integer, and x is an unknown integer, is called a linear congruence in
one variable. The method for calculating x is as follows:
Step 1: The Euclidean algorithm and Extended Euclidean algorithm are used
to calculate d=GCD(a, m) and (x', y') where d=ax'+my', and x' is a solu-
tion to ax'≡d(mod m).
Step 2: If b mod d≠0, there is no solution for ax≡b(mod m); else there
are d incongruent solutions modulo m, where the first solution
b
is x0 = x '× mod m , and the other d−1 solutions are
d
m
xi = x0 +i × mod m , 1≤i≤d−1.
d
In order to prove the correctness of the two steps, the following three theorems
are used.
m
1. Theorem 3.2.2.1 If ac≡bc(mod m) and GCD(c, m)=d, then a ≡ b mod .
d
2. Theorem 3.2.2.2 If d≠0 and ad≡bd(mod md), then a≡b(mod m).
3. Theorem 3.2.2.3 If GCD(a, m)=1, there are solutions for ax+b≡0(mod m).
Step 1: Suppose d=GCD(a, m). If b mod d=0, solutions to
a x ≡ b mod m and ax≡b(mod m) are the same.
d d d
m m m
Because x, x + , x + 2× , …… , and x +( d −1)× are all in [x],
d d d
m m
0 ≤ x +i × < m, 1≤i≤d−1; and they are incongruent modulo m; x, x + ,
d d
m m
x + 2× , …… , and x +( d −1)× are d incongruent solutions modulo m
d d
to ax≡b(mod m).
Step 2: For ax ≡b(mod m), there are exactly d incongruent solutions modulo
m m
m: x modulo m, x + modulo m, x + 2× modulo m, …, and
d d
m
x +(d −1)× d modulo m.
m
Proof. Suppose x +t × is a solution to ax≡b(mod m). Because t≡i(mod
d
m m
d), i∈{0, 1, 2, …, d−1}, based on Theorem 3.2.2.2, t × ≡ i × ( mod m ) ,
d d
m m m m
that is, x +t × is one of x, x + , x + 2× ,…, x +( d −1)× .
d d d d
m
Therefore, there are d incongruent solutions modulo m, x + modulo m,
d
m m
x + 2× d modulo m, …, and x +(d −1)× d modulo m.
Based on the above discussions, Theorem 3.2.2.4 holds.
Theorem 3.2.2.4 Given a positive integer m and two integers a and b,
suppose GCD(a, m)=d. If b mod d≠0, then ax≡b(mod m) has no solutions.
And if b mod d=0, then ax≡b(mod m) has exactly d incongruent solutions
modulo m.
For example, given a congruence equation 9x≡8(mod 3), GCD(9,3)=3.
Because 8 mod 3≠0, there is no solution for 9x≡8(mod 3).
Given a congruence equation 9x≡12(mod 15), GCD(9,15)=3. Because
12 mod 3=0, 9x≡12(mod 15) has exactly three incongruent solutions
modulo 15. The Extended Euclidean algorithm is used to calculate (x', y')
where 3=9x'+15y', x'=2, y'=−1, 2 is a solution to 9x'≡3(mod 15). Therefore,
x0 =8 mod 15=8, x1=(x0+5) mod 15=13, and x 2=(x0+10) mod 15=18
mod 15=3.
120 ◾ Algorithm Design Practice for Collegiate Programming
2. Congruence Equations
Definition 3.2.2.1. Given an integer a with GCD(a, m)=1, an integer solu-
tion x to ax≡1(mod m) is called an inverse of a modulo m.
By Theorem 3.2.2.4, a Congruence Equation ax≡1(mod m) has solutions
if and only if GCD(a, m)=1 and all solutions are congruent modulo m.
For example, solutions to 6x≡1(mod 41) satisfy x≡7(mod 41). Therefore,
7 is an inverse of 6 modulo 41, and all integers congruent to 7 modulo 41 are
inverses of 6 modulo 41. Because 7×6≡1(mod 41), 6 and all integers congru-
ent to 6 modulo 41 are inverses of 7 modulo 41.
Theorem 3.2.2.5 (The Chinese Remainder Theorem). Let n1, n2, …, nk
be pairwise relatively prime positive integers. Then the system of congruences
a≡a1(mod n1)
a≡a2(mod n2)
.........
.........
.........
a≡ak(mod nk)
n
On the other hand, because GCD(ni,nj)=1 and mi = , ni|mj, i≠j.
Therefore ni
j ≡ 0( mod ni )
ajm jm' i,j= 1, 2, ..., k (2)
For example, a≡2(mod 3), a≡4(mod 7), and a≡5(mod 8). 3, 7, and 8 are
pairwise relatively prime positive integers. m1=n2×n3 =56, m2=n1×n3 =24, and
m3 =n1×n2=21. n=3×7×8=168. 56×2=112≡1(mod 3), 24×5=120≡1(mod 7),
and 21×5=105≡1(mod 8). 2×112+4×120+5×105=1229. a=1229 mod n=53.
Steps for calculating the system of congruences are as follows:
n
Step 1: Calculate mi, i=1, 2, …, k. Suppose n=n1×n2×...×nk; m1 = = n2 ×
n1
n n
n3 ×…× nk ; m2 = = n1 × n3 × n4 ×…× nk ; ……; mi = = n1 ×…× ni −1 × ni +1 …× nk ;
n2 ni
n
……; mk = = n1 ×...× nk −2 × nk −1.
nk
Step 2: Calculate an inverse mi-1 of mi modulo ni, that is, mi×mi-1≡1(mod ni) ,
i=1, 2, …, k. There are two methods for calculating mi-1:
1. Congruence Equation
Because mi and ni are relatively prime integers, that is, GCD(mi, ni)=1,
by m1×m1-1≡1(mod n1); …; mi ×mi-1≡1(mod ni); …; mk ×mk-1≡1(mod nk),
m1-1, ..., m i-1, ..., mk-1 are calculated. There is exactly one solution mi-1 to
mi ×mi-1≡1(mod ni), 1≤i≤k.
2. Extended Euclidean algorithm
The Extended Euclidean algorithm is used to calculate x and y for
GCD(ni, mi)=ni×x+mi ×y=1, and y is mi-1 (1≤i≤k).
Step 3: Calculate ci=mi×(mi-1mod ni), 1≤i≤k.
Step 4: Calculate a=(a1×c1+…+ai×ci+…+ak ×ck)mod n.
3.2.2.1 C Looooops
A compiler mystery: We are given a C-language style for a loop of type
for (variable=A; variable!=B; variable+=C)
statement;
that is, a loop which starts by setting a variable to value A, and while variable is
not equal to B, repeats the statement, followed by increasing the variable by C. We
want to know how many times does the statement get executed for particular values
of A, B, and C, assuming that all arithmetic is calculated in a k-bit unsigned integer
type (with values 0≤x<2k) modulo 2k.
Input
The input consists of several instances. Each instance is described by a single line
with four integers A, B, C, k separated by a single space. The integer k (1≤k≤32) is
the number of bits of the control variable of the loop and A, B, C (0≤A,B,C <2k) are
the parameters of the loop.
The input is finished by a line containing four zeros.
122 ◾ Algorithm Design Practice for Collegiate Programming
Output
The output consists of several lines corresponding to the instances on the input. The
i-th line contains either the number of executions of the statement in the i-th instance
(a single integer number) or the word FOREVER if the loop does not terminate.
3 3 2 16 0
3 7 2 16 2
7 3 2 16 32766
3 4 2 16 FOREVER
0 0 0 0
Source: CTU Open 2004
IDs for Online Judges: POJ 2115, ZOJ 2305
Analysis
Based on the problem description, a loop which starts by setting variable to value A
and while variable is not equal to B, repeats the statement, followed by increasing the
variable by C. All arithmetic is calculated in a k-bit unsigned integer type (with values
0≤x<2k) modulo 2k. Therefore D=(B−A)mod 2k is equivalent to x×C≡D(mod 2k ).
Obviously, the number of the loop is 0 if and only if D=(B−A)mod 2k =0.
There are solutions to x×C≡D(mod2k ) if and only if D mod GCD(C,2k )==0. The
Extended Euclidean algorithm is used to calculate the minimal non-negative inte-
ger solution x to x×C+y×2k =GCD(C,2k ). That is, x is a solution to Cx≡GCD(C,2k )
(mod 2k). If ((D mod GCD(C, 2k))≠0), there is no solution to x×C≡D(mod 2k), and the
program enters an endless loop; else (x×D)mod 2k is the solution to x×C≡D(mod 2k);
that is, the number of executions of the statement.
Program
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#define ll long long
#include<iostream>
using namespace std;
Practice for Number Theory ◾ 123
3.2.2.2 Biorhythms
Some people believe that there are three cycles in a person’s life that start the day he
or she is born. These three cycles are the physical, emotional, and intellectual cycles,
and they have periods of lengths 23, 28, and 33 days, respectively. There is one peak
124 ◾ Algorithm Design Practice for Collegiate Programming
in each period of a cycle. At the peak of a cycle, a person performs at his or her best
in the corresponding field (physical, emotional, or mental). For example, if it is the
mental curve, thought processes will be sharper and concentration will be easier.
Since the three cycles have different periods, the peaks of the three cycles
generally occur at different times. We would like to determine when a triple peak
occurs (the peaks of all three cycles occur in the same day) for any person. For each
cycle, you will be given the number of days from the beginning of the current year
at which one of its peaks (not necessarily the first) occurs. You will also be given a
date expressed as the number of days from the beginning of the current year. Your
task is to determine the number of days from the given date to the next triple peak.
The given date is not counted. For example, if the given date is 10 and the next triple
peak occurs on day 12, the answer is 2, not 3. If a triple peak occurs on the given
date, you should give the number of days to the next occurrence of a triple peak.
Input
You will be given a number of cases. The input for each case consists of one line of
four integers p, e, i, and d. The values p, e, and i are the number of days from the
beginning of the current year at which the physical, emotional, and intellectual
cycles peak, respectively. The value d is the given date and may be smaller than any
of p, e, or i. All values are non-negative and at most 365, and you may assume that
a triple peak will occur within 21252 days of the given date. The end of input is
indicated by a line in which p=e=i=d=−1.
Output
For each test case, print the case number followed by a message indicating the
number of days to the next triple peak, in the following form:
Analysis
These three cycles are the physical, emotional, and intellectual cycles, and they
have periods of lengths 23, 28, and 33 days, respectively. These three integers are
pairwise relatively prime positive integers. Suppose x is the number of days to the
next triple peak. The system of congruences is as follows:
x ≡ p ( mod 23)
x ≡ e ( mod 28)
x ≡ i ( mod 33)
Based on The Chinese Remainder Theorem, x is the only solution in the inter-
val [1, 23×28×33=21253]. Suppose ai and ni are the number of days to the next
triple peak and the period of length respectively, that is, a1=p, a 2=e, a3 =i, n1=23,
n2=28, and n3 =33. The system of congruences is as follows:
x ≡ ai ( mod ni ) , (1≤i ≤ 3).
3
Program
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<string>
using namespace std;
typedef long long ll;
ll power(ll a,ll p,ll mo){ //Calculate ap%(mo)
ll ans=1;
for(;p;p>>=1){
if(p&1){
ans*=a;
126 ◾ Algorithm Design Practice for Collegiate Programming
if(mo>0)ans%=mo;
}
a*=a;
if(mo>0)a%=mo;
}
return ans;
}
ll exgcd(ll a,ll b,ll &x,ll &y){ // Extended Euclidean
algorithm: calculate x for GCD(a, b)=ax+by
if(b==0){
x=1;y=0;return a;
}
ll t=exgcd(b,a%b,y,x);
y-=a/b*x;
return t;
}
ll niyuan(ll a,ll p){ //calculate a-1%p
ll x,y;
exgcd(a,p,x,y); //calculate x for ax≡GCD(a, p)(%p)
return (x%p+p)%p;
}
int main(){
int a,b,c,d,i,j,k,u,v,te=0;
while(1){
scanf("%d%d%d%d",&a,&b,&c,&d); //test case
if(a==b&&b==c&&c==d&&a==-1)break; //end case
3
//calculate an =
i=1
∑
(mi * ai *(mi mod ni))- d % (23* 28* 33) , that
-1
is, the number of days to the next triple peak
ll an=0;
an=28*33*a*niyuan(28*33,23)+23*33*b*niyuan(23*33,28)+23*
28*c*niyuan(28*23,33);
an-=d;
an%=(28*33*23);
if(an<=0)an+=28*33*23;
printf("Case %d: the next triple peak occurs in %d
days.\n",++te,(int)an);
}
}
And {3, 9, 21, 27} is also a reduced residue system modulo 10. Therefore, the
least positive residue system for {3, 9, 21, 27} is the set {1, 3, 7, 9} in some order.
3×9×21×27≡1×3×7×9 (mod 10). 1×3×7×9(mod 10)=9. n=10, a=3, and ϕ(10)=4.
34 =3ϕ(10) ≡1(mod 10).
Corollary 3.3.1. If n and a are coprime positive integers, then a ϕ(n)+1≡a(mod n).
Theorem 3.3.6 (Fermat’s Little Theorem). If p is a prime number, a is a posi-
tive integer, and GCD(a, p)=1, then a p-1 ≡1(mod p). And if p is a prime and a is an
positive integer, a p ≡a(mod p).
For example, if a=3 and p=5, 34 ≡1(mod 5). And if a=6 and p=3, 63 ≡6(mod 3).
Definition 3.3.4 (Order of a Modulo n). Suppose a and n are relatively prime
integers, where a≠0 and n>0. The least positive integer x such that ax ≡1(mod n) is
the order of a modulo n, and is denoted as ordna.
For example, suppose a=3 and n=5. 34 =81≡1(mod 5). Therefore ord53=4.
Definition 3.3.5 (Primitive Root). Suppose a and n are relatively prime inte-
gers, where n>0. If ordna=ϕ(n), then a is a primitive root modulo n, and n has a
primitive root.
For example, ord53=ϕ(5)=4. 3 is a primitive root of modulo 5, and 5 has a
primitive root.
Theorem 3.3.7 If a positive integer n has a primitive root, then it has ϕ(ϕ(n))
different incongruent primitive roots.
3.3.1.1 Relatives
Given n, a positive integer, how many positive integers less than n are relatively
prime to n? Two integers a and b are relatively prime if there are no integers x>1,
y>0, z>0 such that a=xy and b=xz.
Input
There are several test cases. For each test case, standard input contains a line with
n≤1,000,000,000. A line containing 0 follows the last case.
Output
For each test case there should be a single line of output answering the question
posed above.
7 6
12 4
0
Source: Waterloo local 2002.07.01
IDs for Online Judges: POJ 2407, ZOJ 1906, UVA 10299
Practice for Number Theory ◾ 129
Analysis
Given a positive integer n, the number of positive integers less than n are relatively
prime to n is the Euler phi-function ϕ(n). n can be written as a product of primes:
n = p1k1 × p2k2 ×...× prkr . Therefore, ϕ(n )=ϕ( p1k1 )×ϕ( p2k2 )×...×ϕ( prkr ), where
ki −1
ϕ( pi )= ( pi −1)× pi , 1≤i≤r.
ki
Program
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
using namespace std;
typedef long long ll;
bool u[50000]; //Prime sieve
ll su[50000],num; //Prime list whose length is num
ll gcd(ll a,ll b){ //GCD(a, b)
if(b==0)return a;
return gcd(b,a%b);
}
void prepare(){ //Construct prime list su[] in [2, 50000]
ll i,j,k;
for(i=2;i<50000;i++)u[i]=1;
for(i=2;i<50000;i++)
if(u[i])
for(j=2;j*i<50000;j++)
u[i*j]=0;
for(i=2;i<50000;i++)
if(u[i])
su[++num]=i;
}
ll phi(ll x) // Euler phi-function φ(x)
{
ll ans=1;
int i,j,k;
for(i=1;i<=num;i++)
if(x%su[i]==0){ //the number of prime factor su[i] is j
j=0;
130 ◾ Algorithm Design Practice for Collegiate Programming
while(x%su[i]==0){++j;x/=su[i];}
for(k=1;k<j;k++)ans=ans*su[i]%1000000007ll;
ans=ans*(su[i]-1)%1000000007ll;
if(x==1)break;
}
if(x>1)ans=ans*(x-1)%1000000007ll;
return ans; // return φ(x)
}
int main(){
prepare(); // Construct prime list su[] in [2, 50000]
int n,i,j,k;
ll ans=1;
while(scanf("%d",&n)==1&&n>0){
//Input test cases until 0
ans=phi(n); //calculate and output φ(n)
printf("%d\n",(int)ans);
}
}
Input
Each line of the input contains an odd prime numbers p. Input is terminated by the
end-of-file separator.
Output
For each p, print a single number that gives the number of primitive roots in a
single line.
23 10
31 8
79 24
Source: Jiayi@pku
ID for Online Judge: POJ 1284
Practice for Number Theory ◾ 131
Analysis
Based on the problem description, an integer x, 0<x<p, is a primitive root modulo
odd prime p if and only if the set {(xi mod p)|1≤i≤p−1} is equal to {1, ..., p−1}. If
p has a primitive root, then it has ϕ(ϕ(p)) different primitive roots. Because p is a
prime, ϕ(ϕ(p))=ϕ(p−1).
Program
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
using namespace std;
typedef long long ll;
bool u[50000]; //prime sieve
ll su[50000],num; //prime list whose length is num
void prepare(){ //Calculate prime list su[]
ll i,j,k;
for(i=2;i<50000;i++)u[i]=1;
for(i=2;i<50000;i++)
if(u[i])
for(j=2;j*i<50000;j++) u[i*j]=0;
for(i=2;i<50000;i++)
if(u[i]) su[++num]=i;
}
ll phi(ll x) // Euler phi-function φ(x)
{
ll ans=1;
int i,j,k;
for(i=1;i<=num;i++) //Enumerate each prime
if(x%su[i]==0){ //if x has prime factor su[i], then
φ(s[i])=su[i]j-1*(su[i]-1), and adjust φ(x)
j=0;
while(x%su[i]==0){++j;x/=su[i];}
for(k=1;k<j;k++)ans=ans*su[i]%1000000007ll;
ans=ans*(su[i]-1)%1000000007ll;
if(x==1)break;
}
132 ◾ Algorithm Design Practice for Collegiate Programming
if(x>1)ans=ans*(x-1)%1000000007ll; // φ(x)
return ans;
}
int main(){
prepare(); //construct prime list su[]
int n,i,j,k;
ll ans=1;
while(scanf("%d",&n)==1){ //input test case n until EOF
ans=phi(n-1); //the number of primitive roots for n
printf("%d\n",(int)ans);
}
}
3.4 Problems
3.4.1 Prime Frequency
Given a string containing only alpha-numerals (0-9, A-Z and a-z), you have to
count the frequency (the number of times the character is present) of all the charac-
ters and report only those characters whose frequency is a prime number. A prime
number is a number which is divisible by exactly two different integers.
Some examples of prime numbers are 2, 3, 5, 7, 11, etc.
Input
The first line of the input is an integer T (0<T< 201) that indicates how many sets of
inputs are there. Each of the next T lines contains a single set of input.
The input of each test set is a string consisting of alpha-numerals only. The
length of this string is positive and less than 2001.
Output
For each set of input, produce one line of output. This line contains the serial of
output followed by the characters whose frequency in the input string is a prime
number. These characters are to be sorted in lexicographically ascending order.
Here “lexicographically ascending” means ascending in terms of the ASCII values.
Look at the output for sample input for details. If none of the character frequency
is a prime number, you should print “empty” (without the quotes) instead.
3 Case 1: C
ABCC Case 2: AD
AABBBBDDDDD Case 3: empty
ABCDFFFF
Source: Bangladesh National Computer Programming Contest
ID for Online Judge: UVA 10789
Practice for Number Theory ◾ 133
Hint
First, the offline method is used to calculate the prime sieve u[] in [2, 2200]. Second,
for each test case (a string), every character’s frequency p[] is calculated. Third, char-
acters whose frequency is a prime number are sorted in lexicographically ascending
order. If none of the character frequency is a prime number, “empty” is output.
Input
The input will contain less than 10001 lines of input. Each line contains an inte-
gers S (1≤S≤100000), which is the serial number of a twin prime pair. Input file is
terminated by end of file.
Output
For each line of input, you will have to produce one line of output which contains
the S-th twin prime pair. The pair is printed in the form (p1,<space>p2). Here
<space> means the space character (ASCII 32). You can safely assume that the
primes in the 100000-th twin prime pair are less than 20000000.
1 (3, 5)
2 (5, 7)
3 (11, 13)
4 (17, 19)
Source: Regionals Warmup Contest 2002, Venue: Southeast University, Dhaka,
Bangladesh
ID for Online Judge: UVA 10394
Hint
Suppose the sequence for twin primes is ans[], where ans[i] is the least prime for the
i-th twin primes, 1≤i≤num.
134 ◾ Algorithm Design Practice for Collegiate Programming
First, the sieve method is used to calculate the prime sieve u[] for the interval
[2, 20000000];
Second, each integer i is enumerated. If i and i+2 is a twin prime (u[i]&&u[i+2]),
then i is added into the sequence for twin primes (ans[++num]=i);
Finally, for each test case s, the twin prime (ans[s], ans[s]+2) is output.
Input
The first line of the input contains an integer, M, indicating the number of test
cases. For each test case, there is a line with a number N, 100≤N≤10000.
Output
For each test case, the output should consist of one line showing the prime number
that verifies the condition above.
5 2203
4399 311
614 4111
8201 53
101 3527
7048
Source: III Local Contest in Murcia 2005
ID for Online Judge: UVA 10852
Hint
Because n−p×x is maximum (x is a prime number, p is an integer, p×x≤n<(p+1)×x),
x is such a prime number that x%n is maximal for all prime numbers less than n.
The algorithm is as follows:
First, the prime list su[] for the interval [2, 11111] is calculated, where its length
is num. Then, for each test case n, all prime numbers less than n are enumerated,
Practice for Number Theory ◾ 135
tmp = max {n% su[i ] su[i ] < n}. The prime number that verifies the condition above
1≤ i ≤ num
Input
The input consists of a set of words. Each word is in a line by itself and has L letters,
where 1≤L≤20. The input is terminated by end of file (EOF).
Output
For each word you should print: It is a prime word., if the sum of the letters of the
word is a prime number; otherwise you should print: It is not a prime word.
Hint
First, the offline method is used to calculate a prime list u[] in the interval [2, 1010].
Second, a test case (a word whose length is n) is input, and the sum of letters in
n
the word is X = ∑ (s[i ] − ' a '+ 1 s[i ] ∈{' a '..' z '}), s[i ] − ' A '+ 27 s[i ] ∈{' A '..' Z '}.
i =1
If X is a prime number in [2, 1010], the word is a prime word; else it isn’t a prime
word.
136 ◾ Algorithm Design Practice for Collegiate Programming
Input
The input is a sequence of datasets followed by a line containing two zeros separated
by a space. A dataset is a line containing two positive integers n and k separated by
a space. You may assume that n≤1120 and k≤14.
Output
The output should be composed of lines, each corresponding to an input dataset. An
output line should contain one non-negative integer indicating the number of ways for
n and k specified in the corresponding dataset. You may assume that it is less than 231.
24 3 2
24 2 3
2 1 1
1 1 0
4 2 0
18 3 2
17 1 1
17 3 0
17 4 1
100 5 55
1000 10 200102899
1120 14 2079324314
0 0
Source: ACM Japan 2006
IDs for Online Judges: POJ 3132, ZOJ 2822, UVA 3619
Practice for Number Theory ◾ 137
Hint
Suppose su[] is the prime list in the interval [2, 1200]; f [i][j] is the number of ways
to express j as a sum of i different primes, 1≤i≤14, and su[i]≤j≤1199. Obviously,
f [0][0]=1.
First, su[] is calculated. Its length is num.
Then, for a test case (two positive integers n and k), Dynamic Programming is
used to compute the number of ways to express n as a sum of k different primes.
Input
The input will consist of several test cases. Each test case will be given as a non-
negative integer a and a positive integer p as specified above, on a line. Both a and
p will fit into a 32-bit signed integer. The last line will contain “−1 −1” and should
not be processed.
Output
For each test case, output “Yes” if the cake can be fairly divided and “No”
otherwise.
138 ◾ Algorithm Design Practice for Collegiate Programming
1 3 Yes
1024 17 Yes
2 101 No
0 1 Yes
-1 -1
Source: 2005 ACM ICPC World Finals Warmup 2
ID for Online Judge: UVA 10831
the job, only the day of the week. Nevertheless, even this information might be
helpful in certain cases: for example, if a widgeteer started working on a Tuesday,
built a Type 41 widget, and was fired on a Friday, then we know that it takes
four days to build a Type 41 widget. Your task is to figure out from these records
(if possible) the number of days that are required to build the different types of
widgets.
Input
The input contains several blocks of test cases. Each case begins with a line
containing two integers: the number 1≤n≤300 of the different types, and the
number 1≤m≤300 of the records. This line is followed by a description of the m
records. Each record is described by two lines. The first line contains the total
number 1≤k≤10000 of widgets built by this widgeteer, followed by the day of
the week when he or she started working and the day of the week he or she was
fired. The days of the week are given by the strings ‘MON’, ‘TUE’, ‘WED’,
‘THU’, ‘FRI’, ‘SAT’, and ‘SUN’. The second line contains k integers separated
by spaces. These numbers are between 1 and n, and they describe the different
types of widgets that the widgeteer built. For example, the following two lines
mean that the widgeteer started working on a Wednesday, built a Type 13 widget,
a Type 18 widget, a Type 1 widget, again a Type 13 widget, and was fired on a
Sunday.
4 WED SUN
13 18 1 13
Note that the widgeteers work seven days a week, and they were working on
every day between their first and last day at the factory (if you like weekends and
holidays, then do not become a widgeteer!).
The input is terminated by a test case with n=m=0.
Hint: Huge input file, ‘scanf’ recommended to avoid TLE.
Output
For each test case, you have to output a single line containing n integers separated
by spaces: the number of days required to build the different types of widgets.
There should be no space before the first number or after the last number, and
there should be exactly one space between two numbers. If there is more than one
possible solution for the problem, then write “Multiple solutions.” (without the
quotes). If you are sure that there is no solution consistent with the input, then
write “Inconsistent data.” (without the quotes).
140 ◾ Algorithm Design Practice for Collegiate Programming
2 3 83
2 MON THU
1 2 Inconsistent
data.
3 MON FRI
1 1 2
3 MON SUN
1 2 2
10 2
1 MON TUE
3
1 MON WED
3
0 0
Source: ACM Central Europe 2005
IDs for Online Judges: POJ 2947, UVA 3529
Hint
There are N types of widgets, and each type takes a fixed number of days (between
three and nine) to be produced. In the factory there were several workers. For each
of them, we know the information “He started on weekday X, produced c1 widgets
of type t1, ..., ck widgets of type tk and finished on weekday Y.” The task is to deter-
mine the production time for each of the widgets.
There may be inputs where there is no answer or more than one answer, and in
these cases you just have to output a corresponding message.
Note that if we want to know the number of days D a widget takes to be com-
pleted, it is enough to determine (D modulo 7).
Each worker’s information can be translated into a linear congruence modulo 7.
The resulting set of equations can be solved using Gaussian elimination.
Note that all operations when solving the set of equations are done modulo 7.
Seven (the number of days in a week) is a prime number. Thus Z7 (the set {0, 1, 2,
3, 4, 5, 6} with addition and multiplication modulo 7) is a field. In other words,
each number other than 0 has a multiplicative inverse, and thus we can divide in
Z7. E.g., in Z7 2×4=1, so instead of dividing a number by 4, we can multiply it by 2.
Input
The input tests will consist of a series of positive integers. Each number is on a line
on its own. The maximum value is 1000000. The end of the input is reached when
the number 0 is met. The number 0 shall not be considered as part of the test set.
Output
The program shall output each result on a line by its own, following the format
given in the sample output.
289384 289384 : 3
930887 930887 : 2
692778 692778 : 5
636916 636916 : 4
747794 747794 : 3
238336 238336 : 3
885387 885387 : 2
760493 760493 : 2
516650 516650 : 3
641422 641422 : 3
0
Source: 2004 Federal University of Rio Grande do Norte Classifying Contest-R
ound 2
ID for Online Judge: UVA 10699
Hint
First, the prime list su[] in the interval [2, 1200] is calculated.
Then, for each test case, a positive integer x, the method by which the number
of different prime factors k for x is calculated as follows:
Initially k=0. The prime list su[] is searched one by one. If su[i] is a prime factor
for x (x% su[i]==0), then k++; and x/=su[i] is repeated until (x% su[i]≠0). If x>1
after all elements in su[] have been searched, k++.
integer kx and uniquely determined integers ekx , ekx −1 ,......, e1 , e0 ,(ekx > 0), that
x = pkexkx × pkexk−x −11 × ...... × p1e1 × p0e0 . The sequence (ekx , ekx −1 ,......, e1 , e0 ) is considered
to be the representation of x in the prime base number system.
It is really true that all numerical calculations in the prime base number system
can seem to us a little bit unusual, or even hard. In fact, the children in Prime Land
learn to add and to subtract numbers for several years. On the other hand, multi-
plication and division are very simple.
Recently, somebody has returned from a holiday in the Computer Land where small
smart things called computers have been used. It turns out that they could be used to
make addition and subtraction in the prime base number system much easier. It has
been decided to make an experiment and let a computer do the operation “minus one”.
Help people in the Prime Land and write a corresponding program for them.
For practical reasons, we will write here the prime base representation as a
sequence of such pi and ei from the prime base representation above, for which ei>0.
We will keep decreasing order with regard to pi.
Input
The input file consists of lines (at least one), each of which, except the last, contains
a prime base representation of just one positive integer greater than 2 and less or
equal to 32767. All numbers in the line are separated by one space. The last line
contains number 0.
Output
The output file contains one line for each but the last line of the input file. If x is a posi-
tive integer contained in a line of the input file, the line in the output file will contain
x−1 in prime base representation. All numbers in the line are separated by one space.
There is no line in the output file corresponding to the last “null” line of the input file.
17 1 24
5 1 2 1 32
509 1 59 1 13 1 11 1 7 1 5 1 3 1 2 1
0
Source: ACM Central Europe 1997
IDs for Online Judges: POJ 1365, ZOJ 1261, UVA 516
Hint
First, a prime list in the interval [2, 32767] is calculated.
Practice for Number Theory ◾ 143
Then, for a test case (a prime base representation of a number x), x is calculated
by multiplying x = pkexkx × pkexk−x −11 × ...... × p1e1 × p0e0 .
Finally, the prime base representation of x−1 is output.
Input
The input will consist of a sequence of numbers. Each line of input will contain one
number g in the range −231<g<231, but this number is different from −1 and 1. The
end of input will be indicated by an input line having a value of zero.
Output
For each line of input, your program should print a line of output consisting of the
input number and its prime factors. For an input number g>0, g=f1×f 2×……×f n,
where each f i is a prime number greater than unity (with f i ≤f j for i<j), the format
of the output line should be g=f1×f 2×……×f n. Where g<0, if |g|=f1×f 2×……×f n, the
format of the output line should be g=−1×f1×f 2×……×f n.
Sample Input Sample Output
-190 -190 = -1 x 2 x 5 x 19
-191 -191 = -1 x 191
-192 -192 = -1 x 2 x 2 x 2 x 2 x 2 x 2 x 3
-193 -193 = -1 x 193
-194 -194 = -1 x 2 x 97
195 195 = 3 x 5 x 13
196 196 = 2 x 2 x 7 x 7
197 197 = 197
198 198 = 2 x 3 x 3 x 11
199 199 = 199
200 200 = 2 x 2 x 2 x 5 x 5
0
Source: ACM East Central Region 1997
ID for Online Judge: UVA 583
144 ◾ Algorithm Design Practice for Collegiate Programming
Hint
First, a prime list in the interval [2, 231 ] is calculated.
Then, for a input number x, if x is negative, the −1 coefficient should be added
before factoring; this method is similar to the 3.4.8 Count the factors method.
Input
Each test case is given by a line of input containing x. The value of x will have mag-
nitude of at least 2 and be within the range of a (32-bit) int in C, C++, and Java. A
line containing 0 follows the last test case.
Output
For each test case, output a line giving the largest integer p such that x is a perfect
pth power.
17 1
1073741824 30
25 2
0
Source: Waterloo local 2004.01.31
IDs for Online Judges: POJ 1730, ZOJ 2124
Hint
The positive integer x is represented as the product of powers of prime factors
x = p1e 1 p2e 2 * pkek . The largest integer p such that x is a perfect pth power is
p=GCD(e1, e2, …, ek).
Practice for Number Theory ◾ 145
3.4.12 Factovisors
The factorial function n! is defined thus for n a non-negative integer:
0!=1
n!=n×(n−1)! (n>0)
Input
The input to your program consists of several lines, each containing two non-
negative integers, n and m, both less than 2^31.
Output
For each input line, output a line stating whether or not m divides n!, in the format
shown below.
6 9 9 divides 6!
6 27 27 does not divide 6!
20 10000 10000 divides 20!
20 100000 100000 does not divide 20!
1000 1009 1009 does not divide 1000!
Source: 2001 Summer keep-fit 1
ID for Online Judge: UVA 10139
Hint
The non-negative integer m is represented as the product of powers of prime factors
k
ers of prime factors n ! = ∏ p' , where {p , p , …, p } is a subset for {p', p ', …, p'}
i
e'i
1 2 k 1 2 t
i =1
and the power for pi in {p1, p2 , …, pk} is less than or equal to the power for pi in
{p1', p2', …, p'}.
t
In order to avoid “Out Of Memory Error (OOME)”, the power for pi for n! is
k
n k +1
calculated directly from n: e i' = ∑ p j ( p > n ).
j =1
i
F2 = {1/2}
F3 = {1/3, 1/2, 2/3}
F4 = {1/4, 1/3, 1/2, 2/3, 3/4}
F5 = {1/5, 1/4, 1/3, 2/5, 1/2, 3/5, 2/3, 3/4, 4/5}
Your task is to calculate the number of terms in the Farey sequence Fn.
Input
There are several test cases. Each test case has only one line, which contains a posi-
tive integer n (2≤n≤106). There are no blank lines between cases. A line with a single
0 terminates the input.
Output
For each test case, you should output one line, which contains N(n)—the number
of terms in the Farey sequence Fn.
2 1
3 3
4 5
5 9
0
Source: POJ Contest, Author: Mathematica@ZSU
ID for Online Judge: POJ 2478
Hint
Based on the problem description, the Farey Sequence Fn for any integer n with
n≥2 is the set of irreducible rational numbers a/b with 0<a<b≤n and GCD(a, b)=1
arranged in increasing order. Suppose F[i] is the number of terms in the Farey
sequence Fi, and f i ' is the number of terms whose denominators are i in the Farey
sequence Fi . Therefore,
f i' i=2
F [i ] = .
F [i − 1] + f i' 3≤i ≤n
Practice for Number Theory ◾ 147
For each term in the Farey sequence, Fi, its denominator i and numerator are
relatively prime. Therefore, f i ' is Euler phi-function ϕ(i). The offline method is used
to calculate F[]. Then for each test case (a positive integer k), F[k] is output.
1 5 7 11
, , ,
12 12 12 12
Input
Each line of the input contains a positive integer n(<1000000000) and the input
terminates with a value 0 for n (do not process this terminating value).
Output
For each n in the input, print a line containing the number of irreducible basic
fractions with denominator n.
12 4
123456 41088
7654321 7251444
0
Source: 2001 Regionals Warmup Contest
ID for Online Judge: UVA 10179
148 ◾ Algorithm Design Practice for Collegiate Programming
Hint
m
is irreducible if and only if gcd(m, n)=1. The number of m satisfying n≤m and
n
GCD(m, n)=1 is ϕ(n). Therefore, the number of irreducible basic fractions with
denominator n is ϕ(n).
Input
The input file contains at most 101 lines of inputs. Each line contains an integer
N (0<N≤2×109). Input is terminated by a line containing a single zero. This line
should not be processed.
Output
For each line of input except the last one, produce one line of output. This line
contains two integers N and C. Here N is the input number and C is its cardinality.
These two numbers are separated by a single space.
2 22
12 12 8
24 24 11
101101291 101101291 5
0
Source: UVa Monthly Contest August 2005
ID for Online Judge: UVA 10892
Hint
For a given positive integer N, the number of different integer pairs with LCM is
equal to N and can be called the LCM cardinality of that number N. Suppose A
Practice for Number Theory ◾ 149
and B are a pair of integers. A and B can be represented as the product of powers
of prime factors, A = ∏ p , and B = ∏ p
i
i
ai
i
bii
i . The LCM for A and B is N,
N = LCM ( A, B ) = ∏pi
Ci
i , where ∀i , ci=max{ai, bi}. This is the insight that lets us
1. If ∀j < i, cj=aj=bj. If ai=ci, then bi =0...ci, there are ci +1 pairs of integers (ci,0),
(ci,1), …, (ci,ci);
2. Otherwise, there are 2×ci +1 pairs of integers (0,ci), (1,ci), …, (ci −1,ci), (ci,ci −1),
…, (ci,0), (ci,ci).
Input
The input file contains several test cases. Each test case starts with an integer n
(0<n<1000), that stands for the cardinality of S. The next line contains the num-
bers of S: x1, x 2, ..., xn. It is known that each xi is an integer, 0<xi <2×109. The input
data set is correct and ends with an end of file.
Output
For each test case, find and print the value Dn mod 1000000007.
150 ◾ Algorithm Design Practice for Collegiate Programming
2 1
1 2 12
3 4
1 3 9
4
1 2 3 6
Source: ACM Southeastern European Regional Programming
Contest 2008
IDs for Online Judges: POJ 3910, UVA 4190
Hint
Suppose ai is the row (gcd(xi, x1) gcd(xi, x 2) gcd(xi, x3) … gcd(xi, xn)) for the matrix
Dn, and aij represents gcd(xi, xj).
There is a linear transformation for the matrix Dn ab − ∑ ad . Each ad
( d |b )&&( d ≠ b )
satisfying (d | b)&&(d≠b) has been transformed before ab is transformed.
0 gcd( xi , x j ) < xi
After ab has been transformed, aij = .
ϕ( xi ) gcd( xi , x j ) = xi
First, all xi are sorted in ascending order. Second, the gcd matrix M is con-
structed as the problem description. Third, a linear transformation for the matrix is
done as above. The matrix must be an upper triangular matrix, and each element
for the diagonal line of the matrix is the Euler phi-function ϕ(xi) for the row’s
n
Input
The input contains multiple test cases, each of which contains two positive inte-
gers, the GCD and the LCM. You can assume that these two numbers are both
less than 263.
Practice for Number Theory ◾ 151
Output
For each test case, output a and b in ascending order. If there are multiple solutions,
output the pair with smallest a+b.
Sample Input Sample Output
3 60 12 15
Source: POJ Achilles
ID for Online Judge: POJ 2429
Hint
For this problem, LCM=LCM(a, b), GCD=GCD(a, b), and a×b=LCM×GCD with
smallest a+b.
First N = LCM is calculated. If N==1, then the pair with smallest a+b is (GCD,
GCD
LCM); else (a, b) is calculated.
LCM N ×GCD N
Suppose a=t×GCD, b = = . Therefore, a :b = t : . Obviously,
t t t
N
a+b being the smallest is equivalent to t + being the smallest. The method for
calculating t is as follows: t
The positive integer N is represented as the product of powers of prime factors
k
N= ∏ p . Array a[] is used to represent the product of powers of prime factors for
i =1
i
ei
N, where a [i ]= pi i (1≤i ≤ k ) .
e
If t2>N, then t=N/t. The pair with smallest a+b is (t×GCD, LCM/t).
Chapter 4
◾◾ Generating Permutations;
◾◾ Enumeration of Permutations and Combinations;
◾◾ The Pigeonhole Principle and the Inclusion−Exclusion Principle;
◾◾ The Pólya Counting Formula.
Step 1: Find the longest suffix that is non-increasing by scanning the sequence
from right to left. The element immediately to the left of the suffix is called
“the first element.” If there is no such element, the sequence is non-increasing
153
154 ◾ Algorithm Design Practice for Collegiate Programming
and is the last permutation. That is, find such an index i that i=max{ j|pj-1<pj,
pj ≥ pj+1}, and pi-1 is the first element.
Step 2: Find the rightmost successor to the first element in the suffix. Because
the first element is less than the head of the suffix, some elements in the suffix
are greater than the first element. In the suffix, the rightmost successor to the
first element is the smallest element greater than the first element. We call the
element “the second element.” That is, find such an index j that j=max{k|k≥i,
pi-1<pk}.
Step 3: Swap pi-1 and pj, and get a new sequence p1 pi − 2 p j pi pi +1 p j −1 pi −1
p j +1 pn .
Step 4: Reverse the subsequence after the original index of the first element. The
next permutation is (q )=p1 pi−2 p j pn … p j+1 pi−1 p j−1 . pi+1 pi .
4.1.1.1 ID Codes
It is 2084 and the year of Big Brother has finally arrived, albeit a century late. In
order to exercise greater control over its citizens and thereby counter a chronic break-
down in law and order, the government decides on a radical measure—all citizens
are to have a tiny microcomputer surgically implanted in their left wrists. This com-
puter will contain all sorts of personal information, as well as a transmitter which
will allow people’s movements to be logged and monitored by a central computer.
An essential component of each computer will be a unique identification code,
consisting of up to 50 characters drawn from the 26 lowercase letters. The set of
characters for any given code is chosen somewhat haphazardly. The complicated
way in which the code is imprinted into the chip makes it much easier for the man-
ufacturer to produce codes that are rearrangements of other codes, rather than to
produce new codes with a different selection of letters. Thus, once a set of letters has
been chosen, all possible codes derivable from it are used before changing the set.
For example, suppose it is decided that a code will contain exactly three occur-
rences of “a”, two of “b”, and one of “c”; then three of the allowable 60 codes under
these conditions are:
abaabc
abaacb
ababac
Practice for Combinatorics ◾ 155
These three codes are listed from top to bottom in alphabetic order. Among
all codes generated with this set of characters, these codes appear consecutively in
this order.
Write a program to assist in the issuing of these identification codes. Your pro-
gram will accept a sequence of no more than 50 lowercase letters (which may con-
tain repeated characters) and print the successor code if one exists, or print the
message “No Successor” if the given code is the last in the sequence for that set of
characters.
Input
Input will consist of a series of lines, each containing a string representing a code.
The entire file will be terminated by a line consisting of a single #.
Output
Output will consist of one line for each code read, containing the successor code or
the words “No Successor”.
abaacb ababac
cbbaa No Successor
#
Source: New Zealand Contest 1991
IDs for Online Judges: POJ 1146, UVA 146
Analysis
1. The successor code is the next permutation based on lexicographic order.
Therefore, the algorithm is as follows. Suppose the given code is s0s1s2……sl-1.
2. Find the index i that i=max{ j|sj-1≥sj}.
3. If i==0, then the given code is the last in the sequence for that set of charac-
ters, output “No Successor”, and exit; else
4. On the right of “the first element”, find the smallest character greater than it.
That is, find such an index j that j=max{k|si-1<sk};
5. Swap si-1 and sj, and get s0…si-2 sj si si+1…sj-1 si-1 sj+1…sl-1;
6. Reverse the substring after sj, and get the successor code (q)=s0…si-2sj sl-1…
sj+1si-1sj-1 …si+1 si.
156 ◾ Algorithm Design Practice for Collegiate Programming
Program
# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <string>
# include <cmath>
# include <algorithm>
using namespace std;
typedef long long int64;
char s[60];int l; // identification codes whose length is l
int get() { //If there is a successor code for s, output
the successor and return 1; else return 0
int i=l-1;
while (i>0&&s[i-1]>=s[i]) i--; //find the first element
if (!i) return 0; //no successor
int mp=i; // find the second element
for (int j=i+1;j<l;j++) {
if(s[j]<=s[i-1])continue;
if(s[j]<s[mp])mp=j;
}
swap(s[mp],s[i-1]); // Swap si-1 and smp
sort(s+i,s+l); // Reverse the suffix after the i-th
character
return 1;
}
int main(){
while (~scanf("%s",s)&&s[0]!='#'){ //Input
identification codes until '#'
l=strlen(s); //the length of the identification
code
if(get()) printf("%s\n",s); // output the successor
else printf("No Successor\n");
}
return 0;
}
Not only can lexicographic order generate the next permutation for p1…pi-1
pi…pn, but it can also generate an r-combination of a set S of n elements {a1,
a 2,…, an}, where a1<a 2<…<an. Suppose the current r-combination of a set S is {ak1,
ak2,…, akr}, where 1≤k1<k 2<…<kr ≤n. Obviously, the first r-combination of a set S
Practice for Combinatorics ◾ 157
of n elements is {a1, a 2,…, ar}, and the last r-combination of a set S of n elements
is {an-r+1, an-r+2,…, an}.
If the current r-combination of a set S{ak1, ak2,…, akr} isn’t {an-r+1, an-r+2,…, an},
then the next r-combination is calculated as follows:
Suppose i is the maximal index kj that akj<an-kr+kj. Based on lexicographic
order, the next r-combination is {ak1,…, akj-1, akj+1,…, akr, akr+1}. Therefore, for an
r-combination {ak1, ak2,…, akr}, the algorithm for calculating the next r -combination
is as follows:
1. i=max{kj|akj<an-kr+kj };
2. ai ← ai+1, where kj≤i≤kr.
Input
The first line of the input contains an integer n, which indicates how many strings to
follow. The next n lines contain n strings. Strings will only contain alpha-numerals
and never contain any space. The maximum length of the string is 10.
Output
For each input string, print all the permutations possible in ascending order. Note
that the strings should be treated as case-sensitive strings and no permutation should
be repeated. A blank line should follow each output set.
158 ◾ Algorithm Design Practice for Collegiate Programming
3 ab
ab ba
abc
bca abc
acb
bac
bca
cab
cba
abc
acb
bac
bca
cab
cba
Source: TCL Programming Contest, 2001
ID for Online Judge: UVA 10098
Analysis
Suppose the length of string s is l. Therefore, l ! permutations in ascending order are
required to output. The algorithm is as follows:
The first permutation is achieved by sorting string s in ascending order. For the
current permutation s,
1. i=max{ j|sj-1≥sj};
2. j=max{k|si-1<sk};
3. Swap si-1 and sj, and get s0…si-2 sj si si+1…sj-1 si-1 sj+1…sl-1;
4. Reverse the substring after sj, and get the next permutation (q)=s0…si-2
sj sl-1…sj+1si-1sj-1 ….si+1 si;
The above process is repeated until i==0. All of the permutations possible in
ascending order are generated.
Program
# include <cstdio>
# include <cstring>
Practice for Combinatorics ◾ 159
# include <cstdlib>
# include <iostream>
# include <string>
# include <cmath>
# include <algorithm>
using namespace std;
typedef long long int64;
char s[60];int l; // the length of string s is l
int get(){ // If there is a successor for s, output the
successor and return 1; else return 0
int i=l-1; // find the first character
while(i>0&&s[i-1]>=s[i])i--;
if(!i) return 0; // no successor
int mp=i; // find the second character
for(int j=i+1;j<l;j++){
if(s[j]<=s[i-1])continue;
if(s[j]<s[mp])mp=j;
}
swap(s[mp],s[i-1]); // Swap si-1 and smp
sort(s+i,s+l); // Reverse the substring after si
return 1;
}
int main(){
int casen;scanf("%d",&casen); //number of strings
while(casen--){
scanf("%s",s); //current string
l=strlen(s); //the length of the current string
sort(s,s+l);
printf("%s\n",s); //the first permutation
while(get()) printf("%s\n",s); //all permutations
printf("\n");
}
return 0;
}
Method 1:
n! (n − r + 1) × (n − r + 2) × ... × n n − r + 1 n−r +2 n
C (n , r ) = = = × × ... .
r !(n − r )! 1 × 2 × ... × r r r −1 1
Input
The input file will contain one or more test cases. Each test case consists of one line
containing two integers n (n>=1) and k (0<=k<=n). Input is terminated by two
zeros for n and k.
Output
For each test case, print one line containing the required number. This number will
always fit into an integer; i.e., it will be less than 231.
Warning: Don’t underestimate the problem. The result will fit into an i nteger—
but whether all intermediate results arising during the computation will also fit into
an integer depends on your algorithm. The test cases will go to the limit.
4 2 6
10 5 252
49 6 13983816
0 0
Source: Ulm Local 1997
IDs for Online Judges: POJ 2249, ZOJ 1938
Practice for Combinatorics ◾ 161
Analysis
Method 1 is used to solve the problem directly:
C ( n, k ) =
n!
=
(n − k + 1) × (n − k + 2) × ... × n
k ! (n − k ) ! 1 × 2 × ... × k
n − k +1 n − k + 2 n
= × × ... .
k k −1 1
Program
# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <string>
# include <cmath>
# include <algorithm>
using namespace std;
typedef long long int64;
int64 work(int64 n,int64 k){ //Calculate C(n, k)
if(k>n/2) k=n-k; // To reduce the amount of
calculation
int64 a=1,b=1;
for(int i=1;i<=k;i++){
a*=n+1-i;
b*=i;
if(a%b==0)a/=b,b=1;
}
return a/b; //return C(n, k)
}
int main() {
int n,k;
while(~scanf("%d %d",&n,&k)&&n){ // Input test cases
printf("%lld\n",work(n,k)); // Calculate and
output C(n, k)
}
return 0;
}
162 ◾ Algorithm Design Practice for Collegiate Programming
4.2.1.2 Combinations
Computing the exact number of ways that N things can be taken M at a time can
be a great challenge when N and/or M become very large. Challenges are the stuff of
contests. Therefore, you are to make just such a computation, given the following:
Given: 5≤N≤100; 5≤M≤100; M≤N
Compute the EXACT value of: C=N!/(N−M)!M!
You may assume that the final value of C will fit in a 32-bit Pascal LongInt or a
C long. For the record, the exact value of 100! is:
93,326,215,443,944,152,681,699,238,856,266,700,490,715,968,264,381,621,
468,592,963,895,217,599,993,229,915,608,941,463,976,156,518,286,253,697,920,
827,223,758,251,185,210,916,864,000,000,000,000,000,000,000,000
Input
The input to this program will be one or more lines each containing zero or more
leading spaces, a value for N, one or more spaces, and a value for M. The last line of
the input file will contain a dummy N, M pair with both values equal to zero. Your
program should terminate when this line is read.
Output
The output from this program should be in the form:
N things taken M at a time is C exactly.
Analysis
Suppose c[i][ j] is C(i, j).
Based on the formula calculating binomial coefficients, c[i][j]=c[i−1][ j]+c[i−1]
[ j−1].
Initially, c[i][0]=1, 0≤i≤101. Then, based on the above formula, c[i][ j] can be
calculated, 1≤i≤100, 1≤j≤100. Finally, for each test case N, M, output c[N ][M].
Practice for Combinatorics ◾ 163
Program
# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <string>
# include <cmath>
# include <algorithm>
using namespace std;
typedef unsigned long long int64;
unsigned int c[110][110]; //c[i][j] is C(i, j)
void pp(){ //calculate c[][] using the formula
for (int i=0;i<102;i++) c[i][0]=1;
for (int i=1;i<101;i++)
for(int j=1;j<101;j++) c[i][j]=c[i-1][j-1]+c[i-1]
[j];
}
int main(){
pp(); //offline method is used to calculate c[][]
int n,m;
while (~scanf("%d %d",&n,&m)&&(n||m)) //Input test
cases
printf("%d things taken %d at a time is %u
exactly.\n",n,m,c[n][m]); //output C(n, m)
return 0;
}
Figure 4.1
164 ◾ Algorithm Design Practice for Collegiate Programming
Input
Your program is to read from standard input. The input consists of four lines. Each
line describes one given rectangle by two positive integers: the lengths of the sides
of the rectangle. Each side of a rectangle is at least 1 and at most 50.
Output
Your program is to write to standard output. The output should contain one line
more than the number of solutions. The first line contains a single integer: the min-
imum area of the enclosing rectangles. Each of the following lines contains one
solution described by two numbers p and q with p≤q. These lines must be sorted in
ascending order of p, and the lines must all be different.
1 2 40
2 3 4 10
3 4 5 8
4 5
Source: IOI 1995
ID for Online Judge: POJ 1169
Analysis
1. Calculating widths and heights for the enclosing rectangles.
The problem description shows six ways to fit four rectangles together. The key
to the problem is to calculate the area of the enclosing rectangles for six ways.
Suppose four rectangles which will be placed into the enclosing rectangle are
represented as an array t[0…3], and for rectangle t[i], its height and width
are t[i].x and t[i].y respectively, 0≤i≤3.
For each rectangle, there are two ways to place it into the enclosing rect-
angle: place it horizontally, or place it vertically. Obviously, if a rectangle’s
placement method is changed, we only need to exchange its height and width.
Practice for Combinatorics ◾ 165
Based on the problem description, six ways to fit four rectangles together
are analyzed as follows:
Case 1:
t[1]
t[0] t[2] t[3]
rectangle p
y
Figure 4.2
Four rectangles (t[0], t[1], t[2], and t[3]) are placed in order as shown in
Figure 4.2. For Case 1, the height and width for the enclosing rectangle p are
as follows: p.x=max{t[0].x, t[1].x, t[2].x, t[3].x}; p.y=t[0].y+t[1].y+t[2].y+t[3].y.
Case 2:
t[2]
t[0] t[1]
rectangle p
t[3].x t[3].y
Figure 4.3
In the enclosing rectangle p, there are two parts: the upper part and the
lower part, as shown in Figure 4.3. In the upper part, t[0], t[1], and t[2]
are placed; and in the lower part, t[3] is placed. For case 2, the height and
width for the enclosing rectangle p are as follows: p.x=max{t[0].x, t[1].x,
t[2].x}+t[3].y, p.y=max{t[3].x, t[0].y+t[1].y+t[2].y}.
166 ◾ Algorithm Design Practice for Collegiate Programming
Case 3:
t[1]
t[0] t[3]
rectangle p
t[2]
Figure 4.4
In the enclosing rectangle p, there are two parts: the left part and the right
part, as shown in Figure 4.4. In the left part, t[2] is placed below, t[0] and t[1]
are placed up, and t[2] and t[1] are right-aligned. In the right part, t[3] is placed.
For case 3, the height and width for the enclosing rectangle p is as follows:
p.x=max{max{t[0].x, t[1].x}+t[2].x, t[3].x)}, p.y=max{t[0].y+t[1].y, t[2].y}+t[3].y.
x x
rectangle p
rectangle p
t[2] t[0]
t[1]
t[3]
t[0] t[3]
t[1]
t[2]
y y
Figure 4.5
Case 6:
rectangle p
x t[3] x rectangle p
t[1]
t[3]
t[1]
t[0]
t[2].y
t[0]
t[2].y
t[2].x
t[2].x
y y
Figure 4.6
In the enclosing rectangle p, four rectangles are placed in two rows, and
in each row there are two rectangles, where t[1].x≤t[3].x≤t[0].x+t[1].x and
t[0].y≤t[1].y. In Figure 4.6, there are two different ways. All placements can
be calculated through rotations and reflections for the two ways. The height
and width for the enclosing rectangle p are as follows: p.x=max{t[0].x+t[1].x,
t[2].y+t[3].x}, p.y=max{t[0].y+t[2].x, t[1].y+t[3].y}.
If rectangle t[i] is placed horizontally (i.e., v[i]=1, 0≤i≤3), its height and
width are exchanged (i.e., t[i].x↔t[i].y).
There are four rectangles, and there are two placements for each rectan-
gle. Therefore, there are 4!×24 different t[0…3]. And for each t[0…3], there
are five enclosing rectangles (Case 1 to 5). Therefore, there are 4!×24×5=1920
areas of enclosing rectangles. We can calculate the minimum area of the
enclosing rectangles as min_area.
Suppose soln[0…ps] stores the sequence of enclosing rectangles whose
area is min_area. In the sequence, each element is described by two numbers
soln[i].x and soln[i].y with soln[i].x≤soln[i].y. All elements are sorted in ascend-
ing order of soln[i].x, 0≤i≤ps.
168 ◾ Algorithm Design Practice for Collegiate Programming
Initially, min_area=∞, the rear pointer for soln[] ps=0. Then, each enclos-
ing rectangle p in r[0…3] is enumerated:
If p. x > p. y , then ( p. x ↔ p. y );
If p. x × p. y <min _ area , then min _ area= p. x × p. y ; and p is stored
( soln[0]← p, ps =1);
If p. x × p. y =min _ area , then p is added into soln []( soln [ ps ++ ]← p );
If p. x × p. y >min _ area , then p is omitted.
After the enumeration, min_area is the minimum area of the enclosing
rectangles. All elements in array soln are sorted, x is the first key, and y is the
second key. And all elements are different.
Program
#include <fstream>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
#define MAX 0x7fffffff
typedef struct //rectangle
{
int x;
int y;
}rec;
int min_area = MAX; //Initialization: the minimum area of
the enclosing rectangles
rec soln[1000]; //the sequence of enclosing rectangles
whose area is minimal, whose length is ps
int ps = 0;
rec r[4]; // Input 4 rectangles
rec t[4]; // 4 rectangles placed into the enclosing
rectangle
rec zero={0,0}; //Initialize height and width
int v[4]; // placements for each rectangle
inline void make(rec p) // soln[] is adjusted based on the
current enclosing rectangle p
{
if(p.x>p.y)
{
p.x = p.x ^ p.y; p.y = p.x ^ p.y; p.x = p.x ^ p.y;
}
Practice for Combinatorics ◾ 169
p.x=max(t[0].x,max(t[1].x,t[2].x))+t[3].y; // the
height and width for p
p.y = max(t[0].y+t[1].y+t[2].y,t[3].x);
make(p); // soln[] is adjusted based on the current
enclosing rectangle p
if(p.x == 10 && p.y == 8) p=p;
p=zero; //Case 3
p.x=max(max(t[0].x,t[1].x)+t[2].x,t[3].x); // the
height and width for p
p.y = max(t[0].y+t[1].y,t[2].y)+t[3].y;
make(p); // soln[] is adjusted based on the current
enclosing rectangle p
if(p.x == 10 && p.y == 8) p=p;
p=zero; //Case 4 and 5
p.x=max(t[0].x,max(t[1].x+t[2].x,t[3].x)); // the
height and width for p
p.y = t[0].y + max(t[1].y,t[2].y) + t[3].y ;
make(p); // soln[] is adjusted based on the current
enclosing rectangle p
if(p.x == 10 && p.y == 8) p=p;
if(t[0].y>t[1].y) continue; //Case 6: If 4
rectangles can't satisfy t[1].x≤t[3].x≤t[0].x+t[1].x and t[0].
y≤t[1].y, continue to enumerate
if(t[3].x > t[0].x+t[1].x) continue;
if(t[3].x<t[1].x) continue;
p = zero; //Initialization
p.x = max(t[0].x+t[1].x,t[2].y+t[3].x); // the
height and width for p
p.y = max(t[1].y+t[3].y,t[0].y+t[2].x);
make(p); // soln[] is adjusted based on the current
enclosing rectangle p
if(p.x == 6 && p.y == 6) p=p;
}
}
}
}
bool comp(rec a,rec b) //comparing enclosing rectangles a and
b (x is the 1st key, y is the 2nd key)
{
if(a.x<b.x) return 1;
else if(a.x == b.x && a.y<b.y) return 1;
else return 0;
}
bool comp2(rec a,rec b) //determine whether enclosing
rectangles a and b are same
{
return a.x==b.x && a.y==b.y;
}
int main()
{
Practice for Combinatorics ◾ 171
Input
Each line of the input file will be a single positive number n, except the last line,
which is a number −1. You may assume that 1≤n≤100.
172 ◾ Algorithm Design Practice for Collegiate Programming
Output
For each n, print in a single line the number of ways to connect the 2n numbers
into pairs.
2 2
3 5
-1
Source: ACM Shanghai 2004 Preliminary
IDs for Online Judges: POJ 2084, ZOJ 2424
Analysis
Based on the problem description, there are n lines connecting 2n numbers into
pairs. For each line, there are i pairs of numbers on the left, and there are n−i−1
pairs of numbers on the right. Suppose Cn is the number of ways to connect the 2n
numbers into pairs. C0 =1, C1=1, and Cn=C0Cn-1+C1Cn-2+…+Cn-1C0, n≥2. Therefore,
Cn is a Catalan number.
The offline method is used to calculate the Catalan sequence C0, C1, …, C120.
Because the range of Catalan numbers is out of the range of integers in program-
ming languages, Catalan numbers are stored as high-precision numbers.
Program
# include <cstdio>
# include <cstring>
# include <algorithm>
# include <iostream>
using namespace std;
struct BIGNUM{ //High-precision number
short s[200],l; //the length of integer array s[] is l
}c[120]; // Catalan sequence, where c[i]=Ci
BIGNUM operator*(BIGNUM a,int b){ //a←a*b, where a is an
integer array, b is a integer
for(int i=0;i<a.l;i++) a.s[i]*=b;
for(int i=0;i<a.l;i++){ //carry
Practice for Combinatorics ◾ 173
a.s[i+1]+=a.s[i]/10;
a.s[i]%=10;
}
while(a.s[a.l]!=0){
a.s[a.l+1]+=a.s[a.l]/10;
a.s[a.l]%=10;
a.l++;
}
return a;
}
BIGNUM operator/(BIGNUM a,int b){ //a←a/b, where a is an
integer array, b is an integer
for(int i=a.l-1;i>0;i--){
a.s[i-1]+=(a.s[i]%b)*10;
a.s[i]/=b;
}
a.s[0]/=b;
while(a.s[a.l-1]==0) a.l--; //number of digits
return a;
}
void print(BIGNUM a){ //output array a
for(int i=a.l-1;i>=0;i--){
printf("%d",a.s[i]);
}
printf("\n");
}
int n;
int main(){
c[0].l=1;c[0].s[0]=1; //The first Catalan number C0=1
for(int i=0;i<=101;i++) //Calculate Catalan sequence
4* n -2
C n = C n-1* , offline method
n +1
c[i+1]=(c[i]*(4*i+2))/(i+2);
while(~scanf("%d",&n)){ //Input test cases
if(n<0) break;
print(c[n]); //Output Cn
}
return 0;
}
B1 = 1. Bn +1 = ∑C (n,k )B .
k =0
k
174 ◾ Algorithm Design Practice for Collegiate Programming
Stirling numbers of the first kind are the number of ways to arrange n objects
into k cycles, where S(n, 0)=0, S(1, 1)=1, S(n, k)=S(n−1, k−1)+(n−1)×S(n−1, k).
Stirling numbers of the second kind are the number of ways to partition
a set of n elements into k non-empty subsets. S(n, n)=S(n, 1)=1, S(n, k)=S(n−1,
k−1)+ k×S(n−1, k).
n
Obviously, Bn +1 =
kind.
∑
k =1
S ( n, k ), where S(n, k) is a Stirling number of the second
Bell numbers and Stirling numbers of the second kind can be calculated
through constructing Bell triangle a.
In a Bell triangle, the numbers on the left-hand side are the Bell numbers for
that row (see Figure 4.7). That is, Bi=a[i, 0], i≥0. The sums of numbers on each row
are Stirling numbers of the second kind.
4.2.2.2.1 Bloques
Little John has N blocks, all of them of different sizes. He is playing to build cities
in the beach. A city is just a collection of buildings.
A single block over the sand can be considered as a building. Then John can
construct higher buildings by putting a block above any other block. At most one
block can be put immediately above any other block. However, he can stack sev-
eral blocks together to construct a building. However, it’s not allowed to put bigger
blocks on top of smaller ones, since the stack of blocks may fall. A block can be
specified by a natural number that represents its size.
1
1 2
2 3 5
5 7 10 15
15 20 27 37 52
52 67 87 114 151 203
203 255 322 409 523 674 877
877 1080 1335 . 1657 2066 . 2589 3263 . 4140
.. .. ..
Figure 4.7
Practice for Combinatorics ◾ 175
12
In this city, both blocks of size 1 and 2 are put over the sand.
City #2:
1
2
In this city a block of size 1 is over a block of size 2, and a block of size 2 is over
the sand.
So, #(2)=2.
Input
A sequence of non-negative integer numbers, each one in a different line. All of
them but the last one are natural numbers. The last one is 0 and means the end.
Each natural number is less than 900.
Output
For each natural number I in the input, you must write a line with the pair of
numbers I, #(I).
2 2, 2
3 3, 5
0
Source: Contest ACM-BUAP 2005
ID for Online Judge: UVA 10844
176 ◾ Algorithm Design Practice for Collegiate Programming
Analysis
The problem requires you to compute the number of possible different cities using
N blocks, that is, the number of different ways to partition a set. Therefore, #(N)
is a Bell number Bn.
The offline method is used to calculate Bell numbers B0, B1, …, Bn … in the
range by constructing a Bell triangle. Because the range of Bell numbers is out of
the range of integers in programming languages, Bell numbers are stored as high-
precision numbers.
Program
# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <string>
# include <cmath>
# include <algorithm>
using namespace std;
typedef unsigned long long int64;
int64 m=1e10;
struct Bigint{ //High-precision number
int l;int64 s[200]; //s[] stores a high-precision number,
each element stores a 10-digit decimal number, the length is l
void read(int64 x){ //integer x is represented by a high-
precision number s[]
l=-1; memset(s,0,sizeof(s))
do {
s[++l]=x%m;
x/=m;
} while(x);
}
void print(){ // Output s[]
printf("%llu",s[l]); // s[l]: practical number of
digit, s[l−1]…s[0]: 10 digits
for(int i=l-1;i>=0;i--) printf("%010llu",s[i]);
}
} dp[2][1000],ans[1000]; //In a Bell triangle, the value
for (i, j) is dp[i&1][j]; the value for (i−1,j) is dp
[(i&1)^1][j], and the Bell number for i is ans[i+1]
Practice for Combinatorics ◾ 177
The steps for applying the pigeonhole principle to solve problems are as
follows:
Input
The first line of the input contains the single number N. Each of the next N lines
contains one number from the given set.
Output
In case your program decides that the target set of numbers cannot be found, it
should print the single number 0 to the output. Otherwise, it should print the
number of the chosen numbers in the first line followed by the chosen numbers
themselves (on a separate line each) in arbitrary order.
If there are more than one set of numbers with the required properties, you
should print to the output only one (preferably your favorite) of them.
5 2
1 2
2 3
3
4
1
Source: Ural Collegiate Programming Contest 1999
IDs for Online Judes: POJ 2356, Ural 1032
Practice for Combinatorics ◾ 179
Analysis
For this problem, we can prove this proposition.
For a sequence with N natural (i.e., positive integer) numbers a1,…, aN, there
r
If there exists a Bi exactly divisible by N, the proposition holds; else there are
N−1 remainders for Bi divided by N; i=1, 2, …, N.
Remainders are regarded as containers, and Bi are regarded as objects. There
are N objects are put into N−1 containers. Based on the pigeonhole principle, there
must exist Bj and Bi, Bj%N==Bi%N, 1≤j<i≤N. Therefore, (Bi−Bj)%N==0, that is,
i
Program
# include <stdio.h>
int a[10004],s[10004],mod[10004],n;
void print(int s,int t){ //Output a[s]..a[t]
printf("%d\n",t-s+1); //the number of the chosen numbers
for(int i=s;i<=t;i++) //the chosen numbers
printf("%d\n",a[i]);
}
int main(){
scanf("%d",&n); //Input the number of positive integers N
for(int i=1;i<=n;i++){ // Remainders are regarded as
containers
scanf("%d",a+i); // the i-th positive integers
s[i]=s[i-1]+a[i]; //the sum of the first i positive
integers
if(s[i]%n==0){ //if the sum of the first i positive
integers can be divided exactly by N
print(1,i);
break;
180 ◾ Algorithm Design Practice for Collegiate Programming
A1 ∪ A2 ∪ ... ∪ An = ∑| A | − ∑
i =1
i
1≤i1 <i2 ≤ n
Ai1 ∩ Ai2 + ∑
1≤i1 <i2 <i3 ≤ n
Ai1 ∩ Ai2 ∩ Ai3 − ......
+ (−1)n −1 A1 ∩ A2 ∩ ... ∩ An ;
A1 ∪ A2 ∪ ...... An = A1 ∩ A2 ...... ∩ An =| S | − A1 ∪ A2 ∪ ...... ∪ An ; where Ai
indicates the cardinality of a set Ai , 1 ≤ i ≤ n.
When the inclusion–exclusion principle is used for A1, ..., An, there are
C(n, 2)=n(n−1)/2 two-set intersections, C(n, 3)=n(n−1)(n−2)/3! three-set intersec-
tions, and so on.
embarrassment this year, the dean has asked for your help. You should find the
number of sets of k different numbers, each of the numbers not exceeding s, which
have a common divisor greater than 1. Of course, the number of such sets equals
the maximum possible number of new students of the department.
Input
The input contains numbers k and s (2≤k≤s≤50).
Output
You should output the maximum possible number of the department’s new stu-
dents if this number does not exceed 10000, which is the maximum capacity of the
department; otherwise, you should output 10000.
3 10 11
Source: USU Open Collegiate Programming Contest March 2001 Senior Session
ID for Online Judge: Ural 1091
Analysis
Every natural number n≥2 is a prime number or a product of prime numbers.
Every common divisor i (2≤i≤s) is enumerated. In 1…s the number of numbers
s −i
that have a common divisor i is d = + 1. The number of k-combination of a
i
d-element set is C(d, k), and the number in each k-combination has the common
divisor i.
If the common divisor i is a prime number, C(d, k) is accumulated into the
number of the department’s new students;
If the common divisor i is a product of two prime numbers, in the number of
the department’s new students, C(d, k) is counted twice. Based on the inclusion–
exclusion principle, C(d, k) must be subtracted from the number of the d epartment’s
new students.
Because of the range of s, for this problem, we need not consider products of three
prime numbers. Suppose ans is the maximum possible number of the department’s
new students.
182 ◾ Algorithm Design Practice for Collegiate Programming
Program
# include <cstdio>
# include <algorithm>
# include <iostream>
using namespace std;
typedef long long int64;
for(int i=2;i<=s;i++){
s-i
if(!pp[i]){ //if i is a prime, ans+=C +1, k
i
int cnt=0;
for(int j=i;j<=s;j+=i)cnt++;
ans+=c[cnt][k];
int main(){
cal_prime(); //construct prime sieve p[]
cal_number(); // calculate c[][]
scanf("%d %d",&k,&s); //calculate the solution
cout<<work()<<endl;
return 0;
}
the item in some other place. Tintin is very intelligent and a boy with a very sharp
memory. To make things worse for his parents, he never returns the things he has
taken for playing to their original places.
Think about a morning when Tintin has managed to “steal” three household
objects. Now, in how many ways he can place those things such that nothing is
placed in their original place? Tintin does not like to give his parents that much
trouble. So, he does not leave anything in a completely new place; he merely per-
mutes the objects.
Input
There will be several test cases. Each will have a positive integer less than or equal
to 800, indicating the number of things Tintin has taken for playing. Each integer
will be in a line by itself. The input is terminated by a –1 (minus one) in a single
line, which should not be processed.
Output
For each test case, print an integer indicating in how many ways Tintin can rear-
range the things he has taken.
2 1
3 2
4 9
-1
Source: The FOUNDATION Programming Contest 2004
ID for Online Judge: UVA 10497
Analysis
Because Tintin never returns the things he has taken for playing to their original
places, the problem requires you to calculate the number of derangements.
Because the number of things Tintin has taken for playing is a positive integer
less than or equal to 800, a high-precision number is used to calculate the result.
First, the offline method is used to calculate D1…D800. Then, for each test case n,
output Dn directly.
Practice for Combinatorics ◾ 185
Program
# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <string>
# include <cmath>
# include <algorithm>
using namespace std;
typedef unsigned long long int64;
int64 m=1e10; //High-precision number array s, each element
is a 10-digit decimal number
struct Bigint{ //Struct Bigint for high-precision
calculation
int64 s[1000];int l; // High-precision number array s[],
its length is l
Bigint(){l=0; memset(s,0,sizeof(s))} //Initialization
void operator *=(int x){ //s←s*x, where x is an integer
int64 d=0;
for(int i=0;i<=l;i++){
d+=s[i]*x;s[i]=d%m;
d/=m;
}
while(d){
s[++l]=d%m;
d/=m;
}
}
void print(){
printf("%llu",s[l]); //output
for(int i=l-1;i>=0;i--)
printf("%010llu",s[i]);
}
void set(int64 a){ //integer a is transferred into high-
precision array s
s[l]=a%m;a/=m;
if(a)l++,s[l]=a%m;
}
}dp[1000]; // dp[n] is Dn
Bigint operator+(Bigint b,Bigint&a){ //b←b+a, where b and a
are high-precision arrays
int64 d=0;
b.l=max(b.l,a.l);
for(int i=0;i<=b.l;i++)
{
186 ◾ Algorithm Design Practice for Collegiate Programming
b.s[i]+=d+a.s[i];
d=b.s[i]/m;b.s[i]%=m;
}
if(d)b.l++,b.s[b.l]=d;
return b;
}
int n;
int main(){
dp[1].set(0);dp[2].set(1); // dp[1]=0, dp[1]=1
for(int i=3;i<=800;i++)dp[i]=dp[i-2]+dp[i-1],
dp[i]*=(i-1); //offline method to calculate dp[]
while(~scanf("%d",&n)&&~n){ //input n
dp[n].print();printf("\n"); //output Dn
}
return 0;
}
a1 a2 ... an
.
f (a1 ) f ( a2 ) ... f (an )
1 2 3 4 1 2 3 4
f1 = , f2 = ,
3 1 2 4 4 3 2 1
1 2 3 4 1 2 3 4 1 2 3 4
f1 f 2 = = .
3 1 2 4 4 3 2 1 2 4 3 1
1 2 3 4 1 2 3 4 1 2 3 4
f 2 f1 = = .
4 3 2 1 3 1 2 4 4 2 1 3
Therefore, f 1 f 2 ≠ f 2 f 1 .
There are six permutations for (1)2(2)1: (12), (13), (14), (23), (24), and
(34);
There is one permutation for (1)4: (1)(2)(3)(4);
There are six permutations for (4)1: (1234), (1243), (1324), (1342), (1423),
and (1432).
Definition 4.4.3 (Conjugacy Class). In Sn, permutations with the same
format are called conjugacy classes.
The number of conjugacy classes in Sn is equal to the number of integer
partitions of n.
The number of permutations for a conjugacy class (1)C1 (2)C 2 ...(n )Cn is
n! .
c1 !...cn !1c1 2c2 ...n cn
For example, in S4, numbers of permutations for all conjugacy classes are
as follows:
4!
In conjugacy class (2)2 there are = 3 permutations. In conjugacy
2!× 22
4!
class (1)1(3)1 there are = 8 permutations. In conjugacy class (1)2(2)1 there
1!× 3
4! 4!
are = 6 permutations. In conjugacy class (1)4 there are =1 permuta-
2!× 2 4!
4!
tion. In conjugacy class (4)1 there are = 6 permutations.
4
Suppose G is a permutation group for {1, 2, …, n}, and K is a number in
{1, 2, …, n}. Of course, G is a subgroup for Sn. The stabilizer of the number
K, written ZK, is the set of all permutations of G that leave K fixed.
For example, G={e, (1 2), (3 4), (1 2)(3 4)}. Z1={e, (3 4)}; Z2={e, (3 4)};
Z3 ={e, (1 2)}; Z4 ={e, (1 2)}. Obviously, ZK is a subgroup for G, K is a number
in {1, 2, 3, 4}. For G, under the permutation, 1 can be permuted to 2, 2 can
be permuted to 1; and 3 can be permuted to 4, 4 can be permuted to 3. But
1 or 2 can’t be permuted to 3 or 4, and 3 or 4 can’t be permuted to 1 or 2.
Therefore, 1 and 2 are in one equivalence class, and 3 and 4 are in the other
equivalence class.
Suppose G is a permutation group for {1, 2, …, n}, and K is a number
in {1, 2, …, n}. Under the permutation, {1, 2, …, n} can be partitioned into
several equivalence classes. The equivalence class that K belongs to is denoted
as EK.
3. Burnside’s Lemma and Pólya Counting Formula.
Theorem 4.4.1 Suppose G is a permutation group for {1, 2, …, n}, and K
is a number in {1, 2, …, n}. |EK |×|ZK |=|G|.
For example, G={e, (1 2), (3 4), (1 2) (3 4)}; E1=E2={1, 2}, E3 =E4 ={3, 4};
|E1|=|E2|=|E3|=|E4|=2; Z1=Z2={e, (3 4)}, Z3 =Z4 ={e, (1 2)}; |Z1|=|Z2|=|Z3|=
|Z4|=2. Obviously, |E1|×|Z1|=|E2|×|Z2|=|E3|×|Z3|=|E4|×|Z4|=4=|G|.
Practice for Combinatorics ◾ 189
C1 C2 C3 C4 C5 C6 C7 C8
Figure 4.8
C1 C2 C3 C4 C5 C6
Figure 4.9
2 1
3 4
Figure 4.10
C1 C2
Figure 4.11
C1 C2 C11 C12
Figure 4.12
If the above square is rotated 0°, 90°, 180°, and 270° counterclockwise, a
permutation group G={P1, P2, P3, P4} is used to represent the rotations. The
number of permutations |G|=4. Suppose c(Pi) is the number of cycles for Pi,
i=1, 2, 3, 4. Therefore, P1=(1)(2)(3)(4), c(P1)=4; P2=(1 2 3 4), c(P2)=1; P3 =(1 3)
(2 4), c(P3)=2; P4 =(4 3 2 1), c(P4)=1.
Suppose m is the number of colors. If each cycle is colored with
same color in Pi, the number of colorings m c ( Pi ) is the number of color-
ings for G under permutation Pi. 2 ( 1 ) = 24 = c1 ( P1 ) = 16, 2 ( 2 ) = 21 =
c P c P
c1 ( P2 ) = 2, 2 ( 3 ) = 22 = c1 ( P3 ) = 4, and 2c ( P4 ) = 21 = c1 ( P4 ) = 2.
c P
P4 =(4 3 2 1), cycles whose order is 1 for P4 are (c1)(c2). That is, c1 and c2
are the four little squares are colored with the same color. (See Figure 4.11.)
P3 =(1 3)(2 4), cycles whose order is 1 for P3 are (c1)(c2)(c11)(c12). That is,
square 1 and square 3 are colored with the same color, and square 2 and
square 4 are colored with the same color (see Figure 4.12).
Practice for Combinatorics ◾ 191
1
Obviously, the number of nonequivalent colorings l = (24 +21 +22 +21 )=6.
4
Based on that, the Pólya Counting Formula is as follows:
Pólya Counting Formula. Let G be a permutation group {P1, P2, ……,
Pk} of n elements. And m colors are used to color the n elements. Then the
1 c(P ) c(P ) c(P )
number of nonequivalent colorings l = (m 1 + m 2 + m k ), where
G
c(Pi) is the number of cycles for Pi, i=1…k.
If there is a permutation group G of a set. Based on the number of per-
mutations |G|, and the number of cycles c(Pi) for each permutation Pi, the
Pólya Counting Formula is used to calculate the number of produced equiv-
alence classes.
Input
The input has several lines, and each line contains the input data n. −1 denotes the
end of the input file.
Red
Green Red
Blue Blue
O O
Figure 4.13
192 ◾ Algorithm Design Practice for Collegiate Programming
Output
The output should contain the output data: the number of different forms, in each
line corresponding to the input data.
4 21
5 39
-1
Source: ACM Xi’an 2002
IDs for Online Judges: POJ 1286, UVA 2708
Analysis
Suppose a is the current permutation, where aj is the number of beads in the jth
position, 1≤j≤n.
Rotate around the center of the circular necklace and reflect to the axis of sym-
metry i times successively, 0≤i≤n−1.
1. The i-th times, a rotation: Bead j is permutated by bead (j+i)%n+1, that is,
a[j]=a[(j+i)%n+1], 1≤j≤n. Suppose ci is the number of cycles for the i-th per-
mutation. The number of colorings is 3ci .
2. The i-th times, a reflection: Bead j and bead (n+1−j) exchange each other,
that is, a[j]↔a[n+1−j], 1≤j≤n. Suppose ci' is the number of cycles for the i-th
c'
permutation. The number of colorings is 3 i .
Obviously, there are 2×n permutations. The Pólya Counting Formula is used to
n
Program
# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
Practice for Combinatorics ◾ 193
# include <string>
# include <cmath>
# include <algorithm>
using namespace std;
typedef long long int64;
int n,vis[30],lab[30]; // lab[]: current permutation, bead
j is permutated by bead lab[j]; vis[j]: permutation flag for j
int64 qpow(int64 a,int64 b){ //calculate and return ab
int64 ans=1;
while(b){
if(b&1) ans*=a;
a*=a;b>>=1;
}
return ans;
}
int getloop(){ // calculate and return the number of cycles
for the current permutation
memset(vis,0,sizeof(vis));
int cnt=0;
for(int i=1;i<=n;i++) {
if(vis[i])continue; //calculate the cycle in
which i is
cnt++;
int j=i;
do{
vis[j]=1;
j=lab[j];
}while(!vis[j]);
}
return cnt; //return the number of cycles for the
current permutation
}
void work(){ // calculate the number of different forms for
n beads
if(!n){
printf("0\b");
return;
}
int64 ans=0;
for(int i=0;i<n;i++){ // rotations and reflections
for(int j=1;j<=n;j++) lab[j]=(j+i)%n+1; // The
i-th times, a rotation
ans+=qpow(3,getloop()); // the number of
colorings with 3 colors
for(int j=1;j<=n/2;j++)swap(lab[j],lab[n+1-j]);
// The i-th times, a reflection
ans+=qpow(3,getloop()); // the number of
colorings with 3 colors
194 ◾ Algorithm Design Practice for Collegiate Programming
}
ans/=(n*2); // the number of different forms
printf("%lld\n",ans);
}
int main(){
while(~scanf("%d",&n)&&~n)work(); //Input n,
calculate and output
return 0;
}
Input
The first line of the input file contains n and m (1≤n, m≤20).
Practice for Combinatorics ◾ 195
Output
Output the number of routes that Eisiem transport companies can organize.
2 2 6
2 3 13
Source: Petrozavodsk Summer Trainings 2003, 2003-08-23
(Andrew Stankevich’s Contest #2)
IDs for Online Judges: ZOJ 2344, SGU 208
Analysis
In the rectangular black rubber sheet, squares are numbered 1... n×m from top to
down, and from left to right. For the rectangle, there are n×m classes of permuta-
tions, where the case that every square is moved left i squares circularly, and is
moved down j squares circularly, is regarded as one class of permutations, 0≤i≤n−1,
0≤j≤m−1.
A class of permutations can also be classified into following permutations.
Because the upper limit for N and M is 20, the number of routes may be out of
the range for integers. Calculation of high-precision numbers should be used. In
order to improve the time complexity, the offline method is also used.
Program
# include <cstdio>
# include <cstring>
# include <iostream>
# include <algorithm>
using namespace std;
struct BIGNUM{ // BIGNUM is used for calculation of high-
precision numbers
int s[200]; //high-precision number: s[] whose length is l
int l;
}ans,two[405]; // the number of routes Eisiem can organize
is ans; two[i] is 2i
inline BIGNUM operator*(BIGNUM a,int b){ //a←a×b, where a
is a high-precision number, and b is an integer
for(int i=0;i<a.l;i++)a.s[i]*=b;
for(int i=0;i<a.l;i++){
a.s[i+1]+=a.s[i]/10;
a.s[i]%=10;
}
while(a.s[a.l]){ //carry
a.s[a.l+1]+=a.s[a.l]/10;
a.s[a.l]%=10;
a.l++;
}
return a; //return a*b
}
inline BIGNUM operator+(BIGNUM a,BIGNUM b){ //a←a+b, where
a and b are high-precision numbers
a.l=max(a.l,b.l);
for(int i=0;i< a.l;i++)a.s[i]+=b.s[i];
for(int i=0;i< a.l;i++){
a.s[i+1]+=a.s[i]/10;
a.s[i]%=10;
}
while(a.s[a.l]){ //carry
a.s[a.l+1]+=a.s[a.l]/10;
a.s[a.l]%=10;
a.l++;
}
Practice for Combinatorics ◾ 197
int x=(k%n+i)%n,y=(k/n+j)%m;
p[0][k]=y*n+x; // Rotation by 0°
p[1][k]=(m-1-y)*n+(n-1-x); // Rotation by 180°
if(n==m){ //Square, Rotation by 90° and 270°
p[2][k]=(m-1-x)*n+y;p[3][k]=x*n+(n-1-y); }
}
div+=2; //accumulation
ans=ans+two[circle(0)]; //accumulation for the
number of circles for Rotation by 0°
ans=ans+two[circle(1)]; // accumulation for the
number of circles for Rotation by 180°
if(n==m){ //Square
div+=2;
ans=ans+two[circle(2)]; // accumulation for the
number of circles for Rotation by 90°
ans=ans+two[circle(3)]; // accumulation for the
number of circles for Rotation by 270°
}
}
ans=ans/div;
print(ans); //Output the result
}
int main(){
cal_two();
while(~scanf("%d %d",&n,&m)){ //Input test cases
if(n<m)swap(n,m);
nm=n*m; //number of squares
work(); // calculate and output the number of routes
Eisiem can organize
}
return 0;
}
4.4.3 Color
Beads of n colors are connected together into a circular necklace of n beads (n
≤1000000000). Your job is to calculate how many different types of the necklaces
can be produced. You should know that the necklace might not use up all the N
colors, and the repetitions that are produced by rotation around the center of the
circular necklace are all neglected.
You only need to output the answer module as a given number p.
Input
The first line of the input is an integer x (x≤3500) representing the number of test
cases. The following x lines each contains two numbers n and P (1≤n≤1000000000,
1≤p≤30000), representing a test case.
Practice for Combinatorics ◾ 199
Output
For each test case, output one line containing the answer.
5 1
1 30000 3
2 30000 11
3 30000 70
4 30000 629
5 30000
Source: POJ Monthly, Lou Tiancheng
ID for Online Judge: POJ 2154
Analysis
Method 1: Using the Pólya Counting Formula
Method 1 is analyzing each rotation, calculating the number of cycles, and
using the Pólya Counting Formula to calculate the number of nonequivalent
classes. For each rotation s, ai=a(i+k×s)%n, where ai is the i-th bead, and these beads
are in a cycle. Multiples of s mod n are 0, d, 2×d, …, n−d, where d=GCD(n, s). The
n
number of cycles is = d . Therefore, the number of different kinds of the necklace
n
d
n −1
ans =
1
n ∑n
i =0
GCD ( n .i )
.
The time complexity is O(n×log2n). Because the range of n is too large, optimi-
zation should be done.
Method 2: Euler Phi-Function φ(n)
i
The length of each cycle is enumerated. For all i such that GCD(i, n)=k,
k
n n n
and are relative prime, and ϕ numbers and are relative prime (ϕ is Euler
k k k
Phi-Function). The number of different kinds of the necklace is calculated as
ans =
1
n ∑ n
ϕ × np =
p
p|n
n
p ∑
ϕ × n p −1.
p|n
200 ◾ Algorithm Design Practice for Collegiate Programming
The time complexity for enumerating p is O ( n ). And the time complexity for
calculating the Euler Phi-Function is O ( n ). The time complexity for method 2
3
is O (n ).
4
Program
# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <string>
# include <cmath>
# include <algorithm>
using namespace std;
typedef long long int64;
bool np[50000]; //Sieve
int prime[50000],pn,lim=50000; //Prime list prime[], its
length pn, its upper limit lim
int n,p;
void pp(){ //calculate prime list prime[] in the interval
[2, lim−1]
np[0]=np[1]=1;
for(int i=2;i<lim;i++){
if(np[i]) continue;
prime[pn++]=i;
for(int j=i*2;j<lim;j+=i)np[j]=1;
}
}
int phi(int n){ // Euler Phi-Function ϕ(n)%p
int ans=n;
for(int i=0;i<pn&&prime[i]*prime[i]<=n;i++){ // Each
factor for n
if(n%prime[i]!=0)continue;
ans-=ans/prime[i];
do{
n/=prime[i];
}while(n%prime[i]==0);
}
if(n!=1)ans-=ans/n;
return ans%p;
}
int exp_m(int64 a,int b){ //calculate (ab) %p
int ans=1,x=a%p;
Practice for Combinatorics ◾ 201
while(b){
if(b&1)ans=(ans*x)%p;
x=(x*x)%p;
b>>=1;
}
return ans; // return (ab)%p
}
int main(){
int casen;
pp(); //Calculating prime list
scanf("%d",&casen); //number of test cases
while(casen--){
int ans=0,i;
scanf("%d %d",&n,&p); //Input a test case
for(i=1;i*i<n;i++){ //enumerate each factor i
n
−1
∑
n
for n, ans = ϕ * ni−1 + ϕ(i)* n i %p
i
i2 < n,n%i= 0
if(n%i!=0)continue;
ans+=(((phi(n/i)%p)*exp_m(n,i-1))+((phi(i)%p)*
exp_m(n,n/i-1)));
ans%=p;
}
if(i*i==n){ //if n==i2, then ans =(ans+ ϕ(i)* ni-1)%p
ans+=((phi(i)%p)*exp_m(n,i-1));
ans%=p; // the answer module a given number p
}
printf("%d\n",ans); // output the answer
}
return 0;
}
4.5 Problems
4.5.1 Common Permutation
Given two strings of lowercase letters, a and b, print the longest string x of lower-
case letters such that there is a permutation of x that is a subsequence of a and there
is a permutation of x that is a subsequence of b.
Input
The input file contains several lines of input. Consecutive two lines make a set of
input. That means, in the input file, lines 1 and 2 are a set of input, lines 3 and 4 are
a set of input, and so on. The first line of a pair contains a and the second contains b.
Each string is on a separate line and consists of at most 1000 lowercase letters.
202 ◾ Algorithm Design Practice for Collegiate Programming
Output
For each set of input, output a line containing x. If several x satisfy the criteria above,
choose the first one in alphabetical order.
pretty e
women nw
walking et
down
the
street
Source: World Finals Warm-up Contest, University of Alberta Local Contest
ID for Online Judge: UVA 10252
Hint
Given two strings of lowercase letters, a and b, the problem requires you to output
the longest string x in alphabetical order such that there is a permutation of x that
is a subsequence of a and there is a permutation of x that is a subsequence of b. The
algorithm is as follows:
Suppose S1=a1a2 ...al a , and S2 =b1b2 ...blb .
First, frequencies for each letter in S1 and S2 are calculated. Let c1[i] be the fre-
quency for the i-th letter in S1, c2[i] be the frequency for the i-th letter in S2, where
1≤i≤26, the first letter is “a”, the second letter is “b”, …, and the 26th letter is “z”.
Second, the common permutation for S1 and S2 is calculated. For each i
(1≤i≤26), if the i-th letter appears in S1 and S2 ((c1[i]≠0)&&(c2[i]≠0)), the letter
appears k (=min{c1[i], c2[i]}) times in the common permutation.
4.5.2 Anagram
You are to write a program that has to generate all possible words from a given set
of letters.
Example: Given the word “abc”, your program should—by exploring all differ-
ent combination of the three letters—output the words “abc”, “acb”, “bac”, “bca”,
“cab”, and “cba”.
In the word taken from the input file, some letters may appear more than once.
For a given word, your program should not produce the same word more than once,
and the words should be output in alphabetically ascending order.
Practice for Combinatorics ◾ 203
Input
The input file consists of several words. The first line contains a number giving the
number of words to follow. Each following line contains one word. A word consists
of uppercase or lowercase letters from A to Z. Uppercase and lowercase letters are
to be considered different.
Output
For each word in the input file, the output file should contain all different words
that can be generated with the letters of the given word. The words generated from
the same input word should be output in alphabetically ascending order. An upper-
case letter goes before the corresponding lowercase letter.
3 Aab
aAb Aba
abc aAb
acba abA
bAa
baA
abc
acb
bac
bca
cab
cba
aabc
aacb
abac
abca
acab
acba
baac
baca
bcaa
caab
caba
cbaa
Source: ACM Southwestern European Regional Contest 1995
IDs for Online Judges: POJ 1256, UVA 195
204 ◾ Algorithm Design Practice for Collegiate Programming
Hint
There are different strategies to solve this problem. The most efficient strategy is
sorting the letters in the input word first, and then directly producing all possible
anagrams without duplicates. A less efficient way is to first sort the letters in the
input word, and then produce all possible permutations (correctly sorted) and elim-
inate all duplicates on the fly without storing more than one word. A completely
inefficient way is to first produce all permutations and store them in memory, and
then sort them and eliminate duplicates as the last step.
Input
Each line in the input will contain two positive integers a(0<a≤20000) and
b(0<b≤20000). Input is terminated by a line where both a and b are zero. This case
should not be processed. You will need to process at most 1200 sets of inputs.
1 2
Top row
a c
Bottom row
1 2 3
Figure 4.14
Practice for Combinatorics ◾ 205
Output
For each line of input, print in a line the serial of the output, followed by the value
of P(a, b). Look at the output for sample input for details. You can assume that the
output for the test cases will fit in 64-bit signed integers.
2 2 Case 1: 1
2 3 Case 2: 3
3 3 Case 3: 9
0 0
Source: Bangladesh National Computer Programming Contest, 2004
ID for Online Judge: UVA 10790
Hint
Line segments connecting two dots on the top row and dots on the bottom
row will produce one intersection point. Based on the multiplication principle,
P(a, b)=C(a, 2)×C(b, 2).
4.5.4 Permutations
We remind you that the permutation of some final set is a one-to-one mapping of
the set onto itself. Less formally, that is a way to reorder elements of the set. For
example, one can define a permutation of the set {1,2,3,4,5} as follows:
1 2 3 4 5
P (n ) =
4 1 5 2 3
1 2 3 4 5
P ( P (n )) =
2 4 3 1 5
It is clear that for every k the following relation is satisfied: (EN)k =EN. The fol-
lowing less trivial statement is correct (we won’t prove it here, but you may prove it
to yourself incidentally):
Let P(n) be some permutation of an N elements set. Then there exists a natural
number k, so that P k =EN.
The least natural k such that P k =EN is called an order of the permutation P.
The problem that your program should solve is now formulated in a very simple
manner: “Given a permutation, find its order.”
Input
In the first line of the standard input, only a natural number N (1≤N≤1000) is con-
tained, that is, a number of elements in the set that is rearranged by this permuta-
tion. In the second line, there are N natural numbers of the range from 1 up to N,
separated by a space, that define a permutation—the numbers P(1), P(2),…, P(N).
Output
You should write only a natural number to the standard output, that is an order of
the permutation. You may consider that an answer shouldn’t exceed 109.
5 6
4 1 5 2 3
8 1
1 2 3 4 5 6 7 8
Source: Ural State University Internal Contest October 2000 Junior Session
ID for Online Judge: POJ 2369
Hint
For the permutation P(1), P(2),…, P(N), the numbers of elements in each cycle are
calculated. Obviously, the least natural k such that Pk =EN is the Least Common
Multiple (LCM) for these numbers.
Practice for Combinatorics ◾ 207
4.5.5 Coupons
Coupons in cereal boxes are numbered 1 to n, and a set of one of each is required
for a prize (a cereal box, of course). With one coupon per box, how many boxes on
average are required to make a complete set of n coupons?
Input
Input consists of a sequence of lines each containing a single positive integer n,
1≤n≤33, giving the size of the set of coupons. Input is terminated by end of file.
Output
For each input line, output the average number of boxes required to collect the
complete set of n coupons. If the answer is an integer number, output the number. If
the answer is not an integer, then output the integer part of the answer, followed by
a space, and then by the proper fraction in the format shown below. The fractional
part should be irreducible. There should be no trailing spaces in any line of output.
2 3
5 5
17 11 --
12
340463
58 ------
720720
Source: Math Lovers’ Contest, Source: University of Alberta Local Contest
ID for Online Judge: UVA 10288
Hint
There are n coupons. Suppose that k coupons are collected, and EK boxes are bought.
n−k
The probability of getting a coupon in the next time is . And the probability
n
n−k k
of getting two coupons two times is × ,, and so on. Therefore, there is a
formula: n n
∞ i
E k +1 = E k +
n−k
n ∑
i =0
k
(i + 1) .
n
208 ◾ Algorithm Design Practice for Collegiate Programming
The formula ∑ kx
k =0
k
=
x
(1 − x )2
(taking the derivative of two sides of the equa-
∞ ∞ i
tion ∑
k =0
x =
k 1
(1 − x )
) is used to calculate the sum of
n−k
n ∑
i =0
k
(i + 1) in the
n
n
above formula. E k +1 = E k +
n
n−k
. Therefore, E n = n × ∑ 1i .
i =1
Figure 4.15
Figure 4.16
Practice for Combinatorics ◾ 209
Input
Input consists of two lines, and the first line is number n (2≤n≤210, n even). The
number n is the size of images. One image is represented internally by an n×n pixel
matrix (a ij ), where i is the row number and j is the column number. The pixel at the
upper-left corner is at row 0 and column 0.
The second line is a non-empty list of at most 32 words, separated by spaces.
Valid words are the keywords id, rot, sym, bhsym, bvsym, div, and mix, or a keyword
followed by “-”. Each keyword key designates an elementary transform (as defined
by Figure 4.17), and key-designates the inverse of the transform key. For instance,
rot- is the inverse of counterclockwise 90o rotation, that is, clockwise 90o rotation.
Figure 4.17
210 ◾ Algorithm Design Practice for Collegiate Programming
Finally, the list k1, k 2,..., kp designates the compound transform ϕ=k1k 2...kp. For
instance, “bvsym rot-” is the transform that first performs clockwise 90o rotation
and then vertical symmetry on the lower half of the image.
Output
Your program should output a single line whose content is the minimal number
m (m>0) such that ϕm is the identity. You may assume that, for all test input, you
have m <231.
256 8
rot- div rot div
256 63457
bvsym div mix
Source: ACM Southwestern Europe 2005
IDs for Online Judges: POJ 2789, UVA 3510
Hint
The problem statements define several operations on square images. Each of the
operations is some simple permutation of the image’s pixels. The input contains a
sequence of operations. Your program should output the smallest positive K such
that applying the whole sequence of operations K times always yields the original
image.
The sequence of operations defines a (more complicated) permutation of the
image’s pixels. If you split this permutation into cycles, the answer is the LCM of
the cycle lengths.
Input
Each line of the input file contains a single integer n (0<n<1000) denoting the
number of different colors. Input is terminated by a line where the value of n=0.
This line should not be processed.
Output
For each line of input, produce one line of output. This line should contain the
number of different cubes that can be made by using the matching number of
colors.
1 1
2 10
0
Source: 2004 ICPC Regional Contest Warmup 1
ID for Online Judge: UVA 10733
Hint
All six sides of a cube are to be colored with paints. Each side is painted uniformly
with one color. When a selection of n different colors of paint is available, how
many different cubes can you make?
Two cubes are considered different if it is not possible to rotate one cube into a
such position that it appears with the same coloring as the other (see Figure 4.18).
c (back)
b
d
a
(left)
e
(bottom)
Figure 4.18
212 ◾ Algorithm Design Practice for Collegiate Programming
adcbfe (a)(bd)(c)(ef) n4
aecfdb (a)(bedf)(c) n3
afcebd (a)(bfde)(c) n3
badcfe (ab)(cd)(ef) n3
bcdaef (abcd)(e)(f) n3
bedfac (abe)(cdf) n2
bfdeca (abf)(cde) n2
cbadfe (ac)(b)(d)(ef) n4
cdabef (ac)(bd)(e)(f) n4
ceafbd (ac)(be)(df) n3
cfaedb (ac)(bf)(de) n3
dabcef (adcb)(e)(f) n3
dcbafe (ad)(bc)(ef) n3
debfca (adf)(bec) n2
dfbeac (ade)(bfc) n2
eafcbd (aeb)(cfd) n2
ebfdca (aecf)(b)(d) n3
ecfadb (aed)(bcf) n2
edfbac (ae)(bd)(cf) n3
faecdb (afb)(ced) n2
Practice for Combinatorics ◾ 213
fbedac (afce)(b)(d) n3
fceabd (afd)(bce) n2
fdebca (af)(bd)(ce) n3
You can obtain all these permutations by first listing the most important
ones—rotating around the X, Y, and Z axes, and then listing all their possible
combinations.
A fixed point of a permutation is some coloring, such that the permutation
results in a cube, which has the same coloring. If each face of the cube may be
assigned one of n colors, and the permutation has c disjoint cycles, then it has nc
fixed points (the faces of each cycle have to be colored in the same color, there are c
cycles, and n ways to choose colors for each).
By Burnside’s Lemma, the total number of distinct colorings is equal to the
arithmetic mean of the number of fixed points of permutations. That is, the answer
1 6
to the problem is given by (n + 3 × n 4 + 12 × n 3 + 8 × n 2 ).
24
If you have never heard of the Pólya-Burnside theory, there are still some other
methods to solve this problem.
For example, you could’ve guessed that the function, given that the number of
colorings is a polynomial in n; obtain its values for small n by brute force, and use
interpolation to find the polynomial’s coefficients.
Here’s another possible solution. Start by backtracking this subproblem: there
are six available paints, the i-th of which must be used to color exactly 0≤ni≤6 sides
of the cube (of course n1+n2+…+n6 =6); how many colorings are possible? Then use
well-known combinatorics (and probably, dynamic programming) to reduce the
original problem to subproblems of this type.
Chapter 5
215
216 ◾ Algorithm Design Practice for Collegiate Programming
5.1.1 Pass-Muraille
In modern-day magic shows, passing through walls is very popular, in which a magi-
cian performer passes through several walls in a predesigned stage show. The wall-
passer (Pass-Muraille) has a limited wall-passing energy to pass through at most k
walls in each wall-passing show. The walls are placed on a grid-like area. An example
is shown in Figure 5.1, where the land is viewed from above. All the walls have unit
widths, but different lengths. You may assume that no grid cell belongs to two or
more walls. A spectator chooses a column of the grid. Our wall-passer starts from the
upper side of the grid and walks along the entire column, passing through every wall
on his way to get to the lower side of the grid. If he faces more than k walls when he
tries to walk along a column, he would fail and would not present a good show. For
example, in the wall configuration shown in Figure 5.1, a wall-passer with k=3 can
pass from the upper side to the lower side by choosing any column except column 6.
Given a wall-passer with a given energy and a show stage, we want to remove the
minimum number of walls from the stage so that our performer can pass through
all the walls at any column chosen by spectators.
Input
The first line of the input file contains a single integer t (1≤t≤10), the number of test
cases, followed by the input data for each test case. The first line of each test case
contains two integers n (1≤n≤100), the number of walls, and k (0≤k≤100), the max-
imum number of walls that the wall-passer can pass through, respectively. After the
first line, there are n lines each containing two (x, y) pairs representing coordinates
of the two endpoints of a wall. Coordinates are non-negative integers less than or
equal to 100. The upper-left of the grid is assumed to have coordinates (0, 0). The
second sample test case below corresponds to the land given in Figure 5.1.
0 1 2 3 4 5 6 7 8
0
1
2
3
4
5
6
7
8
Shaded cells represent the walls
Figure 5.1
Practice for Greedy Algorithms ◾ 217
Output
There should be one line per test case containing an integer number which is the
minimum number of walls to be removed, such that the wall-passer can pass
through walls starting from any column on the upper side.
2 1
3 1 1
2 0 4 0
0 1 1 1
1 2 2 2
7 3
0 0 3 0
6 1 8 1
2 3 6 3
4 4 6 4
0 5 1 5
5 6 7 6
1 7 3 7
Source: ACM Tehran 2002 Preliminary
IDs for Online Judges: POJ 1230, ZOJ 1375
Hint
Walls are parallel to X.
Analysis
All columns are scanned from left to right. Removing the minimum number of
walls from the stage must guarantee removing the minimum number of walls in
scanned columns. Therefore, the optimal solution to the problem consists of its
optimal solutions to subproblems. The key to the problem is its greedy choice.
Suppose there are D walls in the current column. If D≤K, we needn’t remove
any wall; and if D>K, D−K walls must be removed. The greedy choice is as fol-
lows. For walls in the current column, the longest D−K walls in unscanned col-
umns are removed. Obviously, the greedy choice removes a minimum number
of walls.
218 ◾ Algorithm Design Practice for Collegiate Programming
Program
#include<iostream>
using namespace std;
int t,n,k,x,y,x1,y2,max_x,max_y,sum_s=0; //t: number of
test cases; n: number of walls; k: at most k walls can be
passed through; x,y,x1,y2: Coordinate; max_x,max_y: maximal
row and column Coordinate; sum_s: the minimum number of
removed walls
int map[105][105];
int main()
{
scanf("%d",&t); // number of test cases
while(t--) // all test cases are processed
{
memset(map,0,sizeof(map));
max_x=0; //Initialization
max_y=0;
sum_s=0;
scanf("%d %d",&n,&k);
for (int i=1;i<=n;i++)
{
scanf("%d %d %d %d",&x,&y,&x1,&y2);
if (x>max_x)max_x=x;
if (x1>max_x)max_x=x1;
if(y>max_y)max_y=y;
if (x<x1)
{
for (int j=x;j<=x1;j++) map[j][y]=i;
}
else
{
for (int j=x1;j<=x;j++) map[j][y]=i;
}
}
for (int i=0;i<=max_x;i++) //scan from left to right
{
int tem=0; //calculate the number of walls
in the i-th column
for (int j=0;j<=max_y;j++) if (map[i][j]>0)
tem++;
int offset=tem-k;
if (offset>0) // some walls are removed
{
sum_s+=offset;
Practice for Greedy Algorithms ◾ 219
while(offset--)
{
int max_s=0,max_bh;
for (int k=0;k<=max_y;k++) //search
{
if (map[i][k]>0)
//calculate length of wall in unscanned columns
{
int tem_s=0;
for (int z=i+1;z<=max_x;
z++)
if (map[z][k]==map[i][k])
tem_s++;
else break;
if (max_s<tem_s) //record
{
max_s=tem_s; max_bh=k;
}
}
}
for (int a=i;a<=i+max_s;a++) map[a]
[max_bh]=0; // some walls are removed
}
}
}
printf("%d\n",sum_s); //output the result
}
return 0;
}
92 –200 95 92 95 92 95
+2
0
0
83 –200 87 83 87 83 87
+2
00
0
71 –200 74 71 74 71 74
–20
Figure 5.2
Tian Ji was not happy about that, until he met Sun Bin,
one of the most famous generals in Chinese history. Using a
little trick that he learned from Sun, Tian Ji brought home
two hundred silver dollars and such a grace in the next match.
It was a rather simple trick (Figure 5.2). Using his regular class horse race against
the super class from the king, they will certainly lose that round. But then his plus
beat the king’s regular, and his super beat the king’s plus. What a simple trick. And
what do you think of Tian Ji, the high-ranked official in China?
Wherever Tian Ji lives nowadays, he will certainly laugh at himself. Even
more, if he were sitting in the ACM contest right now, he may discover that the
horse racing problem can be simply viewed as finding the maximum matching
in a bipartite graph. Draw Tian’s horses on one side, and the king’s horses on the
other. Whenever one of Tian’s horses can beat one from the king, we draw an
edge between them, meaning we wish to establish this pair. Then, the problem
of winning as many rounds as possible is just to find the maximum matching in
this graph. If there are ties, the problem becomes more complicated; he needs to
assign weights 0, 1, or −1 to all the possible edges, and find a maximum weighted
perfect matching.
However, the horse racing problem is a very special case of bipartite matching.
The graph is decided by the speed of the horses—a vertex of higher speed always
beats a vertex of lower speed. In this case, the weighted bipartite matching algo-
rithm is too advanced a tool to deal with the problem.
In this problem, you are asked to write a program to solve this special case of
matching problem.
Input
The input consists of up to 50 test cases. Each case starts with a positive integer
n (n≤1000) on the first line, which is the number of horses on each side. The next n
integers on the second line are the speeds of Tian’s horses. Then the next n integers
on the third line are the speeds of the king’s horses. The input ends with a line that
has a single “0” after the last test case.
Practice for Greedy Algorithms ◾ 221
Output
For each input case, output a line containing a single number, which is the maxi-
mum money Tian Ji will get, in silver dollars.
3 200
92 83 71 0
95 87 74 0
2
20 20
20 20
2
20 19
22 18
0
Source: ACM Shanghai 2004
IDs for Online Judges: POJ 2287, ZOJ 2397 UVA 3266
Analysis
The problem can be solved by several different methods. Maximum matching in
a bipartite graph or dynamic programming can be used to solve the problem, but
using a greedy algorithm to solve the problem is simple and efficient. The greedy
algorithm is as follows:
First, the speeds of Tian’s horses and the speeds of the king’s horses are sorted
in ascending order respectively. Suppose the sequence for speeds of Tian’s current
horses in ascending order is A=a1…an; and the sequence for the speeds of the king’s
current horses are sorted in ascending order is B=b1…bn.
Second, greedy choices are as follows:
1. If Tian’s current slowest horse is faster than the king’s current slowest horse, that
is, a1>b1; then Tian’s current slowest horse races against the king’s current slow-
est horse, that is, a1 is compared with b1. Because b1 is less than any elements in
A and the king’s current slowest horse can be defeated by any Tian’s remainder
horse, the king’s current slowest horse is defeated by Tian’s current slowest horse.
2. If Tian’s current slowest horse is slower than the king’s current slowest horse,
that is, a1<b1; then Tian’s current slowest horse races against the king’s current
fastest horse, that is, a1 is compared with bn. Because a1 is less than any elements
in B and Tian’s current slowest horse can be defeated by any king’s remainder
horse, Tian’s current slowest horse is defeated by the king’s current fastest horse.
222 ◾ Algorithm Design Practice for Collegiate Programming
3. If Tian’s current fastest horse is faster than the king’s current fastest horse,
that is, an>bn; then Tian’s current fastest horse races against the king’s current
fastest horse, that is, an is compared with bn. Because an is larger than any ele-
ments in B and Tian’s current fastest horse can defeat any king’s remainder
horse, Tian’s current fastest horse defeats the king’s current fastest horse.
4. If Tian’s current fastest horse is slower than the king’s current fastest horse,
that is, an<bn; then Tian’s current slowest horse races against the king’s cur-
rent fastest horse, that is, a1 is compared with bn. Because bn is larger than
any elements in A and the king’s current fastest horse can defeat any Tian’s
remainder horse, the king’s current fastest horse defeats Tian’s current slow-
est horse.
5. If (a1==b1) and (an>bn), then it is suitable that Tian’s current fastest horse
races against the king’s current fastest horse, that is, an is compared with bn.
6. If (an==bn), then there exists an optimal solution that a1 is compared with bn.
The above process repeats until the horse racing ends. Tian’s current fastest
or slowest horse races against the king’s current fastest or slowest horse each time
based on the above greedy choices. Optimal solutions to subproblems constitute the
global optimal solution to the problem.
Program
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a[1010],b[1010]; //Speeds of Tian’s horses and the
king’s horses
int main()
{
int n;
while(scanf("%d",&n),n) //number of Tian’s horses (the
king’s horses)
{
for(int i=1; i<=n; i++) scanf("%d",&a[i]); // Input
speeds of Tian’s horses
for(int i=1; i<=n; i++) scanf("%d",&b[i]); // Input
speeds of the king’s horses
sort(a+1,a+1+n); //Sorting speeds in ascending
order
sort(b+1,b+1+n);
int tl=1,tr=n,ql=1,qr=n; //Initialization
int sum=0;
Practice for Greedy Algorithms ◾ 223
For each day of delay before starting to work for the i-th job, the shoemaker must
pay a fine of Si (1≤Si≤10000) cents. Your task is to help the shoemaker, by writing
a program to find the sequence of jobs with minimal total fine.
Input
The input begins with a single positive integer on a line by itself, indicating the
number of the cases following, each of them as described below. This line is fol-
lowed by a blank line, and there is also a blank line between two consecutive
inputs.
The first line of input contains an integer N (1≤N≤1000). The next N lines each
contain two numbers: the time and the fine of each task in order.
Output
For each test case, the output must follow the description below. The outputs of two
consecutive cases will be separated by a blank line.
Your program should print the sequence of jobs with minimal fine. Each job
should be represented by its number in input. All integers should be placed on only
one output line and separated by one space. If multiple solutions are possible, print
the first lexicographically.
1 2 1 3 4
4
3 4
1 1000
2 2
5 5
Source: Second Programming Contest of Alex Gevak, 2000
ID for Online Judge: UVA 10026
Analysis
“For each day of delay before starting to work for the ith job, the shoemaker must
pay a fine of Si cents” means “For each day of delay after starting to work for the ith
job, the shoemaker must pay a fine of Si/Ti cents”. Si/Ti is the measurement of influ-
ence for the ith job, 1≤i≤n. Therefore, in order to pay a minimal fine, the job whose
Practice for Greedy Algorithms ◾ 225
Program
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxN=1010; // the upper limit of the number of
jobs
struct job
{
double a; // measurement of influence for the job
int num; // the number of a job
} p[maxN]; // the sequence of jobs with minimal fine
int n;
void init()
{
double a1,a2;
scanf("%d",&n); // n jobs
for (int i=1;i<=n;i++) // the time and fine of each task
{
scanf("%lf%lf",&a1,&a2);
p[i].a=a2/a1;p[i].num=i; // Calculate Si/Ti, and record
the number
}
}
bool cmp(job x,job y) // sort two jobs using their
measurement of influence as the first key (in ascending
order), and numbers of jobs as the second key (in descending
order)
{
if ((x.a>y.a)||((x.a==y.a)&&(x.num<y.num))) return true;
return false;
}
void work()
226 ◾ Algorithm Design Practice for Collegiate Programming
{
sort(p+1,p+n+1,cmp); // sort n jobs using their
measurement of influence as the first key (in ascending
order), and numbers of jobs as the second key (in descending
order)
for (int i=1;i<n;i++) printf("%d ",p[i].num); // Output
the result
printf("%d\n",p[n].num);
}
int main()
{
int t;
scanf("%d",&t); //the number of test cases
for (int i=1;i<=t;i++) // deal with each test case
{
if (i>1) printf("\n");
init();
work();
}
return 0;
}
I hope you have already understood your mission, to add a set of integers so that
the cost is minimal.
Input
Each test case will start with a positive number, N (2≤N≤5000) followed by N posi-
tive integers (all are less than 100000). Input is terminated by a case where the value
of N is zero. This case should not be processed.
Practice for Greedy Algorithms ◾ 227
Output
For each case, print the minimum total cost of addition in a single line.
3 9
1 2 3 19
4
1 2 3 4
0
Source: UVa Regional Warmup Contest 2005
ID for Online Judge: UVA 10954
Analysis
Initially there is a set of n positive numbers. Each time, two positive numbers are
deleted from the set, and the sum of the two numbers is added into the set. The
process repeats n−1 times. The final sum is the total cost of addition. The problem
requires you to calculate the minimum total cost of the addition.
Obviously, in order to get the minimum total cost of addition, the greedy choice
is to select two minimal positive numbers each time. Therefore a min heap is suitable
to represent the set.
Program
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxN=5010; //the upper limit of the size of the set
int n,a[maxN]; // n: the size of the heap, a[]: min heap
void sift(int i) // the subtree with root i is adjusted as
a min heap
{
228 ◾ Algorithm Design Practice for Collegiate Programming
a[0]=a[i];
int k=i<<1;
while (k<=n)
{
if ((k<n)&&(a[k]>a[k+1])) k++;
if (a[0]>a[k]) { a[i]=a[k];i=k;k=i<<1;} else k=n+1;
}
a[i]=a[0];
}
void work() //Calculate and output the result
{
for (int i=n >> 1;i;i--) sift(i); // set up a min heap
long long ans=0;
while (n!=1)
{
swap(a[1],a[n--]);
sift(1); // adjust the heap
a[1]+=a[n+1];
ans+=a[1];
sift(1); // adjust the heap
}
cout << ans << endl; //Output the result
}
int main()
{
while (scanf("%d",&n),n)
{
for (int i=1;i<=n;i++) scanf("%d",&a[i]); // Input n
positive numbers
work(); // calculate and output the minimum total cost
of addition
}
return 0;
}
1. The setup time for the first wooden stick is one minute.
2. Right after processing a stick of length l and weight w, the machine will
need no setup time for a stick of length l ' and weight w' if l≤l' and w≤w'.
Otherwise, it will need one minute for setup.
Practice for Greedy Algorithms ◾ 229
You are to find the minimum setup time to process a given pile of n wooden
sticks. For example, if you have five sticks whose pairs of length and weight are (9 , 4) ,
(2 , 5) , (1 , 2) , (5 , 3) , and (4 , 1) , then the minimum setup time should be two
minutes since there is a sequence of pairs (4 , 1) , (5 , 3) , (9 , 4) , (1 , 2) , (2 , 5).
Input
The input consists of T test cases. The number of test cases (T ) is given in the first
line of the input file. Each test case consists of two lines: The first line has an integer
n, 1≤n≤5000, that represents the number of wooden sticks in the test case, and the
second line contains 2n positive integers l1, w1, l2, w2,……, ln, wn, each of magni-
tude at most 10000, where li and wi are the length and weight of the ith wooden
stick, respectively. The 2n integers are delimited by one or more spaces.
Output
The output should contain the minimum setup time in minutes, one per line.
3 2
5 1
4 9 5 2 2 1 3 5 1 4 3
3
2 2 1 1 2 2
3
1 3 2 2 3 1
Source: ACM Taejon 2001
IDs for Online Judges: POJ 1065, ZOJ 1025, UVA 2322
Analysis
Right after processing a stick of length l and weight w, the machine will need no
setup time for a stick of length l' and weight w' if l≤l' and w≤w'. Otherwise, it will
need one minute for setup. In order to reduce the setup time, the strategy for greedy
choice is as follows:
For unprocessed sticks, the stick with minimal length is selected first. If there
are more than one stick with minimal length, the stick with minimal weight is
selected.
230 ◾ Algorithm Design Practice for Collegiate Programming
First, all sticks are sorted. A stick is represented as (l, w), where l is its length,
and w is its weight. Sticks are sorted using l as the first key and w as the second key.
That is, (l1,w1)<(l2,w2), if l1<l2||(l1==l2&&w1<w2).
After sorting sticks, the greedy choice is processed as follows:
Initially, setup time c=0, and stick 0 is as the first unprocessed stick in the
sequence. Then the following steps repeat.
Step 1: In the sequence, all unprocessed sticks after stick 0 which can be pro-
cessed without setup time are set as processed. That is to say, the machine will
need no setup time for these sticks, if stick 0 is processed.
Step 2: Setup time c++.
Step 3: Search the first unprocessed stick in the sequence. If there is no unpro-
cessed stick, then output the minimum setup time; else set the first unprocessed
stick as stick 0, and return to Step 1.
Program
#include <iostream>
using namespace std;
const int N = 5000;
struct node{ // Struct of stick
node& operator=(node &n){
l=n.l, w=n.w, isUsed=n.isUsed; //the length,
weight, flag that is processed or not for stick n
return *this;
}
bool operator>(node &n){ //compare sticks
return l>n.l || (l==n.l && w>n.w);
}
void swap(node &n){ //exchange sticks
node tmp=*this;
*this=n;
n=tmp;
}
int l, w;
bool isUsed;
}A[N]; //sequence of sticks A[ ]
int main()
{
int t, n, i, j, k;
cin >> t; //number of test cases
for(i=0;i<t;i++){ // test cases are processed one by one
cin >> n;
Practice for Greedy Algorithms ◾ 231
Input
The input consists of several test cases. The first line of each case contains two
integers n (1≤n≤1000) and d, where n is the number of islands in the sea and d is
the distance of coverage of the radar installation. This is followed by n lines, each
containing two integers representing the coordinate of the position of each island.
Then a blank line follows to separate the cases. The input is terminated by a line
containing a pair of zeros.
Output
For each test case, output one line consisting of the test case number followed by
the minimal number of radar installations needed. “−1” installation means no solu-
tion for that case.
3 2 Case 1: 2
1 2 Case 2: 1
-3 1
2 1
1 2
0 2
0 0
Source: ACM Beijing 2002
IDs for Online Judge: POJ 1328, ZOJ 1360, UVA 2519
Analysis
Each small island is represented as a segment on the coast. If a radar locates on the
segment, the island can be covered by the radar. Suppose the Cartesian coordinate
for the island is (x, y). If a radar locates on the coast from (x−h, 0) to (x+h, 0), where
h = d 2 − y 2 , the island can be covered. Therefore, the island is represented as a
segment from (x−h, 0) to (x+h, 0). It can be shown as in Figure 5.3.
Suppose there are n islands. First, n islands are represented as n segments.
Second, right endpoints are as the first key (in ascending order), left endpoints are
as the second key (in ascending order), and the n segments are sorted. Finally, all
sorted segments are scanned one by one. If the current segment isn’t covered by a
radar, a radar locates at the right endpoint for the segment.
Practice for Greedy Algorithms ◾ 233
(x – h, 0) (x, 0) (x + h, 0)
d d h = d2 – y2
island (x, y)
Figure 5.3
Program
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 1010; //the upper limit of number of segments
struct tt {
double l,r; // left, right pointer
} p[maxn]; // the sequence of segments, where the i-th
island is represented as segment [p[i].l, p[i].r]
int n,d; //n: number of islands, any radar covers d distance
bool flag;
void init( ) { //Input positions of islands, and calculate
corresponding segments
flag = true;
int i;
double x,y;
for(i = 1 ; i <= n ; ++i){
scanf("%lf%lf",&x,&y);
if(d < y){ // if d<y, no solution
flag = false;
}
double h = sqrt(d*d - y*y);
p[i].l = x - h;
p[i].r = x + h;
}
}
bool cmp (tt a, tt b){ //compare segment a and segment b
if( b.r - a.r > 10e-7){
return true;
}
if(abs(a.r - b.r) < 10e-7 && ( b.l - a.l > 10e-7)) {
234 ◾ Algorithm Design Practice for Collegiate Programming
return true;
}
return false;
}
void work( ) { //Calculate and output the minimal number of
radar installations needed
if( d == -1){ printf("-1\n"); return ; }
sort(p+1,p+1+n,cmp); // Sorting segments
int ans = 0; // Initialize the minimal number of radar
installations needed
double last = -10000.0; //Initialize the position of radar
installation
int i;
for(i = 1 ; i <= n ; ++i){ // search segments one by one
if(p[i].l <= last){ //there is a radar on the segment
if(p[i].r <= last){
last = p[i].r;
}
continue;
}
ans++; // a radar is installed on the right endpoint
last = p[i].r;
}
printf("%d\n",ans); //Output
}
int main(){
int counter = 1;
while(scanf("%d%d",&n,&d)!=EOF,n||d){ // Input test cases
printf("Case %d: ",counter++); // the number of test cases
init();
if(!flag){
printf("-1\n");
}else{
work();
}
}
return 0;
}
In this section, practices for greedy algorithms used with other methods to solve
P-Problems are shown.
Input
The input consists of several test cases. The first line of each case contains two
integers N and R (1≤N≤1000, 1≤R≤N ), where N is the number of nodes in the tree
and R is the node number of the root node. The second line contains N integers,
the i-th of which is Ci (1≤Ci≤500), the coloring cost factor of node i. Each of the
next N−1 lines contains two space-separated node numbers V1 and V2, which are
the endpoints of an edge in the tree, denoting that V1 is the father node of V2. No
edge will be listed twice, and all edges will be listed.
1 C1 = 1
C2 = 2 2 3 C3 = 1
C4 = 2 4 5 C5 = 4
Figure 5.4
236 ◾ Algorithm Design Practice for Collegiate Programming
A test case of N=0 and R=0 indicates the end of input, and should not be
processed.
Output
For each test case, output a line containing the minimum total coloring cost
required for Bob to color all the nodes.
5 1 33
1 2 1 2 4
1 2
1 3
2 4
3 5
0 0
Source: ACM Beijing 2004
IDs for Online Judge: POJ 2054, ZOJ 2215, UVA 3138
Analysis
For each node, the coloring cost is based on its coloring cost factor and the time at
which Bob finishes coloring it. The coloring cost factor for each node is given. The
key to the problem is determining the sequence coloring nodes.
Because Bob is allowed to color a node only when the node’s father has been
colored, the pointer pointing to its father for each node should be set up when edges
are input. A DFS is used to calculate pointers pointing to its father for each node.
The sequence coloring nodes can be regarded as a merger process. For a father-
child relationship (k, x), node x can be colored only after its father k is colored.
If there are several children, the sequence coloring nodes should be determined.
Suppose now[i] is the average for coloring cost factors for nodes which are
merged into node i, and cnt[i] is the number of nodes which are merged into node i.
Initially now[i]= the coloring cost factor for node i, cnt[i]=1(1≤i≤n). After node x
now[k ] × cnt [k ] + now[ x ] × cnt [ x ]
is colored, it is merged into node k, now[k ] = ,
cnt [k ] + cnt [ x ]
and cnt[k]=cnt[k]+cnt[x]. Such a merge process is performed n−1 times. Each time,
the criteria for the merger is selecting a uncolored node whose now value is maxi-
mal. Obviously, it is a greedy strategy. The implementation process is as follows.
Practice for Greedy Algorithms ◾ 237
From the root, based on the coloring sequence, calculating the minimum total
coloring cost required for Bob to color all the nodes.
n
ans = ∑ i × the coloring cost factor for node i in the coloring sequence.
i =1
Program
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxN=1100; // the upper limit for the number of nodes
int root,n,fa[maxN],l[maxN],next[maxN],cnt[maxN],c[maxN],e[maxN]
[maxN];
// root: the root of the tree; n: the number of nodes; fa[ ]:
each node’s father; next[ ]: the coloring sequence, where the
node is colored after node x is colored is node next[x]; cnt[ ]:
the number of merged nodes for each node; c[ ]: coloring cost
factor; e[ ][ ]: the adjacency matrix for the tree
double now[maxN]; //now[ ]: coloring costs for nodes after
merger
void init() // Input coloring cost factors for n nodes and
edges, and construct e[ ][ ]
{
int x,y;
memset(e,0,sizeof(e));
for (int i=1;i<=n;i++) scanf("%d",&c[i]);
for (int i=1;i<n;i++) { scanf("%d%d",&x,&y);e[x][++e[x]
[0]]=y;e[y][++e[y][0]]=x;}
}
void dfs(int x) //calculating the pointer pointing to its
father for each node
238 ◾ Algorithm Design Practice for Collegiate Programming
{
int y;
for (int i=1;i<=e[x][0];i++) // for each child of x,
setting its father pointer x
{
y=e[x][i];
if (fa[y]==0) { fa[y]=x;dfs(y);}
}
}
void addedge(int x,int y) //determine the coloring sequence
for x and y, that is, y is colored after x is colored
{
while (next[x]) x=next[x];
next[x]=y;
}
void work() //calculate and output the minimum total
coloring cost
{
memset(fa,0,sizeof(fa)); //initialization
fa[root]=-1;
dfs(root); // Traverse the tree whose root is root, and
determine father-children relationships
for (int i=1;i<=n;i++) now[i]=c[i]; // initialization
bool flag[maxN]; // marks for merging nodes
int k,f;
double max;
memset(flag,1,sizeof(flag)); memset(next,0,sizeof(next));
for (int i=1;i<=n;i++) cnt[i]=1;
for (int i=1;i<n;i++) // n−1 merger processes
{
max=0; // Selecting an unmerged node k (isn’t the
root) whose now value is maximal
for (int j=1;j<=n;j++) if ((j!=root)&&(flag[j])&&(max<now
[j])) { max=now[j];k=j;}
f=fa[k];addedge(f,k); // Determining the sequence
for coloring node k and its father f;
while (!flag[f]) f=fa[f]; // Searching node f which is
the nearest for k and isn’t merged based on the pointer
pointing to the father for k, that is, the father node for k
after merger
flag[k]=false; // Set the merger mark for node k
now[f]=(now[f]*cnt[f]+now[k]*cnt[k])/(cnt[f]+cnt[k]);
// adjusting now[f]
cnt[f]+=cnt[k]; // adjusting cnt[f]
}
int p=root,ans=0; // calculate minimum total coloring cost
for (int i=1;i<=n;i++)
{
ans+=i*c[p];p=next[p];
}
Practice for Greedy Algorithms ◾ 239
Input
The input consists of N cases. The first line of the input contains only positive
integer N. Then follow the cases. Each case consists of exactly two lines. At
the first line, there are two integers m and k, 1≤k≤m≤500. At the second line,
there are integers p1, p2, … pm separated by spaces. All these values are positive and
less than 10000000.
240 ◾ Algorithm Design Practice for Collegiate Programming
Output
For each case, print exactly one line. The line must contain the input succession
p1, p2, … pm divided into exactly k parts, such that the maximum sum of a single
part should be as small as possible. Use the slash character (‘/’) to separate the parts.
There must be exactly one space character between any two successive numbers and
between the number and the slash.
If there is more than one solution, print the one that minimizes the work
assigned to the first scriber, and then to the second scriber, etc. But each scriber
must be assigned at least one book.
Analysis
Binary search can be used to solve the problem. If the current maximum number of pages
assigned to a single scriber x is feasible, we can reduce it; otherwise, we can increase it.
The key to the problem is to determine whether the current maximum number
of pages assigned to a single scriber x is feasible or not. Because numbers of pages
assigned to scribers are increasing from left to right, the greedy strategy is as fol-
lows. From back to front, every book is scanned, and the criteria that the current
book can be assigned to the current scriber is that after the book is assigned to the
scriber, the sum of numbers of pages assigned to the scriber isn’t more than x, and
every remainder scriber can be assigned at least one book. If the current book meets
the criteria, the book is assigned to the current scriber; else the book is assigned to a
new scriber, and the new scriber becomes the current scriber. A slash character (‘/’)
is used to separate the two scribers’ work.
Obviously, if k scribers can’t finish copies for m books, then the current maxi-
mum number of pages assigned to a single scriber x isn’t feasible; else the current
maximum number of pages assigned to a single scriber x is feasible.
Binary search is used to find the minimal maximum number of pages assigned
to a single scriber min. The above greedy algorithm is used to find the optimal
assignment.
Practice for Greedy Algorithms ◾ 241
Program
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxN=510; //the upper limit of the number of
books
int n,m,a[maxN]; //n books, m scribers, a[]:the sequence of
books
long long sum; // sum of pages
bool flag[maxN]; // flag to separate books
5.4 Problems
5.4.1 Stripies
Our chemical biologists have invented a new very useful form of life called stripies
(in fact, they were first called in Russian “polosatiki”, but the scientists had to invent
an English name to apply for an international patent). The stripies are transparent
Practice for Greedy Algorithms ◾ 243
Input
The first line of the input contains one integer N (1≤N≤100)—the number of strip-
ies in a colony. Each of the next N lines contains one integer ranging from 1 to
10000—the weight of the corresponding stripie.
Output
The output must contain one line with the minimal possible total weight of the
colony with the accuracy of three decimal digits after the point.
3 120.00
72
30
50
Source: ACM Northeastern Europe 2001, Northern Subregion
IDs for Online Judge: POJ 1862, ZOJ 1543, Ural 1161
Hint
Suppose that the weights of n stripies are m1, m2, …, mn, respectively. After n−1
collisions, the total weight of the colony is as follows.
1
1
1
W = 2n −1 (m1m2 ) 2 m3 n − 2 mn2 .
n −1
2
244 ◾ Algorithm Design Practice for Collegiate Programming
Obviously, if m1, m2, …, mn are sorted in ascending order, the total weight of
the colony W is minimal.
Input
The input contains the single integer number N (0≤N≤109).
Output
Your program should print to the output only the number Q. If such a number does
not exist, print −1.
10 25
Source: USU Local Contest 1999
IDs for Online Judge: Ural 1014
Hint
The criteria for factorization of N is to produce factors as big as possible.
There are two special cases: If N==0, then Q=0; and if N==1, then Q=1.
Otherwise, the greedy strategy is used as follows. N is factorized from 9 to 2.
First, factors 9 are produced, as many as possible; second, factors 8 are produced,
as many as possible; ……; and so on. If the final result for the factorization is not 1,
then there is no solution; else Q is the positive integer that lists the factors from
small to large.
The main argument was that the population of the island recently had increased,
and it was no longer easy to hold general meetings.
The essence of the reform is as follows. From the moment of the reform coming
into effect, all the citizens were divided into K (maybe not equal) groups. Votes on
every question were to be held then in each group; moreover, the group was said
to vote “for” if more than half of the group had voted “for”; otherwise, it was said
to vote “against”. After the voting in each group, a number of the group that had
voted “for” and “against” was calculated. The answer to the question was positive if
the number of groups that had voted “for” was greater than the half of the general
number of groups.
At first the inhabitants of the island accepted this system with pleasure. But
when the first delights dispersed, some negative properties became obvious. It
appeared that supporters of the party that had introduced this system could influ-
ence the formation of groups of voters. Due to this, they had an opportunity to put
into effect some decisions without a majority of voters voting “for” it.
Let’s consider three groups of voters, containing five, five, and seven persons,
respectively. Then it is enough for the party to have only three supporters in each
of the first two groups. So it would be able to put into effect a decision with the
help of only six votes “for” instead of the nine that would be necessary in the case
of general votes.
You are to write a program which would determine according to the given
partition of the electors the minimal number of supporters of the party, sufficient
for putting into effect of any decision, with some distribution of those supporters
among the groups.
Input
In the first line, only an odd integer K—a quantity of groups—is written (1≤K≤101).
In the second line, there are written K odd integers, separated with a space. Those
numbers define a number of voters in each group. The population of the island does
not exceed 9999 persons.
Output
You should write a minimal quantity of supporters of the party that can put into
effect any decision.
3 6
5 7 5
Source: Autumn School Contest 2000
IDs for Online Judge: Ural 1025
246 ◾ Algorithm Design Practice for Collegiate Programming
Hint
K groups are sorted in ascending order of the numbers of voters in groups. There are
K
K groups. Therefore, the party needs + 1 groups voting “for”. If there are n
2
n
voters in a group, the party needs + 1 supporters in the group. Therefore, the
2
minimal quantity of supporters of the party is that there are just over half
K
supporters for the party in the first + 1 groups.
2
5.4.4 Box of Bricks
Little Bob likes playing with his box of bricks. He puts the bricks one upon another
and builds stacks of different heights. “Look, I’ve built a wall!”, he tells his older sis-
ter Alice. “Nah, you should make all stacks the same height. Then you would have
a real wall”, she retorts. After a little consideration, Bob sees that she is right. So he
sets out to rearrange the bricks, one by one, such that all stacks are the same height
afterwards. But since Bob is lazy, he wants to do this with the minimum number of
bricks moved, as shown in Figure 5.5. Can you help?
Input
The input consists of several data sets. Each set begins with a line containing the
number n of stacks Bob has built. The next line contains n numbers, the heights hi
of the n stacks. You may assume 1≤n≤50 and 1≤hi≤100.
The total number of bricks will be divisible by the number of stacks. Thus, it
is always possible to rearrange the bricks such that all stacks have the same height.
The input is terminated by a set starting with n=0. This set should not be processed.
Output
For each set, first print the number of the set, as shown in the sample output. Then
print the line “The minimum number of moves is k.”, where k is the minimum num-
ber of bricks that have to be moved in order to make all the stacks the same height.
Figure 5.5
Practice for Greedy Algorithms ◾ 247
6 Set #1
5 2 4 1 7 5 The minimum number of moves is 5.
0
Source: ACM Southwestern European Regional Contest 1997
IDs for Online Judge: POJ 1477, ZOJ 1251, UVA 591
Hint
n
∑h
i =1
i
Suppose the average value of avg = . That is, avg is the heights of the n stacks
n
after the bricks are moved.
The criteria that bricks in the i-th stack should be moved is as follows. If hi>avg,
then hi−avg bricks should be moved in the stack. Therefore, the minimum number
n
Input
The first line is the number of test cases, followed by a blank line.
Each test case in the input should contain an integer M (1≤M≤5000), followed
by pairs “Li Ri ”(|Li|, |Ri|≤50000, i≤100000), each on a separate line. Each test case
of input is terminated by pair “0 0”.
Each test case will be separated by a single line.
Output
For each test case, in the first line of output, your program should print the mini-
mal number of line segments which can cover segment [0, M]. In the following
248 ◾ Algorithm Design Practice for Collegiate Programming
lines, the coordinates of segments, sorted by their left end (Li), should be printed
in the same format as in the input. Pair “0 0” should not be printed. If [0, M ]
cannot be covered by given line segments, your program should print “0” (without
quotes).
Print a blank line between the outputs for two consecutive test cases.
2 0
1 1
-1 0 0 1
-5 -3
2 5
0 0
1
-1 0
0 1
0 0
Source: USU Internal Contest March’2004
IDs for Online Judge: UVA 10020, Ural 1303
Hint
All segments are sorted in ascending order of left ends as the first key, and right
ends as the second key ((Li≤Li+1||((Li == Li+1)&&(Ri<Ri+1)), 1≤i≤the number of
segments −1).
The criteria for selecting segments is selecting a segment whose right end is the
farthest among segments whose left ends are covered.
The greedy algorithm is as follows:
Suppose that now is the end position that the current segment covers; and len is
the farthest position that a segment k whose left end is covered can reach. Initially
ans=now=len=0.
Every segment in the sorted sequence is analyzed one by one:
Input
The input contains several test cases. Each test case starts with one line containing
four integers n, m, r, and c. (1≤r≤n≤100, 1≤c≤m≤100), The following n lines each
describe one row of pixels of the painting you want to create. The i-th line consists
of m characters describing the desired pixel values of the i-th row in the finished
painting (‘0’ indicates white, ‘1’ indicates black).
The last test case is followed by a line containing four zeros.
Output
For each test case, print the minimum number of operations needed to create the
painting, or −1 if it is impossible.
3 3 1 1 4
010 6
101 -1
010
4 3 2 1
011
110
011
110
3 4 2 2
0110
0111
0000
0 0 0 0
Source: Ulm Local 2007
IDs for Online Judge: POJ 3363
250 ◾ Algorithm Design Practice for Collegiate Programming
Hint
The first thing to realize is that in an optimal solution, the painting operation is
never applied more than once at the same position. Also, it doesn’t matter in which
order the operations are done; therefore, we can do the painting operations from
top to bottom, and from left to right.
Using these ideas, we can easily check if a painting operation at some position is
required or not. Since the pixel in the top left corner of a selected area for the paint-
ing operation will not be changed by later operations, we just check if it already
has the required color. If its color still needs to be changed, we have to apply the
painting operation.
After we have applied all the painting operations, we need to check the pixels in
the rightmost m−c columns and bottom n−r rows to see if they have their required
color. If one of these pixels doesn’t have its required color, it is impossible to create
the painting.
Since the size of the picture is at most 100×100, a naive implementation with
O(n^4) runs in time. There exists an optimal solution which runs in O(n×m). The
idea is to store how many operations have been applied with the top left corner in
one of the first i rows and j columns. With this stored data, it is possible to answer
in constant time how many operations covering a pixel have been applied.
5.4.7 Troublemakers
Every school class has its troublemakers—those kids who can make the teacher’s
life miserable. On his own, a troublemaker is manageable, but when you put certain
pairs of troublemakers together in the same room, teaching a class becomes very
hard. There are n kids in Mrs. Shaida’s math class, and there are m pairs of trouble-
makers among them. The situation has gotten so bad that Mrs. Shaida has decided
to split the class into two classes. Help her do it in such a way that the number of
troublemaker pairs is reduced by at least a half.
Input
The first line of input gives the number of cases, N. N test cases follow. Each one
starts with a line containing n (0≤n≤100) and m (0<m<5000). The next m lines
will contain a pair of integers u and v meaning that when kids u and v are in the
same room, they make a troublemaker pair. Kids are numbered from 1 to n.
Output
For each test case, output one line containing “Case #x:” followed by L—the num-
ber of kids who will be moved to a different class (in a different room). The next line
Practice for Greedy Algorithms ◾ 251
should list those kids. The total number of troublemaker pairs in the two rooms
must be at most m/2. If that is impossible, print “Impossible.” instead of L and an
empty line afterwards.
2 Case #1: 3
4 3 1 3 4
1 2 Case #2: 2
2 3 1 2
3 4
4 6
1 2
1 3
1 4
2 3
2 4
3 4
Source: Abednego’s Graph Lovers’ Contest, 2006
IDs for Online Judge: UVA 10982
Hint
A graph is used to represent the problem, where kids in Mrs. Shaida’s math class
are represented as vertices, and there are edges between each pair of troublemakers.
Mrs. Shaida splits the class into two classes, s[0] and s[1], where the number of kids
in s[1] is less than the number of kids in s[0].
The method that Mrs. Shaida uses to split the class into two classes is as
follows:
For kid i (1≤i≤n), numbers of kids among kid 1 to kid i−1 who constitute a pair
of troublemakers with kid i in s[0] and s[1] are calculated. If such a number in s[1] is
less than such a number in s[0], the kid i is moved to s[1]; else the kid i stays in s[0].
The greedy algorithm is as follows.
10
5 13
1 6 11 15
Figure 5.6
Again, several orders can satisfy the criterion. In that case, we prefer the
sequence where smaller numbers come first. For example, for N=4, H=3, we want
the sequence 1 3 2 4 rather than 2 1 4 3 or 3 2 1 4.
Input
Each test case starts with two positive integers N (1≤N≤10000) and H (1≤H≤30).
Input is terminated by N=0, H=0. This case should not be processed. There can be
at most 30 test cases.
4 1 3 2
3 2 2 4 1 4
2 3 1 1
1 4
Order: 4 3 2 1 Order: 1 2 3 4 Order: 3 4 2 1 or Order: 2 1 4 3 or
3 2 1 4 or 2 4 3 1 or
3241 2413
Figure 5.7
Practice for Greedy Algorithms ◾ 253
Output
The output of each test case should consist of a line starting with “Case #: ” where
# is the test case number. It should be followed by the sequence of N integers in
the same line. There must not be any trailing space at the end of the line. If it is
not possible to construct such a tree, then print “Impossible.”. (without the quotes).
4 3 Case 1: 1 3 2 4
4 1 Case 2: Impossible.
6 3 Case 3: 3 1 2 5 4 6
0 0
Source: ACM ICPC World Finals Warmup 1, 2005
IDs for Online Judge: UVA 10821
Hint
The problem requires you to output the Pre-order Traversal of a BST. Because
smaller numbers come first in the sequence, the number for the root is as small as
possible.
A BST with the height of at most H is constructed by the order of 1 to N
integers. The number of nodes in its left subtree and right subtree is no more than
2H-1−1. The criteria for the number of the root is as follows:
If the right subtree is a full subtree, the number for the root is N−(2H-1−1); else
the number for the root is 1.
Then the problem is transferred and a BST with the height of at most H−1 is
constructed by the order of 1 to root−1 integers, the BST is as the left subtree; and
a BST with the height of at most H−1 is constructed by the order of root+1 to N, the
BST is as the right subtree.
Obviously the greedy algorithm is a recursive algorithm.
Program
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
254 ◾ Algorithm Design Practice for Collegiate Programming
#include<cstring>
#include<algorithm>
using namespace std;
const int maxN=31;
int n,h,cnt,s[maxN]; //s[i]: the number of nodes for a full
binary treeth height i
//function work is an in order traversal for a BST with height
at most h, nodes from l to r
void work(int l,int r,int h)
{
int m=max(l,r-s[h-1]); //the number of root is as small
as possible
printf("%d",m);
if (++cnt<n) printf(" ");
if (l<m) work(l,m-1,h-1); // recursion for the left
subtree
if (r>m) work(m+1,r,h-1); // recursion for the right
subtree
}
int main()
{
for (int i=0;i<=30;i++) s[i]=(1<<i)-1;
int t=0;
while (scanf("%d%d",&n,&h),n+h)
{
cnt=0;
printf("Case %d: ",++t);
if (s[h]<n) printf("Impossible.");else work(1,n,h);
printf("\n");
}
return 0;
}
in the lake in the next interval. To simplify the planning, John assumes that no
one else will be fishing at the lakes to affect the number of fish he expects to catch.
Write a program to help John plan his fishing trip to maximize the number of
fish expected to be caught. The number of minutes spent at each lake must be a
multiple of five.
Input
You will be given a number of cases in the input. Each case starts with a line con-
taining n. This is followed by a line containing h. Next, there is a line of n integers
specifying f i (1≤i≤n), then a line of n integers di (1≤i≤n), and finally, a line of n −1
integers ti (1≤i≤n − 1). Input is terminated by a case in which n=0.
Output
For each test case, print the number of minutes spent at each lake, separated by
commas, for the plan achieving the maximum number of fish expected to be caught
(you should print the entire plan on one line, even if it exceeds 80 characters). This
is followed by a line containing the number of fish expected.
If multiple plans exist, choose the one that spends as long as possible at lake 1, even
if no fish are expected to be caught in some intervals. If there is still a tie, choose the one
that spends as long as possible at lake 2, and so on. Insert a blank line between cases.
2 45, 5
1 Number of fish expected: 31
10 1
2 5 240, 0, 0, 0
2 Number of fish expected: 480
4
4 115, 10, 50, 35
10 15 20 17 Number of fish expected: 724
0 3 4 3
1 2 3
4
4
10 15 50 30
0 3 4 3
1 2 3
0
Source: ACM East Central North America 1999
IDs for Online Judge: POJ 1042, UVA 757
256 ◾ Algorithm Design Practice for Collegiate Programming
Hint
Obviously, in the solution there is no turning back. That is, in John’s fishing trip, if
John fishes at a lake and leaves the lake, he can’t go back to the lake.
Suppose John finishes the trip at lake ed. How can we calculate the maximum
number of fish expected to be caught at lake ed?
The criteria for selecting a lake is as follows:
If the time is allowed, the lake in which there are a maximum number of fish is
selected.
fishes at the lake tt[i] is 0, 1≤i≤ed. The time that John can fish is h 2 = h − ∑t ,
i =1
i
for there is no turning back in his fishing trip. The current number of fish to be
caught now=0.
Then, for each terminal ed, repeat the following steps until h2≤0:
h2−=5;
tt[p]+=5;
now+=f2[p];
the number of fish to be caught in lake p is adjusted
f2[p]=max(f2[p]−dp, 0);
Finally, if (ans<now), then ans=now, and ans_tt[ ] is adjusted;
Program
#include<iostream>
#include<cstdio>
#include<cstdlib>
Practice for Greedy Algorithms ◾ 257
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxN=30;
int n,h,f[maxN],d[maxN],t[maxN];
int f2[maxN],tt[maxN],ans,ans_tt[maxN]; //f2 is the same as
f, tt is the time that John fishes at the lake; ans_tt is the
tt when ans is maximal
void init()
{
// Initialization
ans=-1;
memset(t,0,sizeof(t));
memset(f,0,sizeof(f));
memset(d,0,sizeof(d));
memset(ans_tt,0,sizeof(ans_tt));
//Input
scanf("%d",&h);h*=60; //h is transferred into minutes
for (int i=1;i<=n;i++) scanf("%d",&f[i]);
for (int i=1;i<=n;i++) scanf("%d",&d[i]);
for (int i=1;i<n;i++) {scanf("%d",&t[i]);t[i]+=t[i-1];}
}
//function work : calculate the maximum number of fish
expected to be caught at lake ed
void work(int ed)
{
memcpy(f2,f,sizeof(f));
memset(tt,0,sizeof(tt));
int now=0,h2=h; //now: the current number of fish to be
caught; h2: the time that John can fish
h2-=t[ed-1]*5; // the number of minutes spent from lake 1
to lake ed
f2[0]=-1;
while (h2>0) // each while corresponds to five minutes of
fishing
{
int p=0;
h2-=5; // spend 5 minutes
for (int i=1;i<=ed;i++) // search a lake p in which
there are maximum number of fish
if (f2[p]<f2[i]) p=i;
tt[p]+=5;
now+=f2[p];f2[p]=max(f2[p]-d[p],0); // accumulation
}
if (ans<now) { ans=now;memcpy(ans_tt,tt,sizeof(tt));}
}
//output the result
void print()
{
258 ◾ Algorithm Design Practice for Collegiate Programming
259
260 ◾ Algorithm Design Practice for Collegiate Programming
4 7
1
2 4 3
4 3 7
5
1 5 5 4
8 10
2 4
3 5
6
3 6 9
Figure 6.1
For example, Figure 6.1 shows a solution to a problem that is divided into five
orderly and related stages. State 1 is called the initial state, in stage 1. State 10 is
called the goal state, in stage 5. In stage 3 there are three states: state 4, state 5, and
state 6.
Decision uk and Available Decision Set Dk(sk): The choice from a state in
stage k−1 (the current stage) to a state in stage k (the next stage) is called decision
uk. Normally, a state can be reachable through more than one decision from the last
stage, and such decisions constitute an available decision set Dk(sk).
For example, there are two decisions reaching state 5: 2→5, 3→5, D3(5)={2, 3}.
A decision sequence from the initial state to the goal state is called a strategy. For
example, 1→3→5→8→10 is a strategy.
Successor Function and Optimization: A successor function is used to
describe the transition from stage k−1 to stage k. The DP method is used to solve
some optimization problems. Successor functions are used to find a solution with
the optimal (minimum or maximum) value to a problem. A successor function can
be formally defined as follows:
f k ( sk ) = opt g ( f k −1 (Tk ( sk , uk )) , uk ) ;
uk ∈Dk ( sk )
where Tk(sk, uk) is a state sk −1 in stage k−1 which relates to state sk through deci-
sion uk, and f k −1 (Tk ( sk , uk )) is an optimal solution, g(x, uk) is a function for value
x and decision uk, that is, g ( f k −1 (Tk ( sk , uk ) is a function from state sk −1 to state sk
through decision uk; opt means optimization; and f1(s1) is an initial value. Because
uk is one decision in a decision set Dk(sk), all decisions are enumerated to get
the optimal solution to sk. From the initial state, successor functions are used to
get the optimal solution fn (goal state) to the problem finally.
If the stages are in linear order, linear DP is used to solve the problem.
for (every stage i is processed in linear order)
{
for (every state j in stage i is enumerated (j∈Si))
{ for (every state k in stage i−1 which is related to state
j is enumerated (k∈Si-1))
Practice for Dynamic Programming ◾ 261
For example, all of the following sequences of characters are regular brackets
sequences:
(), [], (()), ([]), ()[], ()[()]
Some sequence of characters ‘(’, ‘)’, ‘[’, and ‘]’ is given. You are to find the short-
est possible regular brackets sequence that contains the given character sequence
as a subsequence. Here, a string a1 a 2 ... an is called a subsequence of the string
b1 b2 ... bm, if there exist such indices 1≤i1<i2<…<in≤m, that aj=bij for all 1≤j≤n.
Input
The input file contains at most 100 brackets (characters ‘(’, ‘)’, ‘[’ and ‘]’) that are
situated on a single line without any other characters among them.
Output
Write to the output file a single line that contains some regular brackets
sequence that has the minimal possible length and contains the given sequence
as a subsequence.
([(] ()[()]
Analysis
Suppose stage r is the length of subsequence, 1≤r≤n; and state i is the pointer
pointing to the front of the current subsequence, 0≤i≤n−r. Based on i and r, the
pointer j pointing to the rear of the current subsequence can be calculated, j=i+r−1.
Suppose dp[i, j] is the minimal number of characters that must be inserted into
si…sj. Obviously, if the length of subsequence is 1, dp[i, i]=1, 0≤i<strlen(s).
If ((si=='[')&&(sj==']')||(si=='(')&&(sj==')')), then the minimal number of
characters that must be inserted into si…sj is the minimal number of characters
that must be inserted into si+1…s j −1, that is, dp[i, j]=dp[i+1, j−1]; otherwise si…sj
is divided into two parts, and we need to determine the pointer k (i≤k<j) so that
dp[i , j ] = min(dp[i , k ] + dp[k + 1, j ]).
1≤ k < j
Based on the above, a memorized list path[ ][ ] is used to store all solutions to
subproblems:
After the memorized list path[ ][ ] is calculated through DP, the regular brack-
ets sequence that has the minimal possible length and contains the given sequence
as a subsequence can be obtained through recursion.
Program
#include<cstdio>
#include<cstring>
const int N=100;
char str[N]; //Input String
int dp[N][N];
int path[N][N];
void oprint(int i,int j) //output regular brackets sequence
containing subsequence str[i, j]
{
if(i>j)
return;
if(i==j) //there is only one character for subsequence
str[i, j]
{
if(str[i]=='['||str[i]==']')
Practice for Dynamic Programming ◾ 263
printf("[]");
else
printf("()");
}
else if(path[i][j]==-1) // str[i] and str[j] are matched
brackets
{
printf("%c",str[i]);
oprint(i+1,j-1);
printf("%c",str[j]);
}
else // otherwise
{
oprint(i,path[i][j]);
oprint(path[i][j]+1,j);
}
}
int main(void)
{
while(gets(str))
{
int n=strlen(str);
if(n==0)
{
printf("\n");
continue;
}
memset(dp,0,sizeof(dp));
for(int i=0;i<n;i++)
dp[i][i]=1;
for(int r=1;r<n;r++) //Stage: r is the length of
subsequences
{
for(int i=0;i<n-r;i++) //State: fronts of
subsequences are enumerated
{
int j=i+r; // rears of subsequences
dp[i][j]=0x7fffffff; // Initialization
if((str[i]=='(' && str[j]==')') || (str[i]=='['
&& str[j]==']')) // str[i] and str[j] are matched
{
dp[i][j]=dp[i+1][j-1];
path[i][j]=-1;
}
for(int k=i; k<j; k++) // k is enumerated
{
if(dp[i][j]>dp[i][k]+dp[k+1][j])
{
dp[i][j]=dp[i][k]+dp[k+1][j];
path[i][j]=k;
264 ◾ Algorithm Design Practice for Collegiate Programming
}
}
}
}
oprint(0,n-1); // Output the regular brackets sequence
printf("\n");
}
return 0;
}
There are three classical problems solved by DP method: Subset Sum; Longest
Common Subsequence (LCS); and Longest Increasing Subsequence(LIS).
1 i=0
i −1
c (i , j ) =
∑ c (k , j − ai ) i ≥ 1, j ≥ ai
k =1
6.1.2.1 Dollars
New Zealand currency consists of $100, $50, $20, $10, and $5 notes and $2, $1,
50c, 20c, 10c and 5c coins. Write a program that will determine, for any given
amount, in how many ways that amount may be made up. Changing the order of
listing does not increase the count. Thus 20c may be made up in four ways: 1×20c,
2×10c, 10c+2×5c, and 4×5c.
Practice for Dynamic Programming ◾ 265
Input
Input will consist of a series of real numbers no greater than $50.00 each on a sepa-
rate line. Each amount will be valid, that is, it will be a multiple of 5c. The file will
be terminated by a line containing zero (0.00).
Output
Output will consist of a line for each of the amounts in the input, each line consist-
ing of the amount of money (with two decimal places and right-justified in a field
of width 5), followed by the number of ways in which that amount may be made
up, right-justified in a field of width 12.
0.20 0.20 4
2.00 2.00 293
0.00
Analysis
First, DP is used to calculate all solutions to the problem in the range. The 5c coin
is the smallest coin. Other notes and coins for New Zealand currency are multiples
for the 5c coin. Therefore, the 5c coin is used as the unit for notes and coins for
New Zealand currency. Suppose b[i] is the number of 5c coins for the i-th currency,
0≤i≤10; a[i, j] is the number of ways in which j 5c coins may be made up using the
first i-th currencies, 0≤i≤10, 0≤j≤6000.
Obviously, the number of ways in which j 5c coins may be made up only using
5c coin is 1, that is, a[0, j]=1, 0≤j≤6000. If the amount is equal to a coin or a note,
there is a way that the amount may be made up using the coin or the note.
For 10 cents, there are two ways. 10 cents are made up using 5c coins or a 10c coin.
For 15 cents, the first way is that 15c cents are made up only using 5c coins.
Then we calculate the number of ways in which 15 cents are made up using 5c coin
and 10c coin (the way only using 5c coin needn’t be considered). First a 10c coin is
used (at least one 10c coin is used), and then a 5c coin is used. Therefore, there are
two ways for 15 cents.
For 20 cents, the first case is that only 5c coins are used. For the second case, a
10c coin is used first (at least one 10c coin is used), and for the remaining 10 cents,
there are two ways. The final case is that only the 20c coin is used. Therefore, there
are four ways.
266 ◾ Algorithm Design Practice for Collegiate Programming
Based on the above, the number of ways in which j 5c coins may be made
up using the first i-th currencies is based on the number of ways in which
j−b[i] 5c coins may be made up using the first (i−1)th currencies. That is,
i −1
Program
#include <iomanip>
#include <iostream>
using namespace std;
int main(void) {
int b[] = {1, 2, 4, 10, 20, 40, 100, 200, 400, 1000, 2000};
//5c coin is used as the unit for notes and coins for
New Zealand currency
long long a[6001] = {1}; // the number of ways in which n
5c coins may be made up using notes and coins for New Zealand
currency is a[n]
//Off-line method, DP
for (int i = 0; i < 11; i++){ // Enumerate all coins and
notes
for (int j = b[i]; j < 6001; j++) { // Enumerate
a[j] += a[j - b[i]];
}
}
cout << fixed << showpoint << setprecision(2);
for (float fIn; cin >> fIn && fIn != 0; cout << endl) {
cout << setw(6) << fIn << setw(17) << a[(int)(fIn * 20 +
0.5f)];
}
return 0;
}
Input
The input file may contain multiple test cases. Each case will contain two succes-
sive lines of string. Blank lines and non-letter printable punctuation characters may
appear. Each line of string will be no longer than 1000 characters. The length of
each word will be less than 20 characters.
Output
For each case of input, you have to output a line starting with the case number
right-justified in a field width of two, followed by the longest match, as shown
268 ◾ Algorithm Design Practice for Collegiate Programming
in the sample output. In the case of at least one blank line for each input, output
“Blank!”. Consider the non-letter punctuation characters as white spaces.
Analysis
Consecutive letters in a string are regarded as a word. Words in two strings are got-
ten one by one, where words in the first string are stored in T1.word[1]…T1.word[n],
and words in the second string are stored in T2.word[1]…T2.word[m].
Then every word is regarded as a “character”. The LCS algorithm is used to
calculate the Longest Common Subsequence (LCS). The length of the subsequence
is the length of the longest match.
Program
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<algorithm>
#define N (1024)
using namespace std;
struct text{ // two successive lines of string
int num; // number of words
string word[1024]; // words
}t1,t2;
string s1,s2;
int f[N][N]; //the number of matched words for the first
i-th words in s1 and the first j-th words in s2 is f[i, j]
void devide(string s,text &t) // sequence of words t.word[]
whose length is t.num is taken out from s
{
Practice for Dynamic Programming ◾ 269
f(1)=1
f(i)=max {f(j)|aj<ai}+1
1≤j≤i-1
f(n) is the length of the LIS for A. Obviously, the time
complexity using the DP method is O(n2).
Method 3: Dichotomy.
For Method 2, in order to calculate f(i), the maximal f(j)(j<i) must be found.
Array B is used to store the rear for LIS of subsequences, that is, B[f(j)]=aj.
When f(i) is calculated, dichotomy is used to find j in array B where j<i and
B[f(j)]=aj<ai. Then B[f [j]+1]=ai.
Experiments for the three DP methods are as follows.
1. One point for each event whose rank matches its correct rank;
2. One point for each event in the longest (not necessarily contiguous) sequence
of events which are in the correct order relative to each other.
For example, if four events are correctly ordered 1 2 3 4, then the order 1 3 2
4 would receive a score of 2 using the first method (events 1 and 4 are correctly
ranked) and a score of 3 using the second method (event sequences 1 2 4 and 1 3 4
are both in the correct order relative to each other).
In this problem, you are asked to write a program to score such questions using
the second method.
Practice for Dynamic Programming ◾ 271
Input
The first line of the input will consist of one integer n indicating the number of
events with 2≤n≤20. The second line will contain n integers, indicating the correct
chronological order of n events. The remaining lines will each consist of n inte-
gers with each line representing a student’s chronological ordering of the n events.
All lines will contain n numbers in the range [1..n], with each number appearing
exactly once per line, and with each number separated from other numbers on the
same line by one or more spaces.
Output
For each student ranking of events, your program should print the score for that
ranking. There should be one line of output for each student ranking.
4 1
4 2 3 1 2
1 3 2 4 3
3 2 1 4
2 3 4 1
10 6
3 1 2 4 9 5 10 6 8 7 5
1 2 3 4 5 6 7 8 9 10 10
4 7 2 3 10 6 9 1 5 8 9
3 1 2 4 9 5 10 6 8 7
2 10 1 3 8 4 9 5 7 6
Analysis
Suppose st[ ] is the correct chronological order of n events, where st[t] is the t-th
event in the chronological order; ed[ ] is the current student’s chronological order-
ing of the n events, where ed[t] is the t-th event in the current student’s chronologi-
cal order.
Obviously, the Longest Common Subsequence (LCS) for st[ ] and ed[ ] is the
Longest Increasing Subsequence (LIS) for ed[ ], where its length is the score for that
ranking. Method 1 is used to solve the problem.
Program
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int n; //number of events
int f[30][30];
int st[30]; // st[t] is the t-th event in the chronological
order
int ed[30]; // ed[t] is the t-th event in the current
student's chronological order
int tmp[30];
int main(void)
{
freopen("111.in","r",stdin);
freopen("HG.out","w",stdout);
scanf("%d",&n); // Input number of events
for(int i=1;i<=n;++i) // Input the correct chronological
order of n events
{
cin >> tmp[i];
st[tmp[i]]=i;
}
while(!cin.eof()) //Input students' chronological
ordering of the n events
{
for(int i=1;i<=n;++i) // Input current student's
chronological ordering of the n events
{
Practice for Dynamic Programming ◾ 273
6.1.4.2 Ski
Michael likes to ski. Skiing is really exciting for him. In order to get speed,
the ski area must be down. When he skis down to the bottom, he has to walk
up the hill again or wait for the lift to carry him. Michael wants to know the
longest skidway in a ski area. The ski area is given by a two-dimensional array.
Each digit of the array represents the height of the point. There is an example
as follows:
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
From a point, he can ski to one of four adjacent points (up, down, left,
and right), if and only if the height of an adjacent point is less than the height
of the point. In the above example, a viable skidway is 24−17−16−1. Obviously
25−24−23−...−3−2−1 is the longest viable skidway.
Input
Row R and column C for the ski area are shown in the first line (1≤R,C≤100). Then
there are R rows, and in each row there are C integers representing the height of
points h, where 0≤h≤10000.
274 ◾ Algorithm Design Practice for Collegiate Programming
Output
Output the length of the longest viable skidway that Michael can ski.
5 5 25
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
Analysis
The problem requires you to calculate the length of the longest viable skidway whose
points are adjacent and in descending order. The skidway is the Longest Decreasing
Subsequence, if heights are as keys. Method 2 is used to solve the problem. Suppose
f [ ][ ] is visited marks, if point (x, y) is in the skidway, then f [x][y]=true; and c[ ][ ]
is the successor function, where c[x][y] is the longest viable skidway which starts
from (x, y):
1 Initialization
c[ x ][ y ] = .
max{ c [ xx ][ yy ] + 1} ( xx , yy ) is adjacent to ( x , y ), unvisited, and lower.
Because the start point isn’t given in the problem, the length of the longest
viable skidway ans = max (1≤x ≤n ,1≤ y ≤m ) {c[ x ][ y ]}.
Program
#include<cstdio>
using namespace std;
int n,m,s1[5],s2[5],i,j,ans; //size of the ski area is n*m;
the length of the longest viable skidway is ans
int a[105][105],c[105][105]; // adjacency matrix for ski
area a[ ][ ], state transition equation c[ ][ ]
bool f[105][105]; //visited mark
Practice for Dynamic Programming ◾ 275
Input
The input file contains less than 75 test cases. The description of each test case is
given below. Input is terminated by end of file.
Each set starts with a positive integer, N(1≤N≤10000). In the next few lines
there will be N integers.
Output
For each set of input, print the length of the longest Wavio sequence in a line.
10 9
1 2 3 4 5 4 3 2 1 10 9
19 1
1 2 3 2 1 2 3 4 3 2 1 5 4 1 2 3 2 2 1
5
12345
Source: The Diamond Wedding Contest: Elite Panel’s 1st Contest 2003
IDs for Online Judge: UVA 10534
Analysis
Suppose the sequence of integers is A=a1...an; LIS[k] is the length of the Longest
Increasing Subsequence in [a1...ak]; and LDS[k] is the length of the Longest
Decreasing Subsequence in [ak...an].
First, Method 3 is used to calculate the length of the Longest Increasing
Subsequence in the prefix for A. If the prefix’s rear is ai, the length is f [i], 1≤i≤k.
Therefore, LIS[k ] = max{ f [i ]}.
1≤i ≤ k
Second, Method 3 is used to calculate the length of the Longest Decreasing
Subsequence in the postfix for A. If the postfix’s front is ai, the length is f [i], k≤i≤n.
Therefore, LDS[k ] = max{ f [i ]}.
k ≤i ≤ n
If k is the pointer pointing to the middle of a Wavio sequence, that is, the
number of integers in the left half and the number of integers in the right half is
min{LIS[k], LDS[k]}. The length of the Wavio sequence is ans[k]=2×min{LIS[k],
LDS[k]}−1.
The length of the longest Wavio sequence is ans = max{ans[k ]}.
1≤ k ≤ n
Practice for Dynamic Programming ◾ 277
Program
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 10010,INF = 2147483647;
int N,A[MAXN],F[MAXN],G[MAXN],L[MAXN]; // N: the number of
integers, A[ ] is the given sequence, L[ ]: increasing
sequence, F[ ] is as LIS[ ], G[ ] is as LDS[ ]
int binary(int l,int r,int x) // return the number of
elements in L[l, r] which are less than x
{
int mid;
l = 0; r = N;
while (l<r)
{
mid = (l+r)>>1;
if (L[mid+1]>=x) r = mid; else l = mid+1;
}
return l;
}
inline int min(int x,int y) { return (x<y) ? (x) : (y); }
// return min{x, y}
int main()
{
int i,j,k,Ans;
while (scanf("%d",&N) != EOF)
{
for (i=1;i<=N;i++) scanf("%d",A+i); // Input N
integers
for (i=1;i<=N;i++) L[i]=INF; L[0]=-INF-1;
// Initialization
for (i=1;i<=N;i++) //Right to left in array A
{
F[i]=binary(1,N,A[i])+1;
if (A[i]<L[F[i]]) L[F[i]]=A[i];
}
for (i=1;i<=N;i++) L[i]=INF; L[0]=-INF-1; //
Initialization
for (i=N;i>=1;i--) // Left to right in array A
{
G[i]=binary(1,N,A[i])+1;
if (A[i] < L[G[i]]) L[G[i]]=A[i];
}
Ans=0;
278 ◾ Algorithm Design Practice for Collegiate Programming
1. The calculation sequences are different. There are two calculation sequences
for linear DP: forward and backward. The calculation sequence for tree-like
DP is normally from leaves to the root, and the root is the solution.
2. The calculation methods are different. A traditional iteration method is used
in linear DP. The recursive method is used in tree-like DP, for tree-like DP is
normally implemented by memorized search.
3 4
Figure 6.2
Practice for Dynamic Programming ◾ 279
apples. So you are given numbers of apples on a branch and the number of branches
that should be preserved. Your task is to determine how many apples can remain on
a tree after the removal of excessive branches.
Input
The first line of input contains two numbers: N and Q (2≤N≤100; 1≤Q≤N−1).
N denotes the number of enumerated points in a tree. Q denotes the number of
branches that should be preserved. The next N−1 lines contain descriptions of
branches. Each description consists of three integer numbers divided by spaces. The
first two of them define a branch by its ending points. The third number defines the
number of apples on this branch. You may assume that no branch contains more
than 30000 apples.
Output
Output should contain only the number—the number of apples that can be pre-
served. And don’t forget to preserve the tree’s root.
52 21
131
1 4 10
2 3 20
3 5 20
Analysis
In this problem, the apple tree is a weighted binary tree. The problem requires you
to get such a subtree with Q branches (i.e., Q+1 points) whose weight is maximal.
For each internal point, there are three choices: pruning its left subtree, pruning its
right subtree, or pruning some points in its left subtree and its right subtree; to get
a subtree with maximal weight.
Suppose g[x][k] is the maximal weight for the subtree with root x in which there
are k points (including the weight of the branch from root x to its parent). For each
280 ◾ Algorithm Design Practice for Collegiate Programming
leaf, DP is used in the order of post-order traversal. The successor function for DP
is as follows:
If x is a leaf, then g[x][k]= the weight of the edge from x to its parent; else all
cases where k−1 nodes are distributed in its left subtree and its right subtree are
enumerated, and the best case is found. That is,
0 k=0
the weight of the edge from x to its parent x is a leaf
g [ x ][k ] = the weight of the edge from x to its parent + x isn't a leaf
max { g [the left child for x ][i ] +
0 ≤ k ≤ k −1
g [the right child for x ][k − i − 1]}
Program
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define Max(a,b) ((a)>(b)?(a):(b))
#define N (256)
using namespace std;
int n,m,ne,x,y,z; //n: number of points, m: amount of
preserve branches, that should be preserved, ne: the number of
a branch, (x,y): a branch, z: weight
int id[N],w[N],v[N],next[N],head[N],lch[N],rch[N],f[N];
int g[N][N]; // Successor Function
void add(int x,int y,int z) //add branch (x, y) with weight
z into adjacency list
{
id[++ne]=y; w[ne]=z; next[ne]=head[x]; head[x]=ne;
}
void dfs(int x) //a binary tree is constructed from point x
{
for (int p=head[x];p;p=next[p]) //search every branch p
connecting x
if (id[p]!=f[x])
{
if (!lch[x]) lch[x]=id[p]; else rch[x]=id[p];
f[id[p]]=x;
Practice for Dynamic Programming ◾ 281
v[id[p]]=w[p];
dfs(id[p]);
}
}
int dp(int x,int k) //from x, the subtree with k points and
maximal number of apples
{
if (!k) return 0; //subtree is empty
if (g[x][k]>=0) return g[x][k]; // return the result
if (!lch[x]) return (g[x][k]=v[x]); // x is a leaf
for (int i=0;i<k;++i) // calculate the best case
g[x][k]=Max(g[x][k],dp(lch[x],i)+dp(rch[x],k-i-1));
g[x][k]+=v[x];
return g[x][k];
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<n;++i)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
dfs(1);
memset(g,255,sizeof(g));
printf("%d\n",dp(1,m+1));
return 0;
}
Input
The first line of the input contains a number N. 1≤N≤6000. Each of the sub-
sequent N lines contains the conviviality rating of the corresponding employee.
282 ◾ Algorithm Design Practice for Collegiate Programming
Conviviality rating is an integer number in a range from -128 to 127. After that,
the supervisor relation tree goes. Each line of the tree specification has the form
<L><K>
which means that the K-th employee is an immediate supervisor of the L-th
employee. Input is ended with the line
00
Output
The output should contain the maximal total rating of the guests.
7 5
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0
Source: Ural State University Internal Contest October 2000 Students Session
IDs for Online Judge: POJ 2342, Ural 1039
Analysis
The supervisor relation in Ural State University forms a tree rooted at the president.
For each internal node u in the tree, there are two possible conviviality ratings of
the subtree rooted at u:
If the maximal conviviality rating of the subtree doesn’t include node u, then the
maximal conviviality rating of the subtree is the sum of the maximal conviviality
Practice for Dynamic Programming ◾ 283
ratings of all subtrees for node u (subtrees root at u’s children), and for such sub-
trees, their maximal conviviality ratings also have two cases: including their roots
or not including their roots.
If the maximal conviviality rating of the subtree includes node u is the maximal
conviviality rating of the subtree doesn’t include node u plus conviviality rating for
node u. Suppose F[u][0] is the maximal conviviality rating of the subtree rooted
at u which doesn’t include node u; and F[u][1] is the maximal conviviality rating
of the subtree rooted at u which includes node u. Initially, F[u][0]=0, F[u][1]=u,
1≤u≤n. Then from leaf nodes, based on post-order traversal, the successor function
is calculated as follows:
Program
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 6010; //the upper limit of the number
of nodes
int N,root,Ri[MAXN],F[MAXN][2],son[MAXN],bro[MAXN];
// successor function F[][]
bool is_son[MAXN];
void init() //Input and construct the adjacency list for
the tree
{
int i,j,k;
scanf("%d",&N); //number of employees
for (i=1;i<=N;i++) scanf("%d",Ri+i); // the
conviviality rating of employee
memset(son,0,sizeof(son));
memset(is_son,0,sizeof(is_son));
for (i=1;i<N;i++)
{
scanf("%d%d",&j,&k); //k is the immediate supervisor
for j
bro[j] =son[k]; son[k] = j; //j is added into the
adjacency list for k
284 ◾ Algorithm Design Practice for Collegiate Programming
Input
You’ll be given x, and y, both less than 20, followed by x lines of y characters each
as a map of the area, consisting solely of “.”, “#”, and “L”. Larry and Ryan are cur-
rently located in “L”, and the nuts are represented by “#”. They can travel in all eight
adjacent directions in one step. See below for an example. There will be at most
15 places where there are nuts, and “L” will only appear once.
Output
On each line, output the minimum number of steps starting from “L”, gather all
the nuts, and back to “L”.
55 8
L.... 8
#....
#....
.....
#....
55
L....
#....
#....
.....
#....
Analysis
The places where Ryan and Larry and all nuts locate are as vertices. Their coordi-
nates are recorded, where (x0, y 0) is the place where Larry and Ryan are currently
located, and (xi, yi) is the place where the i-th nut is located, 1≤i≤n. Map[ ][ ] is used
to represent distances between vertices, where Map[i ][ j ] = max { xi − x j , yi − y j }
for vertex i and vertex j.
The state that nuts are gathered is represented as a n bit binary number ( bn−1 , …,
b0), where bi=0 means the (i+1)-th nut isn’t gathered, and bi=1 means the (i+1)-th
nut is gathered. Suppose j is the current state value that nuts are gathered, where
286 ◾ Algorithm Design Practice for Collegiate Programming
nut i is the nut that is gathered finally, and the minimum number of steps is f [i][j].
Obviously the minimum number of steps that Ryan and Larry gather for every nut
is f [i ][2i−1 ]= map[0][i ](1≤ i ≤ n ). Suppose the state the nuts are gathered currently is
j, where the number of gathered nuts is i, and the minimum number of steps is f [i][j].
Obviously, the minimum number of steps that Ryan and Larry gather for each nut is
f [i ][2i−1 ]= map[0][i ], 1≤ i ≤ n . The successor function is analyzed as follows:
After n nuts are gathered, if nut i is the last gathered nut, the minimum number
of steps to reach the position of nut i is f [i][2n−1], the number of steps back to “L”
is map[0][i]. The number of steps is f [i][2n−1]+map[0][i].
Finally, all results are compared i(1≤i≤n), the minimum number of steps start-
ing from “L”, gather all the nuts, and back to “L” is:
ans = min{ f [i ][2n −1]+ map[0][i ]}.
1≤i ≤n
Program
#include <cstdio>
#include <cstring>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Inf (1<<20)
#define N (30)
#define M (65536)
using namespace std;
int f[N][M]; // nuts are gathered currently is j, where the
number of gathered nuts is i, and the minimum number of steps
is f[i][j]
char s[N]; //current row
int map[N][N]; // distance between vertice i and vertex j
is map[i, j]
int x[N],y[N]; //The sequence of vertices’ coordinates
int num,n,m,ans,maxz; //num: number of nuts, n*m: the size
of the map, ans: the minimum amount of steps starting from
Practice for Dynamic Programming ◾ 287
“L”, gather all the nuts, and back to “L”, maxz: the state
that all nuts are gathered
int Abs(int x) { if (x>0) return x; return -x; } //|x|
void Update(int &x,int y) { if (x>y) x=y; } //x←max{x,y}
int main()
{
while (scanf("%d%d",&n,&m)!=EOF) //Input the size of the
map
{
num=0;
for (int i=0;i<n;++i) // Input every row, calculate
the number of nuts, set up the sequence of vertices’
coordinates, where (x[0], y[0]) is the position where Larry
and Ryan are currently located, (x[1…num], y[1…num]) are
positions for num nuts
{
scanf("%s",s);
for (int j=0;j<m;++j)
if (s[j]=='#') { x[++num]=i; y[num]=j; } else
if (s[j]=='L') { x[0]=i; y[0]=j; }
}
if (!num) {printf("0\n"); continue; }
for (int i=0;i<=num;++i) //Calculate distances between
vertices
for (int j=0;j<=num;++j)
map[i][j]=Max(Abs(x[i]-x[j]),Abs(y[i]-y[j]));
maxz=(1<<num)-1; // Calculate the state that all nuts
are gathered
for (int i=0;i<=maxz;++i) // Initialize successor
function
for (int j=0;j<=num;++j) f[j][i]=Inf;
for (int i=1;i<=num;++i) f[i][1<<(i-1)]=map[0][i];
for (int i=0;i<maxz;++i) // states are enumerated
{
for (int j=1;j<=num;++j) if (i & (1<<(j-1))) // The
last gathered nut j in stage i is enumerated
for(int k=1;k<=num;++k) // Nut k which isn’t in
stage i is enumerated, and adjusted
if (!(i & (1<<(k-1))))Update(f[k][i+(1<<(k-1))],
f[j][i]+map[j][k]);
}
ans=Inf;
for (int i=1;i<=num;++i) // Enumerate the last
gathered nut i, and adjust
Update(ans,f[i][maxz]+map[i][0]);
printf("%d\n",ans); // Output the result
}
return 0;
}
288 ◾ Algorithm Design Practice for Collegiate Programming
Figure 6.3
Input
The input file contains several test cases. Each test case is made up of two integer
numbers: the height h and the width w of the large rectangle. Input is terminated
by h=w=0. Otherwise, 1<=h, w<=11.
Output
For each test case, output the number of different ways the given rectangle can be
filled with small rectangles of size 2 times 1. Assume that the given large rectangle
is oriented, i.e., count symmetrical tilings multiple times (see Figure 6.4).
Figure 6.4
Practice for Dynamic Programming ◾ 289
1 2 1
1 3 0
1 4 1
2 2 2
2 3 3
2 4 5
2 11 144
4 11 51205
0 0
Analysis
Assume that you could calculate the number of different paintings for a rectangle
with c columns and r rows where the first r−1 rows are completely filled and the last
row has any of 2c possible patterns. Then, by trying all variations of filling the last
row where small rectangles may be spilled into a further row, you can calculate the
number of different paintings for a rectangle with r+1 rows where the first r rows
are completely filled and the last row again has any pattern.
This straightforwardly leads to a DP solution. All possible ways of filling a row,
part of which may already be occupied and spilling into the next row and creating a
new pattern, are generated by backtracking over a row. Viewing these as transitions
from a pattern to another pattern, their number is given by the recursive equation
Tc = 2Tc −1 + Tc − 2 . Its solution is asymptotically exponential with a base of sqrt(2)+1,
which is not a problem for c<=11.
If both h and w are odd, the result is 0. Since the number of paintings is a sym-
metric function, the number of columns should be chosen as the smaller of the two
input numbers whenever possible to improve runtime behaviour substantially.
Judges’ test data includes all 121 legal combinations of h and w.
Since the size of the painting could be as large as 110, a simple backtracking
solution won’t do, not even with using five hours of contest time to precalculate
the results. Once the DP algorithm is implemented, a quick review of the results
should reveal that they don’t fit into 32-bit ints. There are four ways to solve this
problem: try double (which works actually), implement 64-bit arithmetics (only
addition is needed), implement arbitrary precision arithmetics, or switch to Java
and use BigInteger. A more efficient algebraic solution was not known to the judges.
290 ◾ Algorithm Design Practice for Collegiate Programming
Program
#include <stdio.h>
static double cnt[12][1<<11];
static int trans[16384][2];
int rows, cols, ntrans;
/* there are ((sqrt(2)+1)^c - (sqrt(2)-1)^c) * (sqrt(2)+2) / 4
transitions
* which is the solution to T_{c} = 2 * T_{c-1} + T_{c-2}
*/
void backtrack (int n, int from, int to)
{
if (n > cols) return;
if (n == cols)
{
trans[ntrans][0] = from;
trans[ntrans][1] = to;
++ntrans;
return;
}
backtrack (n+2, from<<2, to<<2);
backtrack (n+1, from<<1, (to<<1)|1);
backtrack (n+1, (from<<1)|1, to<<1);
}
int main ()
{
int r, t;
FILE* in = fopen ("dream.in", "r");
while (fscanf (in, " %d %d ", &rows, &cols) == 2)
{
if (rows == 0 || cols == 0) break;
if (rows < cols) { t = rows; rows = cols ; cols = t; }
/* calculate map of possible transitions by linear
backtracking */
ntrans = 0;
backtrack (0, 0, 0);
for (r=0 ; r<=rows ; r++)
for (t=0 ; t<(1<<cols) ; t++)
cnt[r][t] = 0;
cnt[0][0] = 1;
for (r=0 ; r<rows ; r++) /* the r topmost rows are already
filled */
for (t=0 ; t<ntrans ; t++) /* perform all transitions */
cnt[r+1][trans[t][1]] += cnt[r][trans[t][0]];
printf ("%.0f\n", cnt[rows][0]);
}
return 0;
}
Practice for Dynamic Programming ◾ 291
Figure 6.5
6.4 Problems
6.4.1 Tri Tiling
In how many ways can you tile a 3×n rectangle with 2×1 dominoes?
Figure 6.5 shows a sample tiling of a 3×12 rectangle.
Input
Input consists of several test cases followed by a line containing −1. Each test case
is a line containing an integer 0≤n≤30.
Output
For each test case, output one integer number giving the number of possible tilings.
2 3
8 153
12 2131
-1
Hint
Suppose the state for column i is represented as a binary number j (0≤i≤n−1, 0≤j≤7),
where 0 represents the square that is occupied by a domino, and 1 represents the
square that isn’t occupied by a domino. Obviously, the state for (0, i) is c=j&1; the
j j
state for (1, i) is b = &1; and the state for (2, i) is a = .
2 4
Suppose dp[i][j] is the number of possible tilings for the first i columns whose
state is j. Obviously, dp[0][0]=1. From left to right, DP is used as follows.
1 14 10 10
2 13 11 10
3 13 10 11
4 12 11 11
5 12 10 12
6 11 11 12
7 11 10 13
8 10 11 13
9 10 10 14
10 11 12 11
11 10 12 12
12 12 12 10
13 10 13 11
14 11 13 10
15 10 14 10
Input
In the first line of the input, there will be a single positive integer K followed by
K lines, each containing a single test case. Each test case contains three positive
Practice for Dynamic Programming ◾ 293
Output
For each input, print in a line the value of F (N, T, P).
2 15
3 34 10 15
3 34 10
Hint
Suppose dp[i][j] shows the number of ways the student passes i sub-
jects and gets total j marks. Therefore, dp[1][j]=1, where P≤j≤T; and
j−P
Input
Each line of the input contains two integers n indicating the total number of distin-
guishable types of chocolate and m indicating the total number of distinguishable
boxes (m≤n<100). A single line containing −1 denotes the end.
294 ◾ Algorithm Design Practice for Collegiate Programming
Output
For each of the cases, you should calculate the probability corrected to seven deci-
mal places. The output format is shown below.
50 12 Case 1: 0.1476651
50 12 Case 2: 0.1476651
−1
Hint
Suppose dp[i][j] is the probability that j boxes have chocolates after the i-th chocolate
is placed. Initially, dp[1][1]=1. And dp[i][j]=dp[i−1][j]×f(j)+dp[−1][j−1]×f(m−j+1),
x
where f ( x ) = , represents the probability that one chocolate is placed in x boxes,
m
2≤i≤n, 1≤j≤m.
The solution is 1−dp[n][m].
Figure 6.6
for a train to travel between two consecutive stations is fixed since all trains move at
the same speed. Trains make a very short stop at each station, which you can ignore
for simplicity. Since she is a very fast agent, Maria can always change trains at a sta-
tion even if the trains involved stop in that station at the same time.
Input
The input file contains several test cases. Each test case consists of seven lines with
information as follows.
Output
For each test case, print a line containing the case number (starting with 1) and
an integer representing the total waiting time in the stations for a best schedule, or
the word “impossible” in case Maria is unable to make the appointment. Use the
format of the sample output.
296 ◾ Algorithm Design Practice for Collegiate Programming
4 Case Number 1: 5
55 Case Number 2: 0
5 10 15 Case Number 3: impossible
4
0 5 10 20
4
0 5 10 15
4
18
123
5
0 3 6 10 12
6
0 3 5 7 12 15
2
30
20
1
20
7
1 3 5 7 11 13 17
0
Hint
First, the time that each train departing from the first station arrives at each station
x1[ ][ ] and the time that each train departing from the N-th station arrives at each
station x2[ ][ ] are calculated, where the time that the i-th train departing from the
first stationt arrives at the j-th station is x1[i][j]:
and the time that the i-th train departing from the N-th stationt arrives at the j-th
station is x2[i][j]:
States are minimal waiting times at each point in time for each station. Because
for the previous point in time, the waiting time must also be minimal, DP is used
to solve the problem.
Suppose f [j][k] is the minimal waiting time that Maria arrives at the k-th station
at point in time j. Obviously, f [0][1]=0;
Stage i: A stage is a point in time before the time of the appointment, 0≤i≤T−1;
State k: each station is enumerated, 0≤k≤N;
Decision: There are two kinds of decisions, forward and backward:
Forward: Each forward train j which arrives at the k-th station after point in
time i is enumerated (1≤j≤the number of trains departing from the first
station, i≤x1[j][k]). The minimal waiting time that train j arrives at the
(k+1)-th station is f [x1[j][k+1]][k+1]=min{f [x1[j][k+1]][k+1], f [i][k]+x1[j]
[k]−i}.
Backward: Each backward train j which arrives at the k-th station after point
in time i is enumerated (1≤j≤the number of trains departing from the N-
th station, i≤x2[j][k]). The minimal waiting time that train j arrives at the
(k−1)-th station is f [x2[j][k−1]][k−1]=min{f [x2[j][k−1]][k−1], f [i][k]+x1[j]
[k]−i}
Because the time that trains arrive at the (k+1)-th station or the (k−1)-th station
may be after i, we need to adjust: f [i+1][k]=min{f [i+1][k], f [i][k]+1}.
Obviously, if f [T ][N ] is the initial value before DP, Maria is unable to make
the appointment; otherwise, f [T ][N ] is the total waiting time in the stations for a
best schedule.
The forest is beautiful, and Jimmy wants to take a different route every day.
He also wants to get home before dark, so he always takes a path to make progress
towards his house. He considers taking a path from A to B to be progress if there
exists a route from B to his home that is shorter than any possible route from A.
Calculate how many different routes through the forest Jimmy might take.
Input
Input contains several test cases followed by a line containing 0. Jimmy has num-
bered each intersection or joining of paths starting with 1. His office is numbered
1, and his house is numbered 2. The first line of each test case gives the num-
ber of intersections N, 1<N≤1000, and the number of paths M. The following M
lines each contain a pair of intersections a b and an integer distance 1≤d≤1000000
indicating a path of length d between intersection a and a different intersection
b. Jimmy may walk a path any direction he chooses. There is at most one path
between any pair of intersections.
Output
For each test case, output a single integer indicating the number of different routes
through the forest. You may assume that this number does not exceed 2147483647.
5 6 2
1 3 2 4
1 4 2
3 4 3
1 5 12
4 2 34
5 2 24
7 8
1 3 1
1 4 1
3 7 1
7 4 1
7 5 1
6 7 1
5 2 1
6 2 1
0
Hint
First, a weighted graph is constructed. Each intersection is represented as a vertex.
Each path is represented as an edge. And the length for a path is represented as the
weight of the corresponding edge. Jimmy’s office is as vertex 1, and Jimmy’s house
is as vertex 2.
Second, Dijkstra’s algorithm is used to calculate the shortest path dist[] from
each vertex to vertex 2, where dist[i] is the length of the shortest path form vertex i
to vertex 2. Suppose f [x] is the number of paths from vertex x to vertex 2:
1 x=2
n
f [x ] =
∑ ( f [i ]| (i, x ) ∈ E & &dist[i ] < dist[ x ]) x≠2
i =1
Input
The program input is from the standard input. Each data set in the input contains
two strings representing the given sequences. The sequences are separated by any
number of white spaces. The input data are correct.
Output
For each set of data, the program prints on the standard output the length of the
maximum-length common subsequence from the beginning of a separate line.
300 ◾ Algorithm Design Practice for Collegiate Programming
abcfbc abfcab 4
programming contest 2
abcd mnp 0
Hint
The problem is an LCS problem.
Ever the frugal agrarian, Farmer John would like to build a set of just K (1≤K≤N)
rectangular barns (oriented with walls parallel to the pasture’s edges) whose total
area covers the minimum possible number of cells. Each barn covers a rectangular
group of cells in their entirety, and no two barns may overlap. Of course, the barns
must cover all of the cells containing cows.
By way of example, in the picture above, if K=2. then the optimal solution con-
tains a 2×3 barn and a 1×4 barn and covers a total of 10 units of area.
Input
Line 1: Three space-separated integers, N, K, and B.
Practice for Dynamic Programming ◾ 301
Lines 2. N+1: Two space-separated integers in the range (1,1) to (2,B) giv-
ing the coordinates of the cell containing each cow. No cell contains more than
one cow.
Output
Line 1: The minimum area required by the K barns in order to cover all of the
cows.
8 2 9 10
1 2
1 6
1 7
1 8
1 9
2 2
2 3
2 4
Hint
This is a problem for DP with state compression. Suppose dp[i][j][k] represents the
best solution that the first i columns is covered by j barns, and the current state is
k; where k==1 means only the first row is covered by a barn, k==2 means only the
second row is covered by a barn, k==3 means the first row and the second row is
covered by a barn, and k==4 means the first row and the second row are covered
by two different barns.
Sequence 1:
Sequence 2:
Figure 6.7
Input
The input consists of pairs of lines. The first line of a pair contains the first string
and the second line contains the second string. Each string is on a separate line and
consists of at most 1,000 characters.
Output
For each subsequent pair of input lines, output a line containing one integer num-
ber which satisfies the criteria stated above.
Sample Input Sample Output
a1b2c3d4e 4
zz1yy2xx3ww4vv 3
abcdgh 26
aedfhr 14
abcdefghijklmnopqrstuvwxyz
a0b0c0d0e0f0g0h0i0j0k0l0m0n0o0p0q0r0s0t0u0v0w0x0y0z0
abcdefghijklmnzyxwvutsrqpo
opqrstuvwxyzabcdefghijklmn
Hint
This problem is a classical LCS problem.
Here we will make a palindrome generator that will take an input string and
return a palindrome. You can easily verify that for a string of length ‘n’, no more
than (n−1) characters are required to make it a palindrome. Consider “abcd” and
its palindrome “abcdcba” or “abc” and its palindrome “abcba”. But life is not so
easy for programmers!! We always want optimal cost. And you have to find the
minimum number of characters required to make a given string into a palindrome
if you are allowed to insert characters at any position of the string.
Input
Each input line consists only of lowercase letters. The size of the input string will be
at most 1000. Input is terminated by EOF.
Output
For each input, print the minimum number of characters and such a palindrome
separated by one space in a line. There may be many such palindromes. Any one
will be accepted.
abcd 3 abcdcba
aaaa 0 aaaa
abc 2 abcba
aab 1 baab
abababaabababa 0 abababaabababa
pqrsabcdpqrs 9 pqrsabcdpqrqpdcbasrqp
Hint
First, the longest common subsequence of the string and its reverse are calculated.
This will give you the optimal overlap in the palindrome. Then the rest of the char-
acters are added into the string to make the shortest palindrome.
6.4.10 Vacation
You are planning to take some rest and to go on vacation, but you really don’t know
which cities you should visit. So, you ask your parents for help. Your mother says
“My son, you MUST visit Paris, Madrid, Lisbon, and London. But it’s only fun
304 ◾ Algorithm Design Practice for Collegiate Programming
in this order.” Then your father says: “Son, if you’re planning to travel, go first to
Paris, then to Lisbon, then to London and then, at last, go to Madrid. I know what
I’m talking about.”
Now you’re a bit confused, as you didn’t expect this situation. You’re afraid that
you’ll hurt your mother if you follow your father’s suggestion. But you’re also afraid
to hurt your father if you follow your mother’s suggestion. But it can get worse,
because you can hurt both of them if you simply ignore their suggestions!
Thus, you decide that you’ll try to follow their suggestions in the best way that
you can. So, you realize that the “Paris-Lisbon-London” order is the one which
better satisfies both your mother and your father. Afterwards, you can say that you
could not visit Madrid, even though you would’ve liked it very much.
If your father suggested the “London-Paris-Lisbon-Madrid” order, then
you would have two orders, “Paris-Lisbon” and “Paris-Madrid”, which would
better satisfy both of your parents’ suggestions. In this case, you could only
visit two cities.
You want to avoid problems like this one in the future. And what if their travel
suggestions were bigger? Probably you would not find the better way very easily. So,
you decided to write a program to help you in this task. You’ll represent each city
by one character, using uppercase letters, lowercase letters, digits, and the space.
Thus, you can have at most 63 different cities to visit. But it’s possible that you’ll
visit some city more than once.
If you represent Paris with “a”, Madrid with “b”, Lisbon with “c”, and London
with “d”, then your mother’s suggestion would be “abcd” and your father’s sugges-
tion would be “acdb” (or “dacb”, in the second example).
The program will read two travel sequences, and it must answer how many
cities you can travel to such that you’ll satisfy both of your parents and its
maximum.
Input
The input will consist of an arbitrary number of city sequence pairs. The end of
input occurs when the first sequence starts with an “#” character (without the
quotes). Your program should not process this case. Each travel sequence will be
on a line alone and will be formed by legal characters (as defined above). All travel
sequences will appear in a single line and will have at most 100 cities.
Output
For each sequence pair, you must print the following message in a line alone:
Case #d: you can visit at most K cities.
Where d stands for the test case number (starting from 1) and K is the maxi-
mum number of cities you can visit such that you’ll satisfy both your father’s sug-
gestion and your mother’s suggestion.
Practice for Dynamic Programming ◾ 305
Hint
Your mother’s suggestion is the first string, and your father’s suggestion is the second
string. The Longest Common Subsequence (LCS) for the two strings are cities that
you’ll visit to satisfy both your father’s suggestion and your mother’s suggestion.
W[a[1]]<W[a[2]]<...<W[a[n]]
and
S[a[1]]>S[a[2]]>...>S[a[n]].
decreasing. There may be many correct outputs for a given input, but your program
only needs to find one.
6008 1300 4
6000 2100 4
500 2000 5
1000 4000 9
1100 3000 7
6000 2000
8000 1400
6000 1200
2000 1900
Hint
It is a standard DP (Longest Increasing Subsequence) problem. First, n elephants
are sorted. The weight is as the first key. And the IQ is as the second key. Then the
Longest Increasing Subsequence (LIS) for the sorted sequence is calculated.
A box D=(d1, d2, ……, dn) nests in a box E=(e1, e2, ……, en) if there is some
rearrangement of the di such that when rearranged, each dimension is less than the
corresponding dimension in box E. This loosely corresponds to turning box D to
see if it will fit in box E. However, since any rearrangement suffices, box D can be
contorted, not just turned (see examples below).
For example, the box D=(2,6) nests in the box E=(7,3) since D can be rear-
ranged as (6,2) so that each dimension is less than the corresponding dimension in
E. The box D=(9,5,7,3) does NOT nest in the box E=(2,10,6,8), since no rearrange-
ment of D results in a box that satisfies the nesting property, but F=(9,5,7,1) does
nest in box E since F can be rearranged as (1,9,5,7), which nests in E.
Formally, we define nesting as follows: box D=(d1, d2, ……, dn) nests in box
E=(e1, e2, ……, en) if there is a permutation π of 1..n such that (dπ(1), dπ(2), ……, dπ(n))
“fits” in (e1, e2, ……, en), i.e., if dπ(i)≤ei for all dπ(i)≤ei.
Input
The input consists of a series of box sequences. Each box sequence begins with a line
consisting of the number of boxes k in the sequence followed by the dimensionality
of the boxes, n (on the same line).
This line is followed by k lines, one line per box with the n measurements of
each box on one line separated by one or more spaces. The line in the sequence
(1≤i≤k) gives the measurements for the box.
There may be several box sequences in the input file. Your program should pro-
cess all of them and determine, for each sequence, which of the k boxes determine
the longest nesting string and the length of that nesting string (the number of boxes
in the string).
In this problem, the maximum dimensionality is 10 and the minimum dimen-
sionality is 1. The maximum number of boxes in a sequence is 30.
Output
For each box sequence in the input file, output the length of the longest nest-
ing string on one line, followed on the next line by a list of the boxes that
comprise this string in order. The “smallest” or “innermost” box of the nesting
string should be listed first, and the next box (if there is one) should be listed
second, etc.
The boxes should be numbered according to the order in which they appeared
in the input file (the first box is box 1, etc.).
If there is more than one longest nesting string, then any one of them can be
output.
308 ◾ Algorithm Design Practice for Collegiate Programming
5 2 5
3 7 3 1 2 4 5
8 10 4
5 2 7 2 5 6
9 11
21 18
8 6
5 2 20 1 30 10
23 15 7 9 11 3
40 50 34 24 14 4
9 10 11 12 13 14
31 4 18 8 27 17
44 32 13 19 41 19
1 2 3 4 5 6
80 37 47 18 21 9
Hint
This problem is a Longest Increasing Subsequence problem. The problem requires
you to check whether box a fits in box b.
First, for each box, its dimension (s1, s2, s3, ..., sn) is sorted such that si≤sj for all i<j.
Second, boxes are sorted. For two boxes a and b, a<b if ai≤bi for all i.
Finally, the Longest Increasing Subsequence algorithm is used.
The time complexity for the problem is O(n2).
Input
The input for your program will be a series of integer triples, one per line, until
the end-of-file flag of −1 −1 −1. Using the above technique, you are to calculate
w(a, b, c) efficiently and print the result.
Output
Print the value for w(a, b, c) for each triple.
1 1 1 w(1, 1, 1) = 2
2 2 2 w(2, 2, 2) = 4
10 4 6 w(10, 4, 6) = 523
50 50 50 w(50, 50, 50) = 1048576
-1 7 18 w(-1, 7, 18) = 1
-1 -1 -1
Hint
A memorized search is used to solve the problem. Suppose a[][][] is the memorized
list, where a[x][y][z] stores the result for w(x, y, z).
Input
The input consists of an N×N array of integers. The input begins with a single posi-
tive integer N on a line by itself, indicating the size of the square two-dimensional
array. This is followed by N^2 integers separated by white space (spaces and new
lines). These are the N^2 integers of the array, presented in row-major order; that
is, all numbers in the first row, left to right, then all numbers in the second row,
left to right, etc. N may be as large as 100. The numbers in the array will be in the
range [−127,127].
Output
Output the sum of the maximal subrectangle.
4 15
0 -2 -7 0 9 2 -6 2
-4 1 -4 1 -1
8 0 -2
Hint
Suppose max is the sum of the maximal subrectangle, initially max=−10000; and
array m is the input array.
Practice for Dynamic Programming ◾ 311
First, array m is input. For row i, mai is the maximum for sums of continuous
integers, 1≤i≤N. And after array m is input, the maximum max for all maximums
for sums of continuous integers for each row is computed, max = max{mai } .
1≤i ≤ N
Second, from the first row, a for repetition statement deals with every row top-
down. For the current row, integers for its below rows are added into its correspond-
ing columns. The maximum for sums of continuous integers in the current row is
calculated. That is, row by row, for each row, its below row is added into the row.
And max is adjusted after a row is added into the current row, if it isn’t the maximal
value. After the for repetition, max is the sum of the maximal subrectangle.
6.4.15 Robbery
Inspector Robstop is very angry. Last night, a bank has been robbed and the robber
has not been caught. And this has happened already for the third time this year,
even though he did everything in his power to stop the robber: as quickly as possi-
ble, all roads leading out of the city were blocked, making it impossible for the rob-
ber to escape. Then, the inspector asked all the people in the city to watch out for
the robber, but the only messages he received were of the form “We don’t see him.”
But this time, he has had enough! Inspector Robstop decides to analyze how
the robber could have escaped. To do that, he asks you to write a program which
takes all the information the inspector could get about the robber in order to find
out where the robber has been at which time.
Coincidentally, the city in which the bank was robbed has a rectangular shape.
The roads leaving the city are blocked for a certain period of time t, and during that
time, several observations of the form “The robber isn’t in the rectangle Ri at time
Ti ” are reported. Assuming that the robber can move at most one unit per time step,
your program must try to find the exact position of the robber at each time step.
Input
The input contains the description of several robberies. The first line of each descrip-
tion consists of three numbers W, H, t (1≤W, H, t≤100) where W is the width, H is
the height of the city, and t is the time during which the city is locked.
The next line contains a single integer n (0≤n≤100), the number of messages the
inspector received. The next n lines (one for each of the messages) consist of five inte-
gers ti, Li, Ti, Ri, Bi each. The integer ti is the time at which the observation has been
made (1≤ti≤t), and Li, Ti, Ri, Bi are the left, top, right, and bottom respectively of
the (rectangular) area which has been observed. (1≤Li≤Ri≤W, 1≤Ti≤Bi≤H; the point
(1, 1) is the upper left-hand corner, and (W, H) is the lower right-hand corner of the
city.) The messages mean that the robber was not in the given rectangle at time ti.
The input is terminated by a test case starting with W=H=t=0. This case should
not be processed.
312 ◾ Algorithm Design Practice for Collegiate Programming
Output
For each robbery, first output the line “Robbery #k:”, where k is the number of the
robbery. Then, there are three possibilities:
1. If it is impossible that the robber is still in the city considering the messages,
output the line “The robber has escaped.”
2. If it is impossible that the robber is still in the city considering the messages,
output the line “The robber has escaped.” In all other cases, assume that the
robber really is in the city. Output one line of the form “Time step t: The
robber has been at x, y.” for each time step, in which the exact location can
be deduced. (x and y are the column and row of the robber in time step t.)
Output these lines ordered by time t.
3. If nothing can be deduced, output the line “Nothing known.” and hope that
the inspector will not get even more angry.
4 4 5 Robbery #1:
4 Time step 1: The robber has been at 4,4.
1 1 1 4 3 Time step 2: The robber has been at 4,3.
1 1 1 3 4 Time step 3: The robber has been at 4,2.
4 1 1 3 4 Time step 4: The robber has been at 4,1.
4 4 2 4 4
10 10 3 Robbery #2:
1 The robber has escaped.
2 1 1 10 10
0 0 0
Initialize the table to uncomputed for all possible values. Then read the witness input
and mark every rectangle given by them to vacant. Now we can use memoization
to decide which paths lead to a valid city block after the time is over. Start from the
time t, and work back to time 1. A given position (width, height, time) can be reached
only if at least one of its at most five predecessors can be reached (width±1, height±1,
time−1) and (width, height, time−1). Obviously, time=1 is the base case for the recur-
sion. Don’t be greedy; explore all five options, even if the first one works, since we
not only want to determine if the position is feasible, but also if it is unique.
After trying all paths starting at the end time, we can then perform the output.
If there are no places at the finishing time where the robber can be, output that the
robber must have escaped. Otherwise, for each time that there is only one position,
output that position. Finally, if nothing was printed, output “Nothing known.”
Input
The input contains the descriptions of several scenarios in which Trisha tries to escape.
Every description starts with a line containing two integers n and k. n is the number
of cities through which Trisha’s escape may take her, and k is the number of flights she
will take. The cities are numbered 1, 2, ..., n, where 1 is Paris, her starting point, and
n is Atlanta, her final destination. The numbers will satisfy 2≤n≤10 and 1≤k≤1000.
Next you are given n(n −1) flight schedules, one per line, describing the connec-
tion between every possible pair of cities. The first n −1 flight schedules correspond
314 ◾ Algorithm Design Practice for Collegiate Programming
to the flights from city 1 to all other cities (2, 3, ..., n), the next n −1 lines to those
from city 2 to all others (1, 3, 4, ..., n), and so on.
The description of the flight schedule itself starts with an integer d, the length
of the period in days, with 1≤d≤30. Following this are d non-negative integers,
representing the cost of the flight between the two cities on days 1, 2, ..., d. A cost
of 0 means that there is no flight between the two cities on that day.
So, for example, the flight schedule “3 75 0 80” means that on the first day the flight
costs 75, on the second day there is no flight, on the third day it costs 80, and then the
cycle repeats: on the fourth day the flight costs 75, there is no flight on the fifth day, etc.
The input is terminated by a scenario with the formula n=k=0.
Output
For each scenario in the input, first output the number of the scenario, as shown in
the sample output. If it is possible for Trisha to travel k days, starting in city 1, each
day flying to a different city than the day before, and finally (after k days) arriving
in city n, then print “The best flight costs x.”, where x is the least amount that the
k flights can cost.
If it is not possible to travel in such a way, print “No flight possible.”.
Print a blank line after each scenario.
36 Scenario #1
2 130 150 The best flight costs 460.
3 75 0 80
7 120 110 0 100 110 120 0 Scenario #2
4 60 70 60 50 No flight possible.
3 0 135 140
2 70 80
23
2 0 70
1 80
00
Hint
A thief wants to find the cheapest way of travelling to a certain city in exactly k
days. She must make exactly one flight each day.
Practice for Dynamic Programming ◾ 315
Suppose cost[a][b] is the cost to travel to city a on b day. Then cost[a][b] could
be calculated as the minimum of cost[m][b−1] + cost to travel from city m to city a.
Bloggium refinery
N
Yeyenum refinery
W E
Figure 6.8
316 ◾ Algorithm Design Practice for Collegiate Programming
belt immediately, in the same cell (thus they cannot start the transportation in an
adjacent cell). Furthermore, any bloggium transported to the yeyenum refinement
factory will be lost, and vice versa.
Your program has to design a conveyor belt system that maximizes the total
amount of minerals mined, i.e., the sum of the amount of yeyenum transported
to the yeyenum refinery and the amount of bloggium transported to the blog-
gium refinery.
Input
The input contains several blocks of test cases. Each case begins with a line
containing two integers: the number 1≤n≤500 of rows, and the number
1≤m≤500 of columns. The next n lines describe the amount of yeyenum that
can be found in the cells. Each of these n lines contains m integers. The first
line corresponds to the northernmost row; the first integer of each line cor-
responds to the westernmost cell of the row. The integers are between 0 and
1000. The next n lines describe in a similar fashion the amount of bloggium
found in the cells.
The input is terminated by a block with n=m=0.
Output
For each test case, you have to output a single integer on a separate line: the maxi-
mum amount of minerals that can be mined.
4 4 98
0 0 10 9
1 3 10 0
4 2 1 3
1 1 20 0
10 0 0 0
1 1 1 30
0 0 5 5
5 10 10 10
0 0
Hint
Suppose the matrix that describes the amount of yeyenum is A[ ][ ], and the matrix
that describes the amount of bloggium is B[ ][ ]. F[i][j] is the maximum amount
of minerals that can be mined in the matrix whose upper-left corner is (0,0) and
lower-right corner is (i, j), 0≤i≤n−1,0≤j≤m−1.
F[i][j] is calculated from top to down, and from left to right, 0≤i≤n−1,
0≤j≤m−1. That is, before F[i][j] is calculated, F[i−1][j] and F[i][j−1] are cal-
culated. At (i, j), the astronauts can build a south-north conveyor belt for blog-
gium, or they can build a east-west conveyor belt for yeyenum. Therefore,
t j
F [i ][ j ] = Max { F [i ][−1] + ∑
ko 0
B[k ][ j ], F [i − 1][ j ] + ∑ A[i ][k ]}.
ko 0
Obviously, F[n−1][m−1] is the maximum amount of minerals that can be mined.
Every operation you do on the string would count for a unit cost. You’d have to
keep that as low as possible.
For example, to convert “abccda” you would need at least two operations if we
allowed you only to add characters. But when you have the option to replace any
character, you can do it with only one operation. We hope you would be able to use
this feature to your advantage.
Input
The input file contains several test cases. The first line of the input gives you the
number of test cases, T (1≤T≤10). Then T test cases will follow, each in one line.
The input for each test case consists of a string containing lowercase letters only.
You can safely assume that the length of this string will not exceed 1000 characters.
Output
For each set of input, print the test case number first. Then print the minimum
number of characters needed to turn the given string into a palindrome.
318 ◾ Algorithm Design Practice for Collegiate Programming
6 Case 1: 5
tanbirahmed Case 2: 7
shahriarmanzoor Case 3: 6
monirulhasan Case 4: 8
syedmonowarhossain Case 5: 8
sadrulhabibchowdhury Case 6: 8
mohammadsajjadhossain
Hint
Suppose s1…sn is a string, and f [i][j] is the minimum number of characters needed
to turn si…sj into a palindrome, 1≤i≤j≤n.
The length of the current substring l is the current stage, 2≤l≤n. The front
pointer i (1≤i≤n−l+1) for the substring is the current state. The rear pointer is
j=i+l−1. Based on the above successor function, f [i][j] is calculated.
Finally, f [1][n] is the minimum number of characters needed to turn the given
string into a palindrome.
b c b a
c a c c
Practice for Dynamic Programming ◾ 319
(b(bb))(ba)=(bb)(ba) [as bb = b]
= b(ba) [as bb = b]
= bc [as ba = c]
= a [as bc = a]
By adding suitable brackets, bbbba can produce a according to the above mul-
tiplication table.
You are asked to write a program to show the morphing steps of a string into an
expected character, or otherwise, output “None exist!” if the given string cannot be
morphed as expected.
Input
The first line of the input file gives the number of test cases. Each case consists of
two lines. The first line is the starting string, which has at most 100 characters. The
second line is the target character. All characters in the input are within the range
of a−c.
Output
For each test case, your output should consist of several lines, showing the morph-
ing steps of a string into the character. In case there are more than one solution,
always try to start the morphing from the left. Print a blank line between consecu-
tive sets of output.
2 bbbba
bbbba bbba
a bba
bbbba bc
a a
bbbba
bbba
bba
bc
a
Hint
First, the relationships between letters and numbers are as follows: a=0, b=1, c=2.
The table for a special multiplication operator is shown in the following table.
Right
0 1 2
Left
0 1 1 0
1 2 1 0
2 0 2 2
Suppose F[i][j][t] shows whether the interval [i, j] can can produce t or not.
Obviously F[i][i][str[i]−'a']=true. Suppose Fm is used to store how the result is pro-
duced, where Fm[i][j][t][0] stores the intermediate pointer producing t; the result
for the left subinterval [i, Fm[i][j][t][0]] is stored in Fm[i][j][t][1], and the result for
the right subinterval [Fm[i][j][t][0]+1, j] is stored in Fm[i][j][t][2], 1≤i≤j≤n, 0≤t≤2.
DP is used to calculate F[][][] and Fm[][][], where stage l is the length of the
substring, 2≤l≤n; stage i is the front pointer for the current substring, 1≤i≤n−l+1;
the rear pointer j=i+l−1; and decision k (i≤k≤j−1) is the intermediate pointer such
that the left subinterval [i, k] produces a and the right subinterval [k+1, j] produces
b, (0≤a,b≤2, F[i][k][a]&&F[k+1][j][b]=true). The result t (t=mul[a][b]) is stored.
Fm[i][j][t][0]=k, Fm[i][j][t][1]=a, Fm[i][j][t] [2]=b, and F[i][j][t] = true.
Suppose t is the expected character. If f [1][n][t]==false, then output “None
exist!”; else output the morphing steps of a string into the character based on Fm.
Input
There will be as many as 100 cases in the input file. Each case of input has two
lines. The first line contains a positive integer, where n indicates the number
Practice for Dynamic Programming ◾ 321
of contestants available for selection. The next line will contain n positive
integers, each of which will be at most 30. End of input is indicated by a value
of 0 for n.
Output
For every case of input, there will be one line of output. This line should contain
the case number followed by the maximum number of promising teams that can be
formed. Note that it is not mandatory to assign everyone in a team. In case you
don’t know, each team consists of exactly three members.
Constraint: n≤15
9 Case 1: 3
22 20 9 10 19 30 2 4 1 Case 2: 0
6
2
15 3
0
Hint
Suppose S is a sequence of contestants’ ability points, and best(S) is the maximum
number of promising teams that can be formed.
The problem is solved with its subproblem as such:
If (|S|<3)
best(S)=0;
1 ai + aj + ak ≥ 20
else best(S = {a1 , a2 ,..., an }) = max(best S − ai − aj − ak ) + .
otherwise
0
i,j,k
1. All the strings are composed of ASCII characters in the range 33 to 127.
2. Any of the short strings or their reversed forms can be used any number of
times to construct the long string.
3. Each use of a short string or its reverse would be counted as one occurrence
of that short string.
When you construct the longer string from these short strings, you should
ensure that it is done by keeping the total occurrences of the short strings to a
minimum.
For example, if we want to construct the string “aabbabbabbbb” from the set
{“a”, “bb”, “abb”}, there can be many ways to achieve the goal. “a-abb-abb-abb-bb”
and “a-abb-a-bba-bb-bb” are two such valid constructions. However, we would pre-
fer “a-abb-abb-abb-bb” (five substrings) over “a-abb-a-bba-bb-bb” (six substrings)
because it uses a lesser number of substrings. You would only need to find the
minimum number of substrings that could be used to construct the given string.
Input
The first line of the the input contains S (S<51), the number of data sets. Then
S number of data sets follows. The first line of each data set contains the long
string, P (0<length(P)<10001). The next line contains the number of short strings,
N (0<N<51) to choose from. Each of the next N lines contain the short string
Pi (0<length(Pi)<101) [ i≥1,2,3?N ]. You can safely assume that there is no blank/
empty line in the input file.
Output
For each data set print exactly one line of output.
Either Set S: C;
Or S: Not possible.
If it is possible to construct the string using the given strings, then print the first
line; otherwise, print the second line. Here S is the serial of data set (sequentially
from 1 to S) and C is the minimum number of times the substrings were used to
construct P. For clarification see the sample output below.
2 Set 1: 5.
aabbabbabbbb Set 2: Not possible.
3
a
Practice for Dynamic Programming ◾ 323
bb
abb
ewu**bbacsecsc
4
ewu
bba
cse
csc
Hint
A graph is constructed as follows. Spaces between the characters are as vertices, and
the characters are edges. Therefore, two vertices are connected if the string between
them is located in given shorter strings (or the reverse). Then it’s just a standard DP
problem or a standard Shortest Path problem.
The graph is constructed in O(n2m), where n is the length of the longer string,
and m is the length of the shorter string. The problem is strictly O(n2m) as that is
the amount of data we’re given.
6.4.22 Rivers
Nearly all of the Kingdom of Byteland is covered by forests and rivers. Small riv-
ers meet to form bigger rivers, which also meet and, in the end, all the rivers flow
together into one big river. The big river meets the sea near Bytetown.
There are n lumberjacks’ villages in Byteland, each placed near a river.
Currently, there is a big sawmill in Bytetown that processes all trees cut in the
Kingdom. The trees float from the villages down the rivers to the sawmill in
Bytetown. The king of Byteland decided to build k additional sawmills in vil-
lages to reduce the cost of transporting the trees down river. After building the
sawmills, the trees need not float to Bytetown, but can be processed in the first
sawmill they encounter down river. Obviously, the trees cut near a village with
a sawmill need not be transported by river. It should be noted that the rivers in
Byteland do not fork. Therefore, for each village, there is a unique way down river
from the village to Bytetown.
The king’s accountants calculated how many trees are cut by each village per year.
You must decide where to build the sawmills to minimize the total cost of transport-
ing the trees per year. River transportation costs one cent per kilometre, per tree.
324 ◾ Algorithm Design Practice for Collegiate Programming
◾◾ reads from the standard input the number of villages, the number of addi-
tional sawmills to be built, the number of trees cut near each village, and
descriptions of the rivers,
◾◾ calculates the minimal cost of river transportation after building additional
sawmills,
◾◾ writes the result to the standard output.
Figure 6.9 illustrates the example input data. Village numbers are given inside
circles. Numbers below the circles represent the number of trees cut near villages.
Numbers above the arrows represent the rivers’ lengths.
The sawmills should be built in villages 2 and 3.
Input
The first line of input contains two integers: n—the number of villages other
than Bytetown (2≤n≤100), and k—the number of additional sawmills to be built
(1≤k≤50 and k≤n). The villages are numbered 1,2, . . . , n, while Bytetown has
number 0.
Each of the following n lines contains three integers, separated by single spaces.
Line i+1 contains:
It is guaranteed that the total cost of floating all the trees to the sawmill in
Bytetown in one year does not exceed 2000000000 cents.
In 50 percent of test cases, n will not exceed 20.
3
10
5
Bytetown
0 2
1
1 10 3
1 4
1 1
Figure 6.9
Practice for Dynamic Programming ◾ 325
Output
The first and only line of the output should contain one integer: the minimal cost
of river transportation (in cents).
4 2 4
1 0 1
1 1 10
10 2 5
1 2 3
Hint
A directed graph is constructed as follows. n villages are represented as vertices
(numbered from 1 to n), and the number of trees cut near village i per year is the
weight for vertex i; there is an edge from a village to its first village (or Bytetown)
down river, and the distance between the two villages is the weight for the edge;
and Bytetown is vertex 0. The problem requires you to select k villages to build
sawmills to reduce the cost of transporting the trees down river. That is, k villages
constitute a set A. For each vertex i (i∉A), there is a vertex j (j∈A) such that there is a
path from vertex i to j, and the path is also the shortest path from vertex i to vertices
in A, that is, in the path there are no other vertices in A. The length of the path ×
the weight of vertex i is the cost of transporting the trees for village i. The problem
requires you to calculate the minimal cost of river transportation. Obviously, the
problem is a problem for DP on a tree.
For vertex i, its parent pointer is pa[i], its right child is ch[i], and its left sibling
is b[i], 1≤i≤n.
The current vertex is cur, and its parent is r. In the subtree whose root is cur, l
sawmills are built. The minimal cost of river transportation is f [cur][r][l]. A recur-
sive function dfs(cur, r, l, tot) calculates f [cur][r][l], where tot is the length of the
path from r to the nearest sawmill.
The end condition of recursion: If cur is a leaf (cur==−1), if there is no sawmill
to be built (l==0), return 0; else return ∞.
If cur isn’t a leaf, there are two choices;
sibling (the length of the path from r to the nearest sawmill is still tot). The
minimal cost of river transportation is
{
D1= min dfs ( ch [ cur ] , cur , i , 0 )+ dfs (b [ cur ] , r , l −1−i , tot ) ;
0≤i ≤l −1
}
2. At vertex cur there is no sawmill.
The cost of river transportation from vertex cur to the nearest sawmill is
(tot+d[cur])×w[cur]. l sawmills are built in the subtree for cur (the length of
the path from vertex cur to the nearest sawmill is tot+d[cur]), and the subtree
for cur’s left sibling (the length of the path from r to the nearest sawmill is still
tot). The minimal cost of river transportation is:
{
D 2 = min dfs ( ch [ cur ] , r , i , tot + d [ cur ])+ dfs (b [ cur ] , r , l −i , tot )
0≤i ≤
}
+ (tot + d [ cur ])× w [ cur ].
Input
The input file starts with a number q (q≤20) on the first line, which is the number
of test cases. Each test case starts with a line with two integers n and m, which are
the number of islands and the number of bridges in the map, respectively. The next
line contains n positive integers, the i-th number being the Vi value of island i.
Each value is no more than 100. The following m lines are in the form x y, which
Practice for Dynamic Programming ◾ 327
indicates that there is a (two-way) bridge between island x and island y. Islands are
numbered from 1 to n. You may assume there will be no more than 13 islands.
Output
For each test case, output a line with two numbers, separated by a space. The first
number is the maximum value of a best triangular Hamilton path; the second
number should be the number of different best triangular Hamilton paths. If the
test case does not contain a Hamilton path, the output must be ‘0 0’.
Note: A path may be written down in the reverse order. We still think it is the
same path.
2 22 3
3 3 69 1
2 2 2
1 2
2 3
3 1
4 6
1 2 3 4
1 2
1 3
1 4
2 3
2 4
3 4
Hint
A graph is constructed as follows. Islands are represented as vertices, bridges are
represented as edges, and positive integers associated with islands are represented as
weights associated with corresponding vertices. A state for a circuit is represented as
a binary number with n digits d n −1 … d 0 . If vertex i is in the circuit, di+1=0; other-
wise di+1=1. A circuit is marked by its last edge and its state. Suppose f [ ][ ][ ] and
way[ ][ ][ ] are used to store the best triangular Hamilton path, where the last edge in
the circuit is (i, j), and the the state value for the circuit is k. The value of the circuit
whose state is k is f [i][j][k], and the number of edges in the circuit is way[i][j][k].
328 ◾ Algorithm Design Practice for Collegiate Programming
Queues Q1[ ], Q2[ ], and Q3[ ] are used to store the two vertices for the last
edge and the state for the circuit respectively; and IN[ ][ ][ ] is used to store marks
that the circuit exists.
Initially, f [i ][0][2i −1 ] = the weight of vertex i ; way[i ][0][2i −1 ] = 1 ;
i −1
IN [i ][0][2 ] = true; i, 0 and 2i−1 are stored in Q1[ ], Q2[ ], and Q3[ ] respectively,
1≤i≤n.
BFS is used for states’ transition and to calculate all circuits:
◾◾ Delete fronts of queues (last edge (y, x) and state z), each unvisited vertex xt
which is adjacent to vertex x (( x , xt ) ∈ E , z & (2 xt −1 ) = = 0) is analyzed:
◾◾ Edge (x, xt) is added into the circuit. The state for the circuit becomes
zt = z + 2 xt −1. The value of the circuit is adjusted as tmp=f [x][y][z]+the weight
of vertex xt+the weight of vertex x×the weight of vertex xt. If vertices y, x, and
xt constitute a triangle (y&&(y, xt)∈E ), tmp=tmp+the weight of vertex y×
the weight of vertex x× the weight of vertex xt;
◾◾ If the value of the current Hamilton path is maximal (tmp>f [xt][x][zt]), then
f [xt][x][zt]=tmp, and the number of edges is noted (way[xt][x][zt]=way[x][y][z]).
If (IN[xt][x][zt]==false), then edge (x, xt) and zt is added into queues Q1[ ],
Q2[ ], and Q3[ ] respectively, and IN[xt][x][zt]=true;
◾◾ If the value of the current Hamilton path is the same as f [xt][x][zt] (tmp==f [xt]
[x][zt]), then way[xt][x][zt]=way[xt][x][zt]+way[x][y][z];
ans = ∑
1≤i ≤ n ,0 ≤ j ≤ n ,1≠ j
(way[i ][ j ][2n − 1]| f [i ][ j ][2n − 1]} = max).
If the number of vertices n>1, the number of different best triangular Hamilton
paths is ans/2 (because of the symmetry in an undirected graph); if n==1, the num-
ber of different best triangular Hamilton paths is ans.
Input
Input will consist of multiple test cases. The first line will contain a single integer n
indicating the number of orders to deliver, where 1≤n≤10. After this will be n+1 lines
each containing n+1 integers indicating the times to travel between the pizzeria (num-
bered 0) and the n locations (numbers 1 to n). The j-th value on the i-th line indicates
the time to go directly from location i to location j without visiting any other locations
along the way. Note that there may be quicker ways to go from i to j via other loca-
tions, due to different speed limits, traffic lights, etc. Also, the time values may not be
symmetric, i.e., the time to go directly from location i to j may not be the same as the
time to go directly from location j to i. An input value of n=0 will terminate input.
Output
For each test case, you should output a single number indicating the minimum
time to deliver all of the pizzas and return to the pizzeria.
3 8
0 1 10 10
1 0 1 2
10 1 0 10
10 2 10 0
0
Hint
Suppose the state for the path is represented as a binary number D=dn…d0, where
1 Vertex i is on the path
di = (0 ≤ i ≤ n);
0 Vertex i isn’t on the path
f [i][k] is the minimum time that the pizzeria (numbered 0) is the start, the state
for the path is k, and i is the end (0≤i≤n, 0 ≤ k ≤ 2n+1 −1).
First, the Floyd algorithm is used to calculate the shortest paths between any two
vertices in the directed graph map[ ][ ]. Obviously, initially f [i ][2i−1 ]= map[0][i ].
Then Dynamic Programming of State Compression is used to calculate f [ ][ ]:
All possible states of paths i are enumerated (0≤i≤2n);
330 ◾ Algorithm Design Practice for Collegiate Programming
Vertices j and k are enumerated (1≤j, k≤n), where vertice j is in the state of
the path (i &(2 j −1 ) =1) , and vertice k isn’t in the state of the path (i &(2k −1 ) = 0);
f [k ][i + 2k −1 ]= Min{ f [k ][i + 2k −1 ], f [ j ][i ]+ map[ j ][k ]} is calculated.
Obviously, the minimum time to deliver all of the pizzas and return to the piz-
zeria is ans = min{ f [i ][2n −1]+ map[i ][0]} .
1≤i ≤n
92 –200 95 92 95 92 95
+2
00
83 –200 87 83 87 83 87
+2
00
0
71 –200 74 71 74 71 74
–20
Figure 6.10
Practice for Dynamic Programming ◾ 331
Input
The input consists of up to 50 test cases. Each case starts with a positive integer n
(n≤1000) on the first line, which is the number of horses on each side. The next n
integers on the second line are the speeds of Tian’s horses. Then the next n integers
on the third line are the speeds of the king’s horses. The input ends with a line that
has a single “0” after the last test case.
Output
For each input case, output a line containing a single number, which is the maxi-
mum money Tian Ji will get, in silver dollars.
3 200
92 83 71 0
95 87 74 0
2
20 20
20 20
2
20 19
22 18
0
Source: ACM Shanghai 2004
IDs for Online Judge: POJ 2287, ZOJ 2397, UVA 3266
Hint
The speeds of Tian’s horses and the speeds of the king’s horses are sorted in descend-
ing order respectively. If the king’s horses participating in the horse racing are in
this order, then Tian will let the current slowest horse or the current fastest horse
332 ◾ Algorithm Design Practice for Collegiate Programming
participate in the horse racing each time. If the king’s current fastest horse can defeat
Tian’s any current horse, it defeats Tian’s current slowest horse. If the king’s current
fastest horse can be defeated, Tian’s current fastest horse defeating it is suitable.
Suppose f [i][j] is the maximum silver dollars Tian will get when Tian can use
horse from number i to number j, and the king’s current horse is horse j−i+1.
Obviously, f [1][n] is the solution to the problem.
where a[ ] is Tian’s horse, b[ ] is the king’s horse, and cmp is the result that the two
horses race.
Input
Your program reads from standard input. The first line contains the number of
jobs N, 1≤N≤10000. The second line contains the batch setup time S which is an
integer, 0≤S≤50. The following N lines contain information about the jobs 1, 2,...,
N in that order as follows. First on each of these lines is an integer Ti, 1≤Ti≤100,
the processing time of the job. Following that, there is an integer Fi, 1≤Fi≤100, the
cost factor of the job.
Practice for Dynamic Programming ◾ 333
Output
Your program writes to standard output. The output contains one line, which con-
tains one integer: the minimum possible total cost.
5 153
1
1 3
3 2
4 3
2 3
1 4
Source: IOI 2002
IDs for Online Judge: POJ 1180
ir < ir −1 <…< i2 < i1 and g(ir , ir −1 ) > g(ir −1 ir −2 ) >….. > g (i2 , i1 ) -------- (1)
When Ci is calculated,
Each i is inserted into Q and deleted from Q at most once. In each insertion and
deletion, it takes a constant time. Therefore, the time complexity is O(n).
Chapter 7
In this chapter, experiments for some frequently used data structures are discussed
as follows:
335
336 ◾ Algorithm Design Practice for Collegiate Programming
a a b a a a a b String S
b suffix(8)
a b suffix(7)
a a b suffix(6)
a a a b suffix(5)
a a a a b suffix(4)
b a a a a b suffix(3)
a b a a a a b suffix(2)
a a b a a a a b suffix(1)
Figure 7.1
All suffixes for a string can be sorted in lexicographic order. For a string whose
length is n, there are n different suffixes. A suffix array SA and a rank array Rank
are used to represent sorting the n suffixes.
x is the rank for its left substring, that is, its starting position is i, and its length
is 2k −1 , that is, x is Rank[i] for the last Rank;
y is the rank for its right substring, that is, its starting position is i+2k−1, and its
length is 2k −1 , that is, y is Rank[i + 2k −1 ] for the last Rank.
Practice for Advanced Data Structures ◾ 337
Rank = 4 6 8 1 2 3 5 7
a a b a a a a b
sa[1] =4 a a a a b
sa[2] =5 a a a b
sa[3] =6 a a b
sa[4] =1 a a b a a a a b
sa[5] =7 a b
sa[6] =2 a b a a a a b
sa[7] =8 b
sa[8] =3 b a a a a b
Figure 7.2
k=0, substrings whose starting position is every character and length is 20 =1 are
sorted. Rank[1..8]={1, 1, 2, 1, 1, 1, 1, 2}.
k=1, substrings whose starting position is every character and length is 21=2 are
sorted. That is, based on the previous rank values x and y, key xy[1..8]={11,12,
21,11,11,11,12,20}. And Rank[1..8]={1, 2, 4, 1, 1, 1, 2, 3}.
k=2, substrings whose starting position is every character and length is 22=4 are
sorted. Key xy[1..8]={14, 21, 41, 11, 12, 13, 20, 30}. And Rank[1..8]={4, 6, 8,
1, 2, 3, 5, 7}.
k=3, substrings whose starting position is every character and length is 23 =8 are
sorted. Key xy[1..8]={42, 63, 85, 17, 20, 30, 50, 70}. And Rank[1..8]={4, 6,
8, 1, 2, 3, 5, 7}.
a a b a a a a b
Sorting 1
rank 1 1 2 1 1 1 1 2 Length is 1
x y 1 1 1 2 2 1 1 1 1 1 1 1 1 2 2 0
Sorting 2
rank 1 2 4 1 1 1 2 3 Length is 2
x y 1 4 2 1 4 1 1 1 1 2 1 3 2 0 3 0
Sorting 3
rank 4 6 8 1 2 3 5 7 Length is 4
x y 4 2 6 3 8 5 1 7 2 0 3 0 5 0 7 0
Sorting 4
rank 4 6 8 1 2 3 5 7 Length is 5
Figure 7.3
{
for (int k =1; k>=0;k --)
{
memset(c, 0, sizeof(c));
for (int i=r; i>=l; i --)
add_value(val[pos[i]][k], pos[i], i);
int t = 0;
for (int i =0; i<=20000; i ++)
for (int j=c[i]; j; j=d[j].next) pos[++t]=d[j].now;
}
int t=0;
for (int i=1; i<=n; i ++) {
if (val[pos[i]][0]!=val[pos[i-1]][0]||val[pos[i]]
[1]!=val[pos[i-1]][1]) t++;
Rank[pos[i]] = t;
}
}
void add_value(int u, int v, int i)
{
d[i].next=c[u]; c[u]=i;
d[i].now=v;
}
a a b a a a a b
height
a a a a b sa[1]=4
3
a a a b sa[2]=5
2
a a b sa[3]=6
3
a a b a a a a b sa[4]=1
1
a b sa[5]=7
2
a b a a a a b sa[6]=2
0
b sa[7]=8
1
b a a a a b sa[8]=3
Figure 7.4
1. Based on the rank array Rank[ ] and the array for the longest common
prefix height[ ], brute-force searches can be avoided and algorithms can be
optimized;
2. The efficiency for calculating the rank array Rank[ ] and the array for the
longest common prefix height[ ] can be improved. Calculating a rank array
Rank[ ] and the array for the longest common prefix height[ ] can also be
implemented as standard program segments.
Input
The input contains several test cases. The first line of each test case contains the
integer N. The following N integers represent the sequence of notes.
The last test case is followed by one zero.
Use scanf instead of cin to reduce the read time.
342 ◾ Algorithm Design Practice for Collegiate Programming
Output
For each test case, the output file should contain a single line with a single integer
that represents the length of the longest theme. If there are no themes, output 0.
30 5
25 27 30 34 39 45 52 60 69 79 69 60 52 45
39 34 30 26 22 18 82 78 74 70 66 67 64
60 65 80
0
Source: LouTiancheng@POJ
IDs for Online Judges: POJ 1743
Analysis
One application of suffix arrays is to compute the length of the longest disjoint
repeating substrings in a string. First, we need to determine two substrings whose
length is k are the same and disjoint. The length of the longest common prefix,
array height[ ], is used to solve the problem. Sorted suffixes are divided into several
groups, where in each group suffixes’ height aren’t less than a number. For example,
there is a string “aabaaaab”. If k=2, suffixes for “aabaaaab” are divided into four
groups, as shown in Figure 7.5.
a a b a a a a b
height
a a a a b sa[1]=4
3 Group 1
a a a b sa[2]=5
2
a a b sa[3]=6
3
a a b a a a a b sa[4]=1
k=2 1
a b sa[5]=7 Group 2
2
a b a a a a b sa[6]=2
0
b sa[7]=8 Group 3
1
b a a a a b sa[8]=3 Group 4
Figure 7.5
Practice for Advanced Data Structures ◾ 343
Obviously, the two suffixes whose suffixes’ height are less than k must be in a
group. Then, for each group, we need to determine whether the difference between
the maximum and the minimum for suffixes’ SA is less than k or not. If the differ-
ence is less than k, then there exist two suffixes whose length of the longest disjoint
repeating substrings is less than k; else there isn’t such a pair of suffixes. For example,
in group 1, there exist two suffixes whose length of the longest disjoint repeating
substrings is less than 3 (height[2]=height[4]=3), and the difference between the
maximum and the minimum for suffixes’ SA is SA[3]−SA[4]=6−1=5>3. Therefore,
the longest disjoint repeating substring is “aab”, and it appears two times.
The algorithm is as follows:
First, a string a is input and pretreated. Because of transposition, the current number
subtracts the previous number. A new string whose length is n−1 is generated.
Second, for the new string, the longest common prefix, array height[ ], is calculated.
Program
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <string>
344 ◾ Algorithm Design Practice for Collegiate Programming
#include <map>
#include <utility>
#include <vector>
#include <set>
#include <algorithm>
#define maxn 20010 //the upper limit of the length for the
sequence of notes
#define Fup(i,s,t) for (int i=s; i <=t; i ++) //Increasing
loop
#define Fdn(i,s,t) for (int i = s; i >= t; i --) //Descending
loop
#define Path(i,s) for (int i=s; i; i=d[i].next) //Singly
Linked List d[]
using namespace std;
struct node {int now, next;}d[maxn]; // d[], where d[].now
is the sequence number for an element, and d[].next is the
successor pointer
int val[maxn][2], c[maxn], rank[maxn], sa[maxn], pos[maxn],
h[maxn], height[maxn], x[maxn]; //x[]: the sequence of
notes is transposed; val[][]: keys, where x is val[][0], y is
val[][1]; c[ ] stores elements’ front pointers in d[ ]; Rank[]
stores suffixes’ rank; SA[] stores the starting position for
suffixes; height[] is the array for the longest common prefix;
h[i]=height[Rank[i]]
int n; // the length of the sequence of notes
void add_value(int u, int v, int i) //add an element into d[]
{
d[i].next = c[u]; c[u] = i;
d[i].now = v;
}
void radix_sort(int l, int r) // val[][0] and val[][1]
are combined into xy, calculate Rank[l…r] that substring’s
length is t
{
Fdn(k, 1, 0){
memset(c, 0, sizeof(c));
Fdn(i, r, l) add_value(val[pos[i]][k], pos[i], i);
int t = 0;
Fup(i, 0, 20000)
Path(j, c[i])
pos[++ t] = d[j].now;
}
int t = 0;
Fup(i, 1, n){
if (val[pos[i]][0] != val[pos[i - 1]][0] ||
val[pos[i]][1] != val[pos[i - 1]][1])
t ++;
rank[pos[i]] = t;
}
}
Practice for Advanced Data Structures ◾ 345
now ++;
h[i] = now;
}
}
Fup(i, 1, n) height[rank[i]] = h[i];
}
int binary_search(int l, int r) //using binary search to
calculate the length of the longest disjoint repeating
substring
{
while (l <= r){
int mid = (l + r) / 2;
if (exist(mid)) //If there exists a disjoint
repeating substring whose length is mid, search the left
interval; else search the right interval
l = mid + 1;
else
r = mid - 1;
}
return r; //return the length
}
void solve() //compute and output the length of the longest
theme
{
Fup(i, 1, n - 1) //For two adjacent notes, subtract the
previous note from the current note, a new string is formed
rank[i] = x[i]= x[i + 1] - x[i] + 88;
n --; //the length of the new string
get_suffix_array(); //calculate Rank[]
get_common_prefix(); // calculate height[]
int ans = binary_search(0, n) + 1; // using binary
search to calculate the length of the longest disjoint
repeating substring
ans = ((ans < 5) ? 0 : ans); // at least five notes
long
printf("%d\n", ans); //output the length of the longest
theme
}
int main()
{
while (scanf("%d\n", &n), n > 0){
Fup(i, 1, n)scanf("%d", &x[i]); // the sequence of
notes
solve(); // calculate output the length of the
longest theme
}
return 0;
}
Practice for Advanced Data Structures ◾ 347
Given two strings A, B and one integer K, we define S, a set of triples (i, j, k):
S = {(i , j , k )|k ≥ K , A(i , k )= B ( j , k )}.
Input
The input file contains several blocks of data. For each block, the first line contains
one integer K, followed by two lines containing strings A and B, respectively. The
input file is ended by K=0. 1≤|A|,|B|≤105, 1≤K≤min{|A|,|B|}. Characters of A and B
are all Latin letters.
Output
For each case, output an integer |S|.
2 22
aababaa 5
abaabaa
1
xx
xx
0
Source: POJ Monthly, 2007.10.06, wintokk
ID for Online Judge: POJ 3415
Analysis
The problem requires you to calculate the number of common substrings whose
length isn’t less than k for two strings A, B.
In the previous problem, array height[ ] is the length of the longest common
prefix for two suffixes whose ranks are adjacent. In this problem, array height[ ]
is the number of common substrings whose length isn’t less than k for the longest
common prefix for two suffixes whose ranks are adjacent. If height[i]−k+1>0, then
348 ◾ Algorithm Design Practice for Collegiate Programming
there are height[i]−k+1 common substrings whose length is k for two suffixes whose
ranks are i and i−1 respectively, and height[i]←height[i]−k+1; else there are no com-
mon substrings whose length is k for the two suffixes. Therefore, the idea for solving
the problem is as follows.
Calculate the length of the longest common prefix for all suffixes for strings A,
B, and accumulate the number of common substrings whose length isn’t less than k.
The algorithm is as follows. Strings A and B adjoin. And a character (e.g., “$”)
which doesn’t appear is inserted into the string to separate Strings A and B. Based
on array height[ ], strings are divided into several groups. For each group, the num-
ber of common substrings whose length isn’t less than k is calculated. For each
suffix for B, calculate the number of common substrings whose length isn’t less
than k for the longest common prefix for all suffixes for A. And for each suffix
for A, calculate the number of common substrings whose length isn’t less than k for
the longest common prefix for all suffixes for B.
Program
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <string>
#include <map>
#include <utility>
#include <vector>
#include <set>
#include <algorithm>
#define maxn 200010
#define Fup(i, s, t) for (int i = s; i <= t; i ++)
#define Fdn(i, s, t) for (int i = s; i >= t; i --)
#define Path(i, s) for (int i = s; i; i = d[i].next)
using namespace std;
struct node {int now, next;}d[maxn]; // d[], where d[].now
is the sequence number for an element, and d[].next is the
successor pointer
int val[maxn][2], c[maxn], rank[maxn], sa[maxn], pos[maxn],
h[maxn], height[maxn], x[maxn], sta[maxn], num1[maxn],
num2[maxn]; //x[] is a combined array; val[][] are keys,
where x is val[][0], and y is val[][1]; c[] stores front
pointers for elements in d[]; Rank[], SA[] and height[] have
been defined; h[i]=height[Rank[i]]; h[i]=height[Rank[i]];
string S, s; // two strings for a test case
Practice for Advanced Data Structures ◾ 349
int n, k;
void add_value(int u, int v, int i) // add an element into d[]
{
d[i].next = c[u]; c[u] = i;
d[i].now = v;
}
void radix_sort(int l, int r) // val[][0] and val[][1] are
combined into xy, calculate Rank[l…r] that substring’s length
is t
{
Fdn(k, 1, 0){
memset(c, 0, sizeof(c));
Fdn(i, r, l)
add_value(val[pos[i]][k], pos[i], i);
int t = 0;
Fup(i, 0, 200000)
Path(j, c[i])
pos[++ t] = d[j].now;
}
int t = 0;
Fup(i, 1, n){
if (val[pos[i]][0] != val[pos[i - 1]][0] ||
val[pos[i]][1] != val[pos[i - 1]][1])
t ++;
rank[pos[i]] = t;
}
}
void get_suffix_array() //calculate Rank[] and SA[]
{
int t = 1;
while (t / 2 <= n){
Fup(i, 1, n){
val[i][0] = rank[i];
val[i][1] = (((i + t / 2 <= n) ? rank[i + t / 2] :
0));
pos[i] = i;
}
radix_sort(1, n);
t *= 2;
}
Fup(i, 1, n)
sa[rank[i]] = i;
}
void get_common_prefix() //Calculating the array for the
longest common prefix height[ ]
{
memset(h, 0, sizeof(h));
Fup(i, 1, n){
if (rank[i] == 1)
h[i] = 0;
350 ◾ Algorithm Design Practice for Collegiate Programming
else{
int now = 0;
if (i > 1 && h[i - 1] > 1)
now = h[i - 1] - 1;
while (now + i <= n && now + sa[rank[i] - 1] <= n
&& x[now + i] == x[now + sa[rank[i] - 1]])
now ++;
h[i] = now;
}
}
Fup(i, 1, n)
height[rank[i]] = h[i];
}
void get_ans() //calculate the number of common substrings
whose length isn’t less than k
{
Fup(i, 2, n)
height[i] -= k - 1;
long long sum1 = 0, sum2 = 0, ans = 0;
int top = 0;
Fup(i, 2, n)
if (height[i] <= 0){
top = sum1 = sum2 = 0;
}else{
sta[++ top] = height[i];
if (sa[i - 1] <= (int)S.size()){
num1[top] = 1; num2[top] = 0;
sum1 += (long long)sta[top];
}else{
num1[top] = 0; num2[top] = 1;
sum2 += (long long)sta[top];
}
while (top > 0 && sta[top] <= sta[top - 1]){
sum1 = sum1 - (long long)sta[top - 1] *
num1[top - 1] + (long long)sta[top] * num1[top - 1];
sum2 = sum2 - (long long)sta[top - 1] *
num2[top - 1] + (long long)sta[top] * num2[top - 1];
num1[top - 1] += num1[top];
num2[top - 1] += num2[top];
sta[top - 1] = sta[top];
top --;
}
if (sa[i] <= (int)S.size())
ans += sum2;
else
ans += sum1;
}
cout << ans << endl;
}
void init() //Input the current test case (two strings) and
are combined into array x[]
Practice for Advanced Data Structures ◾ 351
{
cin >> S >> s;
n = (int)S.size() + s.size() + 1;
string str = S + '$' + s;
Fup(i, 1, n)
x[i] = rank[i] = (int)str[i - 1];
}
void solve() //calculate the number of common substrings
whose length isn’t less than k
{
get_suffix_array();
get_common_prefix();
get_ans();
}
int main()
{
ios::sync_with_stdio(false);
while (cin >> k, k > 0){
init();
solve();
}
return 0;
}
Input
The first line of input file contains initial text.
The second line contains the number of commands n. And the following n lines
describe each command. There are two formats of commands:
I ch p: Insert a character ch before the p-th. If p is larger than the current length
of text, then insert at end of the text.
Q i j: Ask the length of matching started from the i-th and j-th character of the
initial text, which doesn’t include the inserted characters.
352 ◾ Algorithm Design Practice for Collegiate Programming
You can assume that the length of initial text will not exceed 50000, the num-
ber of I commands will not exceed 200, and the number of Q commands will not
exceed 20000.
Output
Print one line for each Q command, containing the max length of matching.
abaab 0
5 1
Q 1 2 0
Q 1 3 3
I a 2
Q 1 2
Q 1 3
Source: POJ Monthly, 2006.02.26, zgl & twb
ID for Online Judge: POJ 2758
Analysis
Jiajia will be given a string of text consisting of English letters, and he must count
the maximum number of letters that can be matched, starting from position two
of the current text simultaneously. That is, given a string, the longest common
prefix is required to calculate. Based on the definition of the longest common
prefix, the longest common prefix for suffix(j) and suffix(k) (Rank[j]<Rank[k]) is
min{height[Rank[j]+1], height[Rank[j]+2], …, height[Rank[k]]}, 1≤j<k≤length(S).
Dynamic programming is used to calculate the minimal values of height[] for
all subintervals. A two-dimensional array f is used to store results, where f [i, j]
stores the minimal height in the subinterval [j, j+2i−1].
Therefore, for suffixes suffix[a] and suffix[b], the max length of matching is
the minimal values of height[] for the rank interval [l, r], where l=min(Rank[a],
Rank[b])+1, r=max(Rank[a], Rank[b]).
Suppose cor[k] is the current position for the character whose initial position is
k; dis[k] is the distance between the character whose initial position is k, and the
recently inserted character right; opp[i] is the initial position for the current i-th
character.
Practice for Advanced Data Structures ◾ 353
1. If Ranks for suffix[a] and suffix[b] are same (l>r), the max length of matching
is the length of the suffix suffix[a], that is, the length of string s−cor[a]+1;
2. If there is no inserted character in the max matching (the minimal values of
height[] for the rank interval [l, r] is less than dis[a] and dis[b]), the max length
of matching is the minimal values of height[] for the rank interval [l, r];
3. Otherwise, the max length of matching is len=min(dis[a], dis[b]) at least.
Then the max length of matching len is calculated through a loop statement,
and the condition for the loop statement is cor[a]+len≤the length of the string
s&&cor[b]+len≤the length of the string s.
Program
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <string>
#include <map>
#include <utility>
#include <vector>
#include <set>
#include <algorithm>
#define maxn 50210 //the upper limit of the length of the
text
#define Fup(i, s, t) for (int i = s; i <= t; i ++)
//Increasing loop
#define Fdn(i, s, t) for (int i = s; i >= t; i --)
//Descending loop
#define Path(i, s) for (int i = s; i; i = d[i].next)
//Singly Linked List d[]
using namespace std;
struct node {int now, next;}d[maxn]; // d[], where d[].now
is the sequence number for an element, and d[].next is the
successor pointer
354 ◾ Algorithm Design Practice for Collegiate Programming
pos[i] = i;
}
radix_sort(1, n); //val[][0] and val[][1] are
combined to xy, and calculate Rank[] with length t
t *= 2; //the length of substring *2
}
Fup(i, 1, n) sa[rank[i]] = i; //SA[]
}
void get_common_prefix() //Calculate the longest common
prefix height[]
{
memset(h, 0, sizeof(h));
Fup(i, 1, n){
if (rank[i] == 1)
h[i] = 0;
else{
int now = 0;
if (i > 1 && h[i - 1] > 1)
now = h[i - 1] - 1;
while (now + i <= n && now + sa[rank[i] - 1] <= n
&& x[now + i] == x[now + sa[rank[i] - 1]])
now ++;
h[i] = now;
}
}
Fup(i, 1, n) height[rank[i]] = h[i]; //calculate
height[] based on h[]
}
void get_RMQ() //calculate f[][], f[i, j] stores the minimal
height in the subinterval [j, j+2i−1]
{
Fup(i, 1, n)f[i][0] = height[i];
Fup(k, 1, (int)(log(n) / log(2))) //length is
enumerated (integral power of 2)
Fup(i, 1, n - (1 << k) + 1)
f[i][k]=min(f[i][k-1],f[i+(1<<(k - 1))][k-1]);
}
int query(int a, int b) //calculate the length of maximum
matching string for suffix[a] and suffix[b]
{
int head = min(rank[a], rank[b])+1,
tail=max(rank[a],rank[b]);
if (head > tail)
return (int)str.size() - cor[a] + 1;
int t = (int)(log(tail - head + 1) / log(2));
int len = min(f[head][t], f[tail - (1 << t) + 1][t]);
if (len < dis[a] && len < dis[b])return len;
len = min(dis[a], dis[b]);
while (cor[a] + len <= (int)str.size() && cor[b] + len <=
(int)str.size()){
356 ◾ Algorithm Design Practice for Collegiate Programming
if(str[cor[a]+len-1]!=str[cor[b]+len-1])return len;
if (opp[cor[a] + len] && opp[cor[b] + len])
return len + query(opp[cor[a] + len], opp[cor[b] +
len]);
len ++;
}
return len;
}
void insert(char ch, int pre) //character ch is inserted
{
int t = (int)str.size(); //length of str
pre = min(t + 1, pre); //inserted position
str = str + ' '; //space is added to the end of the
string
Fdn(i, t, pre){
str[i] = str[i - 1];
opp[i + 1] = opp[i]; // opp[i] is the initial
position for the current i-th character
if (opp[i])
cor[opp[i]] = i + 1; // cor[k] is the current
position for the character whose initial position is k
}
opp[pre] = 0; //the current the pre-th character is the
inserted character
str[pre - 1] = ch; //Insertion
Fdn(i, pre - 1, 1){
if (!opp[i])break;
dis[opp[i]] = min(dis[opp[i]], pre - i);
}
}
void init() //Input the initial text and commands
{
cin >> str; // the initial text
n = (int)str.size(); //the length of the initial text
Fup(i, 1, n){ //Initialization
x[i] = rank[i] = (int)str[i - 1];
cor[i] = i;opp[i] = i;
}
cin >> k; //number of commands
}
void solve() //commands are executed one by one
{
get_suffix_array(); //calculate Rank[]
get_common_prefix(); //calculate height[]
get_RMQ(); // calculate the minimal height in the
subinterval
memset(dis, 127, sizeof(dis));
Fup(i, 1, k){ // commands are executed one by one
char kind;
Practice for Advanced Data Structures ◾ 357
a + b
If L>1: Interval a , represents the left child for the root, and interval
2
a + b
2 + 1, b is the right child for the root;
If L=1: The left child and the right child for T (a, b) are leaves [a] and [b]
respectively.
If L=0, that is, a==b: T (a, b) is a leaf representing [a], that is, an element a.
358 ◾ Algorithm Design Practice for Collegiate Programming
[1, 10]
[1] [2]
Figure 7.6
Input
There will be several test cases in the input. Each test case consists of N+1 lines
where N (1≤N≤200,000) is given in the first line of the test case. The next N lines
contain the pairs of values Posi and Vali in the increasing order of i (1≤i≤N). For
each i, the ranges and meanings of Posi and Vali are as follows:
Posi ∈[0, i−1]: The i-th person came to the queue and stood right behind the
Posi-th person in the queue. The booking office was considered the 0th person
and the person at the front of the queue was considered the first person in
the queue.
Vali ∈[0, 32767]: The i-th person was assigned the value Vali.
There are no blank lines between test cases. Proceed to the end of input.
Output
For each test case, output a single line of space-separated integers which are the
values of people in the order they stand in the queue.
Practice for Advanced Data Structures ◾ 361
4 77 33 69 51
0 77 31492 20523 3890 19243
1 51
1 33
2 69
4
0 20523
1 19243
1 3890
0 31492
Source: POJ Monthly, 2006.05.28, Zhu Zeyuan
IDs for Online Judges: POJ 2828
Hint
Figure 7.7 shows how the Little Cat found out the final order of people in the queue
described in the first test case of the sample input.
Analysis
Initially there is an empty sequence. N persons are interested into the sequence.
Each person has a value. Values of persons are output in the order they stand in the
queue finally.
For each test case, N pairs of values are dealt with in reverse order, in order to
guarantee that the inserted position can’t be changed. For example, for the second
Figure 7.7
362 ◾ Algorithm Design Practice for Collegiate Programming
sample test case, the sequence of the sample input is 0 20523 1 19243 1 3890 0
31492. These four pairs of values are dealt with in reverse order. First, the fourth pair
(pos[4], val[4])is dealt: pos[4]=0, val[4]=31492. j= pos[4]+1=1. The fourth person will
be inserted into the “current” j-th empty position (the “current” first empty position).
Second, the third pair (pos[3], val[3])is dealt: pos[3]=1, val[3]=3890. j=pos[3]+1=2.
That is, the third person will be inserted into the current j-th empty position (the cur-
rent second empty position). Third, the second pair (pos[2], val[2]) is dealt: pos[2]=1,
val[2]=19243. j=pos[2]+1=2. That is, the third person will be inserted into the current
j-th empty position (the current second empty position). Finally, the first pair (pos[1],
val[1]) is dealt: pos[1]=0, val[1]=20523. j=pos[1]+1=1. That is, the first person will be
inserted into the current first empty position. Therefore, for the second test case, the
values of people in the order they stand in the queue are 31492 20523 3890 19243.
A segment tree is used to solve the problem. Nodes in the segment tree are used
to store the number of empty positions in the corresponding interval. For each
time, first the pos[i]-th empty position is searched, and then nodes’ states for repre-
senting the pos[i]-th empty position are changed.
Initially, the state value for a node is the length of interval. Leaf nodes represent
persons.
The process is as follows.
From the n-th person, each person’s position is dealt with one by one. When the
i-th person is inserted into the sequence, his position is the current j-th empty
position (j=pos[i]+1, i=n…1, pos[i]<i), and then the number of the empty
position is recursively calculated from the root of the segment tree.
If the number of empty positions in the left subtree ≥j, recursive search is on the
left subtree; otherwise the k-th empty position in the right subtree is calcu-
lated, k=j−(number of empty positions in the left subtree). Repeat the above
steps until leaf node d is found, where node d represents interval [t]. Then the
i-th person’s position is t.
Then the segment tree is adjusted. On the path from leaf node d to the root, the
number of empty positions in each node −1.
Repeat the above steps until the first person’s position is calculated.
Program
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
Practice for Advanced Data Structures ◾ 363
#include <utility>
#include <algorithm>
#define maxn 200100 //the upper limit of number of persons
#define Fup(i, s, t) for (int i = s; i <= t; i ++)
#define Fdn(i, s, t) for (int i = s; i >= t; i --)
using namespace std;
int pos[maxn], val[maxn], size[maxn * 3], ans[maxn],
point[maxn]; // pos[i] and val[i]: described in problem;
ans[k]: the i-th person in the queue; point[k]: the sequence
number for the leaf representing [k]; size[j]: number of empty
positions in node j
int n; //number of persons
void build_tree(int l, int r, int i) //From node i, a
segment tree is built for interval [l, r]
{
size[i] = r - l + 1; // number of empty positions in
node i
if (l==r){ // There is only one element in the
interval. Set the sequence number for the leaf containing the
element
point[l] = i;
return;
}
int mid = (l + r) / 2; // pointer pointing to the middle
of the interval
build_tree(l, mid, i + i); // A segment tree is built for
the left subinterval
build_tree(mid + 1, r, i + i + 1); // A segment tree is
built for the right subinterval
}
int require(int sum, int l, int r, int i) //Calculate the
sequence number of the leaf for the sum-th empty position
{
if (l == r) // In the interval there is only one element,
return the element
return l;
int mid = (l + r) / 2; // pointer pointing to the middle
if (size[i + i] >= sum) //number of empty positions in
the left subtree ≥ sum
return require(sum, l, mid, i + i);
return require(sum - size[i + i], mid + 1, r, i + i + 1);
}
void change(int i) //Updating the segment tree, from leaf i
to the root, adjust number of empty positions
{
while (i > 0){
size[i] --;
i = i / 2;
}
}
364 ◾ Algorithm Design Practice for Collegiate Programming
void init()
{
Fup(i, 1, n) // Input test case
scanf("%d%d\n", &pos[i], &val[i]);
}
void solve() // calculate and output the values of people
in the order they stand in the queue
{
memset(size, 0, sizeof(size));
build_tree(1, n, 1); //construct segment tree (1, n)
Fdn(i, n, 1){ // n pairs of values are dealt with in
reverse order
int t = require(pos[i] + 1, 1, n, 1);
ans[t] = i;
change(point[t]); //updating segment tree
}
Fup(i, 1, n - 1) // output the values of people in the
order they stand in the queue
cout << val[ans[i]] << ' ';
cout << val[ans[n]] << endl;
}
int main()
{
while (scanf("%d\n", &n) == 1){
init(); //Input
solve(); //calculate and output the values of people
in the order they stand in the queue
}
return 0;
}
Input
The first line contains two numbers N and Q. 1≤N,Q≤100000.
The second line contains N numbers, the initial values of A1, A 2, …, A N.
−1000000000≤Ai ≤1000000000.
Each of the next Q lines represents an operation.
Output
You need to answer all Q commands in order. One answer in a line.
10 5 4
1 2 3 4 5 6 7 8 9 10 55
Q 4 4 9
Q 1 10 15
Q 2 4
C 3 6 3
Q 2 4
Hint: The sums may exceed the range of 32-bit integers.
Source: POJ Monthly, 2007.11.25, Yang Yi
IDs for Online Judges: POJ 3468
366 ◾ Algorithm Design Practice for Collegiate Programming
Analysis
A segment tree is used to solve the problem. Subintervals in the tree correspond to
indexes of numbers, that is, [l, r] corresponds to numbers Al, Al +1, …, Ar. Obviously,
leaves represent initial values for Al, Al +1, …, Ar from left to right. In each node,
there are two attributes:
Each time, the label is used to update the segment tree. If node i isn’t labeled,
then return; else subintervals that the left child and right child correspond to are
covered. Sums of current numbers in subintervals for the left child and right child
are calculated. And the left child and right child are labeled v.
Suppose the root of the segment tree is i, and corresponds to an interval [l, r].
Then the sum of current numbers in the subinterval [tl, tr] is calculated:
Program
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <string>
#include <map>
#include <utility>
#include <set>
#include <algorithm>
#define maxn 100010 // the upper limit of the number of
numbers
using namespace std;
struct node {long long mark,sum;}tree[maxn*4]; // segment
tree, for node i, the sum of numbers is tree[i].sum, and the
label is tree[i].mark
int x[maxn]; // the sequence of initial numbers
int n, m; //numbers of numbers and operations
void update(int l, int r, int i) //label method is to
update a segment tree(i is the root, corresponding to an
interval [l, r])
{
if (!tree[i].mark) return; // if label i is labeled,
then return; else subintervals that left child and right child
correspond to are covered. Sums of current numbers in
subintervals for left child and right child are calculated.
And left child and right child are labeled v.
int mid = (l + r) / 2;
tree[i + i].sum += tree[i].mark * (long long)(mid - l + 1);
tree[i + i + 1].sum += tree[i].mark * (long long)(r - mid);
tree[i+i].mark+=tree[i].mark;
tree[i+ i+1].mark += tree[i].mark;
tree[i].mark = 0; //removing the label for node i
}
long long query(int tl, int tr, int l, int r, int i) // the
sum of current numbers in the subinterval [tl, tr] is
calculated. (i is the root of segment tree corresponding to
the interval [l, r], [tl, tr] is a subinterval for [l, r])
{
if (tl > r || tr < l)
return 0;
if (tl <= l && r <= tr) // If [tl, tr] covers [l, r]
completely, return the sum s for node i
return tree[i].sum;
368 ◾ Algorithm Design Practice for Collegiate Programming
They have built a wall 10000000 bytes long (such that there is enough place
for all candidates). When the electoral campaign was restarted, the candidates
were placing their posters on the wall, and their posters differed widely in width.
Moreover, the candidates started placing their posters on wall segments already
occupied by other posters. Everyone in Bytetown was curious whose posters will be
visible (entirely or in part) on the last day before elections.
Your task is to find the number of visible posters when all the posters are placed,
given the information about posters’ size, their place, and order of placement on
the electoral wall.
Input
The first line of input contains a number c giving the number of cases that follow.
The first line of data for a single case contains number 1≤n≤10000. The subsequent
n lines describe the posters in the order in which they were placed. The i-th line
among the n lines contains two integer numbers li and ri, which are the number
of the wall segment occupied by the left end and the right end of the i-th poster,
respectively. We know that for each 1≤i≤n, 1≤li≤ri≤10000000. After the i-th poster
is placed, it entirely covers all wall segments numbered li, li+1, …, ri.
Output
For each input data set, print the number of visible posters after all the posters are placed.
1 4
5
1 4
2 6
8 10
3 4
7 10
Source: Alberta Collegiate Programming Contest 2003.10.18
IDs for Online Judges: POJ 2528
Analysis
The wall is represented as an interval [0, 10000000]. One poster being placed
on the wall can be regarded as a subinterval being colored. Placing the i-th
Practice for Advanced Data Structures ◾ 371
1 2 3 4 5 6 7 8 9 10
Top view
Front view
Figure 7.8
poster can be regarded as the i-th subinterval being colored color i, 1≤i≤n.
The final number of colors in the interval [0, 10000000] (previous colors can
be covered by later colors) is the number of visible posters after all the posters
are placed.
The problem is a basic problem for a segment tree. In the segment tree, each
node stores its subinterval’s color, where colorless is represented as 0, mixed color
is represented as −1; otherwise, the color is represented as the number of color that
the node is colored. Then a subinterval in the segment tree is updated each time.
Because the wall is 10000000 bytes long, and 1≤n≤10000. Discretization should
be used. And it is not simple discretization.
The algorithm is as follows:
1. Discretization.
The left boundaries, right boundaries, and middle positions for n posters are
stored in array x[1…3×n]. Then x[ ] is sorted to delete repeated coordinates.
For the i-th poster, numbers of coordinates which aren’t larger than its left
boundary and right boundary are l[i] and r[i] respectively. Obviously, l[i] and
r[i] constitute the i-th segment, and the color of the segment is i, 1≤i≤n.
For example, there are three posters placed on the wall. Subintervals
[1, 5], [1, 2] and [4, 5] are covered by the three posters. After the three posters
are placed on the wall, there are three colors in the interval [0, 10000000].
For the first poster, numbers of coordinates which aren’t larger than its left
boundary and right boundary are 1 and 4. For the second poster, numbers of
coordinates which aren’t larger than its left boundary and right boundary are
1 and 2. And for the third poster, numbers of coordinates which aren’t larger
than its left boundary and right boundary are 3 and 4.
372 ◾ Algorithm Design Practice for Collegiate Programming
Program
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#define maxn 10010 // the upper limit of the number of
posters
using namespace std;
bool tab[maxn]; //tab[k]: the label that color k is used
int l[maxn], r[maxn], x[maxn*3], num[maxn*3], tree[maxn*12];
//For the i-th posters, numbers of coordinates which aren’t
larger than its left boundary and right boundary are l[i] and
r[i] respectively; its left boundary, right boundary, and
middle position are x[3*i−2], x[3*i−1] and x[3*i]
respectively; after x[ ] is sorted, in x[1..j] the number of
non-repeating coordinates is num[j]; the label for node k in
the segment tree is tree[k], is the color for its subinterval
int c, n; //c: number of test cases, n: number of posters
int binary_search(int sum) //calculate different
coordinates in interval [0..sum]
{
int l = 1, r = 3*n;
while (r >= l){ //binary search is used to find the
sequence number r in x[ ] whose coordinate is sum
int mid = (l + r) / 2;
if (x[mid] <= sum)
l = mid + 1;
Practice for Advanced Data Structures ◾ 373
else
r = mid - 1;
}
return num[r]; //the number of different coordinates in
x[1…r]
}
void update(int i) //Update a segment with label method
{
if (!tree[i]) // if label i isn’t labeled, return
return;
tree[i+i]=tree[i+i+1]=tree[i]; //the label for node i is
given to its left and right child, and removed
tree[i] = 0;
}
void change(int tl, int tr, int l, int r, int i, int co)
// In segment tree (root i, interval [l, r]), a subinterval
[tl, tr]) whose color is co is inserted
{
if (tr < l || tl > r)
return;
if (tl<=l && r<=tr){ //[tl, tr] covers [l, r] completely
tree[i] = co;
return;
}
update(i); // update the segment tree with label method
int mid = (l + r) / 2; // recursions for left and right
subtree
change(tl, tr, l, mid, i+i, co);
change(tl, tr, mid + 1, r, i + i + 1, co);
}
int require(int l, int r, int i) //the number of visible
posters in the interval [l, r] (i is the root of its subtree)
{
int mid = (l+r)/2; //middle pointer
if (tree[i]){ //i has been labeled, if the segment wasn’t
colored before, then set the label to the color and return 1,
else return 0
if (!tab[tree[i]]){
tab[tree[i]] = 1;
return 1;
}
return 0;
}
if (l == r) //the current vertex isn’t covered, return 0
return 0;
return require(l, mid,i+i)+require(mid+1,r,i+i+1);
//accumulate the number of visible posters in left and right
subintervals
}
void init() // Discretization
374 ◾ Algorithm Design Practice for Collegiate Programming
{
scanf("%d\n", &n); //number of posters
for (int i = 1; i <=n; i ++){ //posters’ left and right
boundaries, for the i-th poster, its left and right boundaries
are x[3*i−2] and x[3*i−1], x[3*i] stores the middle position
scanf("%d%d\n", l + i, r + i);
x[i+ i+i-2] = l[i]; x[i+i+i-1]=r[i]; x[i+i+i]=(l[i] +
r[i])/2;
}
sort(x + 1, x + 3 * n + 1); //sort x[]
memset(num, 0, sizeof(num));
for (int i=1;i<=3*n;i++){ //calculate num[], where num[i]
is the number of coordinates in x[1…i]
num[i] = num[i - 1];
if (x[i] != x[i - 1]) num[i] ++;
}
for (int i=1; i<=n; i++){ //calculate coordinates for
left and right boundaries of each poster
l[i] = binary_search(l[i]);
r[i] = binary_search(r[i]);
}
}
void solve() //calculate the number of visible posters
{
memset(tree, 0, sizeof(tree));
for (int i = 1; i<=n; i++) //insert subintervals in the
segment tree
change(l[i], r[i], 1, 3 * n, 1, i);
memset(tab, 0, sizeof(tab));
int ans = require(1,3*n,1); // calculate and output the
number of visible posters
printf("%d\n", ans);
}
int main()
{
scanf("%d\n", &c); //number of test cases
for (int i = 1; i<=c; i++) {
init(); // calculate the number of visible posters
solve();
}
return 0;
}
exists an “occupied interval” for the deleted segment in the segment tree, the seg-
ment can be deleted.
The label for a node includes:
1. The mark for the corresponding subinterval: There are three kinds of marks—
occupied, empty, and partly occupied;
2. The longest empty subinterval in the corresponding subinterval for the node:
The start position pos, and the length lm;
3. The length of the rightmost empty subinterval ls in the node’s left child and
the length of the leftmost empty subinterval rs in the node’s right child, that
is, the length of the subinterval crossing the left and right subintervals for the
node is ls+rs.
7.2.3.3.1 Hotel
The cows are journeying north to Thunder Bay in Canada to gain cultural enrich-
ment and enjoy a vacation on the sunny shores of Lake Superior. Bessie, ever the com-
petent travel agent, has named the Bullmoose Hotel on famed Cumberland Street as
their vacation residence. This immense hotel has N (1≤N≤50,000) rooms all located
on the same side of an extremely long hallway (all the better to see the lake, of course).
The cows and other visitors arrive in groups of size Di (1≤Di ≤N) and approach
the front desk to check in. Each group i requests a set of Di contiguous rooms from
Canmuu, the moose staffing the counter. He assigns them some set of consecutive
room numbers r..r+Di−1 if they are available; or, if no contiguous set of rooms is
available, politely suggests alternate lodging. Canmuu always chooses the value of
r to be the smallest possible.
Visitors also depart the hotel from groups of contiguous rooms. Checkout i
has the parameters Xi and Di which specify the vacating of rooms Xi ..Xi +Di −1
(1≤Xi ≤N−Di +1). Some (or all) of those rooms might be empty before the checkout.
Your job is to assist Canmuu by processing M (1≤M<50,000) checkin/checkout
requests. The hotel is initially unoccupied.
Input
* Line 1: Two space-separated integers: N and M;
* Lines 2: M+1: Line i+1 contains a request expressed as one of two possible
formats:
1. Two space-separated integers representing a check-in request: 1 and Di ;
2. Three space-separated integers representing a checkout: 2, Xi, and Di.
Output
* Lines 1.....: For each check-in request, output a single line with a single integer r,
the first room in the contiguous sequence of rooms to be occupied. If the request
cannot be satisfied, output 0.
376 ◾ Algorithm Design Practice for Collegiate Programming
10 6 1
1 3 4
1 3 7
1 3 0
1 3 5
2 5 5
1 6
Source: USACO 2008 February Gold
IDs for Online Judges: POJ 3667
Analysis
For each node, there are three kinds of marks: occupied, empty, and partly occu-
pied. There are two types of operations:
Operation 1: Search the position for the foremost empty subinterval whose
length is n;
Operation 2: Set the mark for a subinterval empty.
For each operation, the segment tree needs to be updated. The label method is
used to update the segment tree. The label for a node includes:
mark: the state for the node’s corresponding subinterval (0: undetermined;
1: empty; 2: occupied);
ls: the length of the rightmost empty subinterval in the node’s left child;
rs: the length of the leftmost empty subinterval in the node’s right child;
ms: the length of the longest empty subinterval in the node’s corresponding sub-
interval: and the start position for the subinterval is pos;
The three operations (update, query, and modification for a subinterval) for a
segment tree whose root is i, and corresponding subinterval is [l, r] are as follows:
l - r +2
ls, rs and ms for the left child are
2 , its pos is
l - r +1
l; ls, rs and ms for right child are
2 , and its pos
is
l - r +1; mark for the left and right child is 1;
2
}else{ // the subinterval [l, r] for node i is
occupied, 0 empty positions, set marks for the left and
right subtrees “occupied”
ls, rs and ms for the left child are 0, its pos is
l; ls, rs and ms for right child are 0, and its pos is
l - r +1; mark for the left and right child is 2;
2
}
Set the state for node i 0; //Set the state for
node i “undetermined”
2. Query.
For node i (corresponding to the subinterval [l, r]), search whether there exist
empty subintervals whose length is d. If there exist such subintervals, return
the left pointer for the foremost empty subinterval.
3. Modification.
A segment [tl, tr] is inserted into or deleted from a segment tree whose root is
i, represent an interval [l, r].
Program
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#include <utility>
#include <set>
#include <algorithm>
#define maxn 80010
using namespace std;
struct node {int ls, rs, ms, pos, mark;}tree[4*maxn];
//segment tree, where the label for node i: tree[i].mark: the
Practice for Advanced Data Structures ◾ 379
tree[i + i + 1].pos = (l + r) / 2 + 1;
tree[i + i].mark = tree[i + i + 1].mark = 2;
}
tree[i].mark = 0; // node i “undetermined”
}
int query(int d, int l, int r, int i) //Query. If there exist
empty subintervals whose length is d in the segment tree (root
i, interval [l, r]), return the left pointer for the empty
subinterval, else return 0.
{
update(l, r, i);
if (tree[i].ms < d) // there is no empty subinterval
whose length is d
return 0;
if (tree[i].ms==d) // if (ms for node i==d) return pos
for node i
return tree[i].pos;
int mid = (l + r)/2; //Intermediate pointer
if (tree[i+i].ms>=d) // if (ms for the left subtree≥d)
recursion for the left subtree
return query(d, l, mid, i + i);
if (tree[i + i].rs + tree[i + i + 1].ls >= d) //the
length for empty interval covering the intermediate pointer
≥d, return its left pointer
return mid - tree[i + i].rs + 1;
return query(d, mid + 1, r, i + i + 1); // recursion
for the right subtree;
}
void change(int tl, int tr, int l, int r, int i, bool flag)
//Modification. Insert or delete a segment [tl, tr] into or
from a segment tree (root i, interval [l, r])
{
if (tl > r || tr < l) //[tl, tr] isn’t in [l, r]
return;
if (tl <= l && r <= tr){ // [tl, tr] covers [l, r]
if (flag){ //Insertion
tree[i].ls = tree[i].rs = tree[i].ms = 0;
tree[i].pos = l;
tree[i].mark = 2; //the interval for node i is
occupied
}else{ //delete
tree[i].ls = tree[i].rs = tree[i].ms = r - l + 1;
tree[i].pos = l;
tree[i].mark = 1; // the interval for node i is
empty
}
return;
}
update(l, r, i);
int mid = (l + r) / 2; // Intermediate pointer
Practice for Advanced Data Structures ◾ 381
round trip. If there was more than one such round trip, he would have chosen the
one which, when written down as a sequence of street numbers, is lexicographically
the smallest. But Johnny was not able to find even one such round trip.
Help Johnny and write a program which finds the desired shortest round trip.
If the round trip does not exist, the program should write a message. Assume that
Johnny lives at the junction ending where the street appears first in the input with
a smaller number. All streets in the town are two-way. There exists a way from each
street to another street in the town. The streets in the town are very narrow, and
there is no possibility to turn back the car once he enters a street.
Input
Input file consists of several blocks. Each block describes one town. Each line
in the block contains three integers x, y, z, where x>0 and y>0 are the numbers
of junctions that are connected by the street number z. The end of the block is
marked by the line containing x=y=0. At the end of the input file there is an empty
block, x=y=0.
Output
Output one line of each block containing the sequence of street numbers (single
members of the sequence are separated by spaces) describing Johnny’s round trip. If
the round trip cannot be found, the corresponding output block contains the mes-
sage “Round trip does not exist.”
1 2 1 1 2 3 5 4 6
2 3 2
3 1 6 Round trip does not exist.
1 2 5
2 3 3
3 1 4
0 0
1 2 1
2 3 2
1 3 3
2 4 4
0 0
0 0
Source: ACM Central European Regional Contest 1995
IDs for Online Judges: POJ 1041, UVA 302
384 ◾ Algorithm Design Practice for Collegiate Programming
Analysis
The problem requires you to calculate the Euler circuit for which the sequence of street
numbers is lexicographically the smallest for a graph. The algorithm is as follows:
Program
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <string>
#include <map>
#include <utility>
#include <vector>
#include <set>
#include <algorithm>
#define maxn 2000 // The upper limit of the number of edges
#define maxm 50 // The upper limit of the number of vertices
using namespace std;
struct node{int s,t;}r[maxn]; //the sequence of edges,
where the i-th edge is (r[i].s, r[i].t)
bool vis[maxn]; //visited marks for edges vis[ ]
int deg[maxm], s[maxn]; // degrees of nodes deg[ ], the
sequence of edges for the Euler circuit s[ ]
int n, S, stop; //the number of edges n, the smallest number
for nodes S, the number of edges in the Euler circuit stop
bool exist() // If there exists a node whose degree is odd,
return 0; else return 1
{
Practice for Advanced Data Structures ◾ 385
Theorem 7.3.3. A directed graph is Eulerian if and only if every graph vertex has
equal in-degree and out-degree.
7.3.1.2 Catenyms
A catenym is a pair of words separated by a period such that the last letter of the
first word is the same as the last letter of the second. For example, the following are
catenyms:
dog.gopher
gopher.rat
rat.tiger
aloha.aloha
arachnid.dog
aloha.aloha.arachnid.dog.gopher.rat.tiger
Input
The first line of standard input contains t, the number of test cases. Each test case
begins with 3≤n≤1000—the number of words in the dictionary. n distinct diction-
ary words follow; each word is a string of between 1 and 20 lowercase letters on a
line by itself.
Output
For each test case, output a line giving the lexicographically least compound catenym
that contains each dictionary word exactly once. Output “***” if there is no solution.
2 aloha.arachnid.dog.gopher.rat.tiger
6 ***
aloha
arachnid
dog
gopher
rat
Practice for Advanced Data Structures ◾ 387
tiger
3
oak
maple
elm
Source: Waterloo local 2003.01.25
Ids for Online Judges: POJ 2337, ZOJ 1919
Analysis
The key to the problem is data modeling: What are represented as vertices and what
are represented as arcs?
A dictionary is represented as a digraph G, where all letters are represented as ver-
tices, that is, ‘a’ corresponds to 1, ……, and ‘z’ corresponds to 26; and each word is
represented as an arc (u, v), where u is the number of the first letter for the word, and v is
the number of the last letter for the word. Two corresponding words become a catenym
if and only if the last letter of the first word is the same as the first letter of the second
word. Therefore, the problem requires you to calculate an Euler path in the digraph G.
The algorithm is as follows:
Program
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <string>
#include <map>
#include <utility>
#include <vector>
#include <set>
#include <algorithm>
#define maxn 1010
using namespace std;
struct node{int u,v;string name;}road[maxn]; //edges, the
i-th edge is (road[i].u, road[i].v), and the word is road[i].
name
bool app[30], use[maxn]; //marks for vertices and edges are
app[] and use[]
int ind[30], oud[30], anc[30], s[maxn]; //in-degree and
out-degree for vertex i are ind[i] and oud[i], the root for
its union-find set is anc[i], directed Euler path is s[]
int n, S, stop, t; //number of edges n, the starting point
and length for the directed Euler path are S and stop, number
of test cases is t
bool cmp(const node &a, const node &b) //Lexicographic order
{
return a.name < b.name;
}
int get_father(int x) //return the root for the union-find
set containing x
{
if (!anc[x]) //x doesn’t belong to any union-find set,
return x
return x;
anc[x] = get_father(anc[x]); //calculating the root for
the union-find set containing x
return anc[x];
}
int change(char ch) //letter ch is transferred as its
corresponding number
{
return (int)ch - (int)’a’ + 1;
}
Practice for Advanced Data Structures ◾ 389
Case 1: In a graph there are a few vertices. Brute-force search can be used to solve
the traveling salesman problem, although its time complexity is O(n!×n).
Case 2: State compression is used in solving the traveling salesman problem
when there are a few vertices in a graph.
Case 3: A Hamiltonian path is calculated in a tournament. The time complexity
is O(n2).
(8,16) (12,16)
(8,11)
(24,10)
11.18 ft.
(13,8)
Figure 7.9
the computers plus 16 additional feet of cable to connect from the floor to the com-
puters and provide some slack for ease of installation.
Figure 7.10 shows the optimal way of connecting the computers shown above,
and the total length of cable required for this configuration is (4+16)+(5+16)+
(5.83+16)+(11.18+16)=90.01 feet.
Input
The input file will consist of a series of data sets. Each data set will begin with a line
consisting of a single number, indicating the number of computers in a network.
Each network has at least two and at most eight computers. A value of 0 for the
number of computers indicates the end of input.
After the initial line in a data set specifying the number of computers in a net-
work, each additional line in the data set will give the coordinates of a computer
in the network. These coordinates will be integers in the range 0 to 150. No two
computers are at identical locations and each computer will be listed once.
Output
The output for each network should include a line which tells the number of the
network (as determined by its position in the input data), and one line for each
4 ft.
(8,16) (12,16)
(8,11)
5.83 ft.
(24,10)
11.18 ft.
(13,8)
Figure 7.10
Practice for Advanced Data Structures ◾ 393
length of cable to be cut to connect each adjacent pair of computers in the network.
The final line should be a sentence indicating the total amount of cable used.
In listing the lengths of cable to be cut, traverse the network from one end
to the other. (It makes no difference at which end you start.) Use a format similar
to the one shown in the sample output, with a line of asterisks separating output for
different networks and with distances in feet printed to two decimal places.
6 **********************************************************
5 19 Network #1
55 28 Cable requirement to connect (5,19) to (55,28) is 66.80 feet.
38 101 Cable requirement to connect (55,28) to (28,62) is 59.42 feet.
28 62 Cable requirement to connect (28,62) to (38,101) is 56.26 feet.
111 84 Cable requirement to connect (38,101) to (43,116) is 31.81 feet.
43 116 Cable requirement to connect (43,116) to (111,84) is 91.15 feet.
5 Number of feet of cable required is 305.45.
11 27 **********************************************************
84 99 Network #2
142 81 Cable requirement to connect (11,27) to (88,30) is 93.06 feet.
88 30 Cable requirement to connect (88,30) to (95,38) is 26.63 feet.
95 38 Cable requirement to connect (95,38) to (84,99) is 77.98 feet.
3 Cable requirement to connect (84,99) to (142,81) is 76.73 feet.
132 73 Number of feet of cable required is 274.40.
49 86 **********************************************************
72 111 Network #3
0 Cable requirement to connect (132,73) to (72,111) is 87.02 feet.
Cable requirement to connect (72,111) to (49,86) is 49.97 feet.
Number of feet of cable required is 136.99.
Source: ACM/ICPC World Finals 1992
ID for Online Judge: UVA 216
Analysis
A weighted graph is constructed as follows. Computers are represented as vertices.
Euclidean distances between computers are as weights of edges connecting the two
computers. Because each vertex’s degree is n−1, there must be Hamilton paths in
the graph. The problem requires you to calculate the Hamilton path with minimal
length. Because the upper limit of the number of vertices is eight, DFS can be used
to solve the problem.
394 ◾ Algorithm Design Practice for Collegiate Programming
Program
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <string>
#include <map>
#include <utility>
#include <vector>
#include <set>
#include <algorithm>
#define maxn 10
using namespace std;
bool vis[maxn]; //visited marks for vertices
int x[maxn], y[maxn], ans[maxn], t[maxn]; //computers’
coordinates x[] and y[], the shortest Hamiltonian path ans[],
the current path t[]
double dis[maxn][maxn]; //distance between vertices
double Min; //the length of the shortest path
int n, casenum; //number of vertices n, number of test
cases casenum
int sqr(int x) //return x2
{
return x * x;
}
void dfs(int sum, int now, double s) //calculate the
Hamiltonian path from the current state (there are sum
vertices in the current path, the length of the current path
is s, the last vertex in the current path is now)
{
if (sum == n){ // the Hamiltonian path
if (s < Min){ // the current Hamiltonian path is
the shortest
Min = s;
for (int i = 1; i <=n; i ++) ans[i] = t[i];
}
return; //backtracking
}
for (int i = 1; i <=n; i ++) //search unvisited
vertices
if (!vis[i]){
vis[i] = 1; //Set vertex i visited mark, (now, i)
is added into the path
Practice for Advanced Data Structures ◾ 395
t[sum + 1] = i;
dfs(sum + 1, i, s + dis[now][i]);
vis[i] = 0; // Set vertex i unvisited mark
}
}
void init() // Input computers’ coordinates, construct
distance matrix
{
for (int i = 1; i <=n; i ++) // Input computers’
coordinates
cin >> x[i] >> y[i];
memset(dis, 0, sizeof(dis));
for (int i = 1; i <=n; i ++) //distances between vertices
for (int j= 1; j<=n; j ++)
dis[i][j] = sqrt(sqr(x[i] - x[j]) + sqr(y[i]
- y[j])) + 16;
}
void solve() // calculate and output the shortest
Hamiltonian path
{
cout << "*************************************************
*********" << endl;
cout << "Network #" << ++ casenum << endl;
Min = 1e10; //Initialization
dfs(0, 0, 0.0); // calculate the shortest Hamiltonian
path
for (int i = 1; i <=n-1; i ++) //Output the optimal way
of connecting the computers
cout << "Cable requirement to connect (" << x[ans[i]]
<< "," << y[ans[i]] << ") to (" << x[ans[i + 1]] << "," <<
y[ans[i + 1]] << ") is " << dis[ans[i]][ans[i + 1]] << "
feet." << endl;
cout << "Number of feet of cable required is " << Min <<
"." << endl;
}
int main()
{
ios::sync_with_stdio(false);
cout << fixed;
cout.precision(2);
while (cin >> n, n > 0){ //number of computers
init(); //Input computers’ coordinates, construct
distance matrix
solve(); //calculate and output the shortest
Hamiltonian path
}
return 0;
}
396 ◾ Algorithm Design Practice for Collegiate Programming
5 5 8
L.... 8
#....
#....
.....
#....
5 5
L....
#....
#....
.....
#....
Source: UVa Local Qualification Contest 2005
ID for Online Judge: UVA 10944
Larry and Ryan will go south for a nut, then south again for another nut, then
south twice for another nut, and then back where they are.
Analysis
Nuts are represented as vertices. Nuts are numbered 1…k from top to down and
from left to right. A k-digit binary number is used to represent whether nuts are
Practice for Advanced Data Structures ◾ 397
gathered or not. If the i-th nut is gathered, the (i-1)-th digit is 1, else the (i-1)-th
digit is 0. Initially the k-digit binary number is 0. And finally the k-digit binary
number is 2k−1. Suppose the current position for Larry and Ryan is (x, y) and the
current gathered nuts is z. The current state is represented as (x, y, z). Suppose a
queue q is used to store states, and a hash table hash is to avoid repeated states.
Initially, the starting position for Larry and Ryan (lx, ly) and the current gath-
ered nuts 0 are added into queue q as the initial state, and hash[the initial state]=1.
Then BFS is used until queue q is empty.
The front is popped from q and extended in eight directions to produce new
states. If a new state isn’t in hash, then it is added into q, and hash[the new state]=1.
If the new state is the goal state (lx, ly, 2k−1), Ryan and Larry have gathered all the
nuts, and returned back to “L”.
The amount of steps starting from “L”, gather all the nuts, and back to “L” is
calculated during the BFS.
Program
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <string>
#include <map>
#include <utility>
#include <vector>
#include <set>
#include <algorithm>
#define maxn 22 //upper limit for the size of the map
using namespace std;
const int dx[9] = {0, 0, -1, -1, -1, 0, 1, 1, 1};
// Horizontal displacement and vertical displacement
const int dy[9] = {0, 1, 1, 0, -1, -1, -1, 0, 1};
struct node {int x, y, get;}q[10000000]; //queue, where the
current position is (q[].x, q[].y), and q[].get represents
gathered nuts
bool hash[maxn][maxn][32768]; //Hash table, where hash[i]
[j][k] represents arriving at (i, j) and gathering k is the
current gathered nuts
int land[maxn][maxn]; // If (i, j) is the i-th nut from top to
down and from left to right, land[i][j]=2i; else land[i][j]=0
int n, m, sum, Sx, Sy; //the size for the map is (n, m);
the starting position for Larry and Ryan is (Sx, Sy)
void init() //Input the map
398 ◾ Algorithm Design Practice for Collegiate Programming
{
memset(land, 0, sizeof(land));
sum = 1;
for (int i = 1; i <=n; i ++){ // If (i, j) is the i-th
nut from top to down and from left to right, land[i][j]=2i;
else land[i][j]=0
char ch;
cin.get(ch);
for (int j = 1; j <=m; i ++) {
cin.get(ch);
switch (ch){
case 'L': land[i][j]=0; Sx = i; Sy = j; break;
case '#': land[i][j]=sum; sum *= 2; break;
case '.': land[i][j] = 0; break;
}
}
}
for (int i = 0; i <=n+1; i ++) //boundary value −1
land[i][0] = land[i][m + 1] = -1;
for (int i = 1; i <=m+1; i ++)
land[0][i] = land[n + 1][i] = -1;
}
void solve() //calculate and output the minimum amount of
steps
{
memset(hash, 0, sizeof(hash)); //initialize Hash table
hash[Sx][Sy][0] = 1; //Hash value for the starting
position
int head = 1, tail = 1, move = 0; //Initialization
q[1].x = Sx; q[1].y = Sy;
q[1].get = 0;
bool flag = 0;
if (sum == 1) flag = 1; //no nut
while (head <= tail && !flag){ //queue is not empty,
no Hamiltonian Circuit
int t = tail; //the rear for the queue
for (int i = head; i <= tail; i ++) { // elements
in the queue
int tx = q[i].x, ty = q[i].y; //the current
element
for (int j = 1; j <=8;j ++) { // 8 directions
are searched
int val=land[tx+dx[j]][ty+dy[j]];
if (val >= 0 && !hash[tx+dx[j]][ty+dy[j]]
[q[i].get | val]) //add into the queue
{ t ++;
q[t].x = tx + dx[j]; q[t].y = ty + dy[j];
q[t].get = q[i].get | val;
hash[tx+dx[j]][ty+dy[j]][q[i].get|val]=1;
//Hash value
Practice for Advanced Data Structures ◾ 399
Case 1: If (an+1, a1) is an arc, then an+1 is inserted into the path, and the path
becomes an +1 → a1 → a2 → ...ai ...an −1 → an ;
Case 2: If there are arcs (ai, an+1), 1≤i≤n−1, and ai+1 is the first vertex that there
is an arc (an+1, ai+1), then an+1 is inserted into the path and the path becomes
a1 → a2 → ...ai → an +1 → ai +1...an −1 → an ;
Case 3: There is no such a vertex ai in the path that (an+1, ai) is an arc, 1≤i≤n.
There must be an arc (an, an+1). Then an+1 is inserted into the path and the path
becomes a1 → a2 → ...ai ...an −1 → an → an +1 .
otherwise, the machine will stop automatically. You must start it up again to make
it continue working. Of course, the machine cannot move arbitrarily from one task
to another. So each time before it starts up, one task sequence should be well sched-
uled. Specially, a single task also can be regarded as a sequence. In the sequence,
the machine should be able to smoothly move from one task to its successor (if a
successor exists). After the machine has been started up, the machine always works
according to the task sequence, and stops automatically when it finishes the last one.
If all the tasks have not been finished, the machine has to start up again and works
according to a new sequence. Of course, the finished tasks can’t be scheduled again.
For some unknown reason, it was guaranteed that for any two tasks i and j, the
machine can smoothly move from i to j or from j to i or both. Because the startup
process is quite slow, Tom would like to schedule the task sequences properly, so
that all the tasks can be completed with a minimal number of startup times. It is
your task to help him achieve this goal.
Input
The input contains several test cases. For each test case, the first line contains only
one integer n, (0<n≤1,000), representing the number of tasks Tom has received.
Then n lines follow. Each line contains n integers, 0 or 1, separated by white
spaces. If the j-th integer in the i-th line is 1, then the machine can smoothly move
from task i to task j; otherwise. the machine can not smoothly move from task i
to task j. The tasks are numbered from 1 to n.
Input is terminated by end of file.
Output
For each test case, the first line of output is only one integer k, the minimal number
of startup times needed. And 2k lines follow, to describe the k task sequences. For
each task sequence, the first line should contain one integer m, representing the
number of tasks in the sequence. And the second line should contain m integers,
representing the order of the m tasks in the sequence. Two consecutive integers
in the same line should be separated by just one white space. Extra spaces are not
allowed. There may be several solutions, and any appropriate one is accepted.
3 1
0 1 1 3
1 0 1 2 1 3
0 0 0
Source: ACM Asia Guangzhou 2003
IDs for Online Judges: POJ 1776, ZOJ 2359, UVA 2954
Practice for Advanced Data Structures ◾ 401
Analysis
A directed graph G(V, E) is used to represent the problem. Tasks are represented
as vertices, and relationships for any two tasks are represented as arcs. For any
two tasks i and j, the machine can smoothly move from i to j or from j to i or
both. Therefore, the directed graph is a tournament. Because a tournament has
a Hamiltonian path, the minimal number of startup times is 1. The algorithm
calculating the Hamiltonian path in a tournament is shown in the proof for
Theorem 7.3.5.
Vertex 1 is as the first vertex in the Hamiltonian path. Other vertices are
inserted into the Hamiltonian path one by one. Suppose the current inserted vertex
is vertex k. Vertices in the current Hamiltonian path are searched one by one, and
the current vertex is vertex i.
If all vertices in the current Hamiltonian path have been searched, then (t, k) is
inserted into the current Hamiltonian path.
Program
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <string>
#include <map>
#include <utility>
#include <vector>
#include <set>
#include <algorithm>
#define maxn 1010
402 ◾ Algorithm Design Practice for Collegiate Programming
{
ios::sync_with_stdio(false);
while (cin >> n){ // the number of tasks (vertices)
init(); //construct an adjacency matrix
solve(); //calculate and output the Hamiltonian Path
}
return 0;
}
s-th vertex v for vertex v+1 .. vertex n in the current clique. Initially, vertex i is put
into a clique, s=1, t is the number of vertices in get[1][]. The algorithm for dfs(s, t)
is as follows:
max=0;
Enumerate vertices in descending order (vertex i=n…1):
Vertex i is the first vertex in the clique;
Calculate the number of vertices adjacent to vertex i
from vertex i+1 to vertex n, and these adjacent vertices are
stored into get[1][];
dfs(1, t);
f[i]=max;
Output max(the number of vertices for the optimal
solution);
3 6
1
4
2
5
Input
The graph is given as a set of nodes denoted by numbers 1…n, n≤100, and a set of
undirected edges denoted by pairs of node numbers (n1, n2), n1!=n2. The input file
contains m graphs. The number m is given on the first line. The first line of each
graph contains n and k, the number of nodes and the number of edges, respectively.
The following k lines contain the edges given by a pair of node numbers, which are
separated by a space.
Output
The output should consists of 2m lines, two lines for each graph found in the input
file. The first line should contain the maximum number of nodes that can be col-
ored black in the graph. The second line should contain one possible optimal color-
ing. It is given by the list of black nodes, separated by a blank.
1 3
6 8 1 4 5
1 2
1 3
2 4
2 5
3 4
3 6
4 6
5 6
Source: ACM Southwestern European Regional Contest 1995
ID for Online Judge: POJ 1419, UVA 193
Analysis
The coloring is restricted by the rule that no two connected nodes may be black. The
coloring of the graph is called optimal if a maximum of nodes is black. Therefore,
the problem requires you to calculate a maximum independent set for the graph.
When a graph is input, its complement graph is constructed. Then a maximum
clique for the complement graph is calculated. The maximum clique for the com-
plement graph is a maximum independent set for the graph. The cardinal number
406 ◾ Algorithm Design Practice for Collegiate Programming
of the maximum independent set for the graph is the maximum number of nodes
that can be colored black in the graph. And the maximum independent set for the
graph is one possible optimal coloring.
For each node i (i=n…1), node i is as the first node for the current clique. Then,
for node j (j= i+1…n), if node j and node i are adjacent, node j is put into a set, and
cliques are calculated with the above method.
Obviously, finally the maximum clique is calculated when the loop ends.
Program
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <string>
#include <map>
#include <utility>
#include <vector>
#include <set>
#include <algorithm>
#define maxn 105 //The upper limit for the number of nodes
using namespace std;
bool pic[maxn][maxn]; // adjacency matrix for complement
graph
int get[maxn][maxn]; // get[k][]: nodes adjacent to the
k-th node in the current clique
int node[maxn], ans[maxn], dp[maxn]; //node[]: current
clique; ans[]: maximum clique; dp[i]: the number of nodes for
the maximum clique storing node i… node n
int n, m, t, Max; //number of nodes n, number of edge m,
the number of nodes for the current clique Max
void dfs(int now, int sum) // the maximum clique is
calculated from the current state (the number of nodes for
the current clique now, number of edges connecting the last
node sum)
{
if (sum == 0){ // clique, that is, a complete subgraph
if (now>Max){ //adjust the number of nodes for the
maximum clique
Max = now;
for (int i=1; i<=Max; i ++) ans[i]=node[i];
}
return;
Practice for Advanced Data Structures ◾ 407
}
for (int i=1; i<=sum; i ++) { //Enumeration
int v=get[now][i], t=0; //the other node v for the
i-th edge, the number of edges connecting v t
if (now+dp[v]<=Max)return;
for (int j=i+1;j<=sum; j++) //v is added into the
clique
if (pic[v][get[now][j]]) get[now+1][++t]=get[now]
[j];
node[now+1]=v;
dfs(now+1, t);
}
}
void init() //Input edges, construct the complement graph
{
cin >> n >> m; //numbers of nodes and edges
memset(pic, true, sizeof(pic)); //initialize the
complement graph
for (int i = 1; i <= m; i ++){ // Input edges,
construct the complement graph
int a, b;
cin >> a >> b;
pic[a][b]=pic[b][a]=0;
}
}
void solve() // calculate the maximum clique for the
complement graph (the maximum independent set for the original
graph)
{
Max = 0; // the number of nodes for the current clique
Max
for (int i = n; i >= 1; i --){ //node i is as the first
node for the current clique
int sum = 0;
for (int j=i+1; j<=n; j++) // if node j (j=i+1…n)
and node i are adjacent, node j is put into get[1][]
if (pic[i][j]) get[1][++sum]=j;
node[1] = i; // node i is as the first node for the
current clique
dfs(1, sum); //number of nodes for complete
subgraph for node i...n Max
dp[i] =Max;
}
cout << Max << endl; // number of nodes for the maximum
clique
for (int i=1; i<=Max-1;i++) // nodes for the maximum
clique
cout << ans[i] << ' ';
cout << ans[Max] << endl;
}
408 ◾ Algorithm Design Practice for Collegiate Programming
int main()
{
ios::sync_with_stdio(false);
cin >> t; //number of test cases
for (int i = 1; i <= t; i ++) {
init(); //Input edges, construct the complement
graph
solve(); // calculate the maximum clique for the
complement graph (the maximum independent set for the original
graph)
}
return 0;
}
In the algorithm, low[u] is changed until the DFS subtree whose root is u, and
array low and array pre for u and its descendants are produced.
In DFS, edges can be classified into four types:
Branch edge T: Edge (u, v) is a branch edge, if it is the first time that v is visited
in DFS.
Back edge B: Edge (u, v) is a back edge, if u is a descendant of v, and v has been
visited, but all descendants of v haven’t been visited.
Forward edge F: Edge (u, v) is a forward edge, if v is a descendant of u, all
descendants of v have been visited, and pre[u]<pre[v].
Cross edge C: All other edges (u, v). That is, u and v have no ancestor-descen-
dant relationship in a DFS tree, or u and v are in different DFS trees. All
descendants of v have been visited and pre[u]>pre[v].
U’s ancestors
Chosen root
U
for the forest
U
s1 s2
s2
s1
A subtree whose A subtree whose
root is s1 root is s2
s2’s descendants
Property 1 Property 2
(a) (b)
Figure 7.12
410 ◾ Algorithm Design Practice for Collegiate Programming
In Figure 7.12(b), root U has two subtrees whose roots are s1 and s2
respectively, and there is no cross edge C between the two trees (in an undi-
rected graph, there is no cross edge C). Therefore, the graph isn’t connected
after vertex U is deleted, and vertex U is a cut vertex.
Based on the above two properties, the algorithm for calculating cut ver-
tices is as follows:
0
5
0 1 6
0 4 3
6 7 8 2 0
1 2 3 9 5 11
10 6 1 Note
4 5 4 11
3 9 2 0
4 7 Cross edge C Forward edge F
5 11 12
9 12 4
10 6 8
11
8 7
Branch T Back edge B
10 7
Undirected graph DFS tree
(a) (b)
Node number 0 1 2 3 4 5 6 7 8 9 10 11 12
Pre[v] 0 7 8 3 2 1 9 10 12 4 11 5 6
Low[v] 0 0 0 1 1 1 0 10 10 2 10 2 6
Figure 7.13
412 ◾ Algorithm Design Practice for Collegiate Programming
block 3 block 4
a d
block 1 block 2
f c e g
Figure 7.14
Practice for Advanced Data Structures ◾ 413
7.3.4.1 Network
A Telephone Line Company (TLC) is establishing a new telephone cable network.
They are connecting several places numbered by integers from 1 to N. No two places
have the same number. The lines are bidirectional and always connect two places
together, and in each place the lines end in a telephone exchange. There is one tele-
phone exchange in each place. From each place, it is possible to reach every other
place through lines; however, it need not be a direct connection, it can go through
several exchanges. From time to time, the power supply fails at a place and then the
exchange does not operate. The officials from TLC realized that in such a case, it can
happen that besides the fact that the place with the failure is unreachable, this can
also cause some other places to be unable to connect to each other. In such a case, we
will say the place (where the failure occurred) is critical. Now the officials are trying
to write a program for finding the number of all such critical places. Help them.
Input
The input file consists of several blocks of lines. Each block describes one network.
In the first line of each block, there is the number of places N<100. Each of the next
at most N lines contains the number of a place followed by the numbers of some
places to which there is a direct line from this place. These at most N lines completely
describe the network, i.e., each direct connection of two places in the network is con-
tained at least in one row. All numbers in one line are separated by one space. Each
block ends with a line containing just 0. The last block has only one line with N=0.
Output
The output contains for each block except the last in the input file one line contain-
ing the number of critical places.
5 1
5 1 2 3 4 2
0
6
2 1 3
5 4 6 2
0
0
Source: ACM Central Europe 1996
Ids for Online Judges: POJ 1144, ZOJ 1311, UVA 315
You need to determine the end of one line. In order to make it easy to deter-
mine, there are no extra blanks before the end of each line.
Practice for Advanced Data Structures ◾ 415
Analysis
A graph is constructed as follows. Places are represented as vertices. Lines between
two places are represented as edges. Obviously, critical places are articulation points
in a graph. The problem requires you to calculate the number of articulation points
in a graph.
A Tarjan algorithm is used to recursively calculate dfn[ ] and low[ ] for
vertices, and calculate the number of articulation points in a graph based on two
properties.
Program
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <string>
#include <map>
#include <utility>
#include <vector>
#include <set>
#include <algorithm>
#define maxn 110 //The upper limit of the number of vertices
using namespace std;
bool use[maxn]; //marks for articulation points
int pic[maxn][maxn]; // adjacency matrix
int dfn[maxn], low[maxn]; //dfn and low for vertices
int din, n, ans, s; //visiting sequence din, number of
vertices n, number of articulation points ans, number of
children for the root s
void tarjan(int u) //calculate the number of articulation
points from vertex u
{
dfn[u] = low[u] = ++ din;
for (int i = 1; i <=n; i ++) //enumerate every adjacent
vertex for vertex u
if (pic[u][i]){
if (!dfn[i]){ //if (u, i) is a branch edge or a
cross-edge
416 ◾ Algorithm Design Practice for Collegiate Programming
tarjan(i);
low[u]=min(low[u], low[i]); //adjust low
for u
if (low[i]>=dfn[u] && !use[u]){ //there are
no back edges for i or descendants for i to u’s ancestors
if (u > 1){ //if u isn’t the root, u is
an articulation point
ans ++;
use[u] = true;
}else //u is the root, the number of
children +1
s ++;
}
}else //(u, i) is a back edge, adjust low for u
low[u] = min(low[u], dfn[i]);
}
}
void init() //Input a graph, and construct an adjacency
matrix
{
int u, v; //two adjacent vertices
memset(pic, 0, sizeof(pic)); //initialization
while (cin >> u, u > 0){
char ch;
do{
cin >> v;
cin.get(ch);
pic[u][v] = pic[v][u] = 1; // two adjacent
vertices
}while (ch != '\n');
}
}
void solve() //calculate and output articulation points
{
memset(dfn, 0, sizeof(dfn)); //Initialization
memset(low, 0, sizeof(low));
memset(use, 0, sizeof(use));
ans = din = s= 0;
tarjan(1); //calculate the number of articulation
points from the root
if (s > 1) ans ++; // if the root has more than one
child, the root is an articulation point
cout << ans << endl; // Output the number of
articulation points in a graph
}
int main()
{
ios::sync_with_stdio(false);
while (cin >> n, n > 0){ //Input the number of vertices
Practice for Advanced Data Structures ◾ 417
Input
The first line of input will consist of positive integers n and r, separated by a space,
where 3≤n≤1000 is the number of tourist attractions on the island, and 2≤r≤1000
is the number of roads. The tourist attractions are conveniently labelled from 1 to
n. Each of the following r lines will consist of two integers, v and w, separated by a
space, indicating that a road exists between the attractions labelled v and w. Note
that you may travel in either direction down each road, and any pair of tourist
attractions will have at most one road directly between them. Also, you are assured
that in the current configuration, it is possible to travel between any two tourist
attractions.
418 ◾ Algorithm Design Practice for Collegiate Programming
Output
One line, consisting of an integer, which gives the minimum number of roads that
we need to add.
10 12 2
1 2
1 3
1 4
2 5
2 6
5 6
3 7
3 8
7 8
4 9
4 10
9 10
3 3 0
1 2
2 3
1 3
Source: Canadian Computing Competition 2007
ID for Online Judge: POJ 3352
Analysis
Remote Island is represented as a graph. Let tourist attractions be vertices, and
roads be edges. Because any two tourist attractions are connected, the graph is a
connected graph. Adding roads means adding edges in the graph. The goal for add-
ing a road is “if any one road is undergoing construction, it would still be possible
to travel between any two tourist attractions using the remaining roads.” That is to
say, a biconnected graph is constructed by adding roads with the minimum num-
ber. The algorithm is as follows.
First, all bridges are calculated. Second, all bridges are removed. And connected
components are biconnected components. All biconnected components are repre-
sented as vertices, and all bridges are added back. The new graph is a tree, and its
edge-connectivity is 1.
Practice for Advanced Data Structures ◾ 419
Then the number of vertices whose degree is 1 is calculated. Suppose the num-
ber of leaves is leaf. In order to make the tree become a biconnected graph, at least
leaf + 1 edges are added into the tree.
2
There are two lemmas.
Lemma 1: If there exists an edge (i, j), vertex i and vertex j are in a biconnected
component if and only if low[i]=low[j].
Lemma 2: There are n leaves in a tree. The tree will become a biconnected graph
n
after adding at least edges.
2
The following algorithm is based on Lemma 1 and Lemma 2. Suppose e[][] is
an adjacency list, e[i][0] is the number of edges connecting vertex i, and the other
vertex for the j-th edge is e[i][j], 1≤e[i][0]≤n−1, and 1≤j≤e[i][0].
1. Calculating low[];
2. Calculating degrees for vertices in the contacted tree;
3. The number of vertices whose degree is 1 is calculated, denoted as leaf. In
leaf + 1
order to make the tree become a biconnected graph, at least
2 edges
are added into the tree.
Program
# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <vector>
# define vi vector<int>
# define pb push_back
using namespace std;
const int maxn=1010; //the upper limit of the number of
vertices
vi e[maxn]; //an adjacency list for a graph
int dfsn[maxn],low[maxn],Time,deg[maxn]; // deg[]: degrees
for vertices in a tree, Time: visited time
int n,m;
void dfs(int a,int fa){ //calculate low from branch (fa, a)
int q;dfsn[a]=low[a]=++Time;
for(int p=0;p< e[a].size();p++)
if(!dfsn[q=e[a][p]])
dfs(q,a),low[a]=min(low[a],low[q]);
else if(q!=fa)low[a]=min(low[a],dfsn[q]);
420 ◾ Algorithm Design Practice for Collegiate Programming
}
void work(){
for(int i=1;i<=n;i++) e[i].clear(); //Initialization
for(int i=0;i<m;i++){ // adjacency list e is constructed
int a,b;
scanf("%d %d",&a,&b);
e[a].pb(b);e[b].pb(a);
}
Time=0; // Initialization
memset(dfsn,0,sizeof(dfsn));
memset(deg,0,sizeof(deg));
dfs(1,-1); //calculate low
for(int i=1;i<=n;i++) // Calculating degrees for
vertices in the contacted tree
for(int p=0;p< e[i].size();p++) if(low[e[i][p]]!=low[i])
deg[low[i]]++;
int cnt=0; //number of leaves
for(int i=1;i<=n;i++) if(deg[i]==1)cnt++;
printf("%d\n",(cnt+1)/2); // the minimum number of roads
}
int main(){
while(~scanf("%d %d ",&n,&m)) work();
return 0;
}
7.4 Problems
7.4.1 Long Long Message
Little Cat is majoring in physics in the capital of Byterland. A piece of sad news
comes to him these days: his mother is ill. Being worried about spending so much on
railway tickets (Byterland is such a big country, and he has to spend 16 hours on the
train to get to his hometown), he decided only to send SMS messages to his mother.
Little Cat belongs to a family that is not rich, so he frequently visits the mobile
service center to check how much money he has spent on SMS. Yesterday, the com-
puter of the service center was broken, and printed two very long messages. The
brilliant Little Cat soon found out the following:
4. For these broken issues, Little Cat has printed his original text twice (so there
are two very long messages). Even though the original text remains the same
in two printed messages, the redundancy characters on both sides would pos-
sibly be different.
You are given those two very long messages, and you have to output the length
of the longest possible original text written by Little Cat.
Background: The SMS in the Byterland mobile service are charged in dollars-
per-byte. That is why Little Cat is worrying about how long could the longest origi-
nal text be.
Why ask you to write a program? There are four reasons:
Input
Two strings with lowercase letters on two of the input lines individually. The num-
ber of characters in each one will never exceed 100000.
Output
A single line with a single integer number—what is the maximum length of the
original text written by the little cat?
yeshowmuchiloveyoumydearmotherreallyicannotbelieve 27
ityeaphowmuchiloveyoumydearmother
Source: POJ Monthly, 2006.03.26, Zeyuan Zhu, “Dedicated to my great beloved
mother.”
ID for Online Judge: POJ 2774
Hint
Given two strings, the problem requires you to calculate the length of the longest
common substring.
Any substring in a string is a prefix for a suffix in the string. Calculating the
longest common substring for strings A and B is calculating the longest common
422 ◾ Algorithm Design Practice for Collegiate Programming
a a a b a $ a b a a
height $ a b a a String A
a
1
a $ a b a a
1
a a
2
a a a b a $ a b a a
a a b a $ a b a a
a b a $ a b a a
3
a b a a
0
b a $ a b a a
2
b a a
String B
Figure 7.15
prefix for suffixes for strings A and B. It is inefficient to enumerate all suffixes for
strings A and B. String B is adjoined to the end of string A, and a character which
doesn’t appear is inserted between A and B. For example, A=“aaaba”, B= “abaa”,
B is adjoined to the end of A, and a character ‘$’ which doesn’t appear is inserted
between A and B. The longest common prefix for suffixes for the new string is cal-
culated as Figure 7.15.
In Figure 7.15, “aa” is the longest common prefix for suffix(2) and suffix(9), and
“aa” is a suffix for B and isn’t a suffix for A; “aba” is the longest common prefix for
suffix(3) and suffix(7), and “aba” is a suffix for A and isn’t a suffix for B. The maxi-
mal value for height[] may not be the length of the longest common substring, for
the two suffixes may be in the same string. Therefore, “aba” is the longest common
substring for strings A and B.
The time complexity for the algorithm is O(|A|+|B|).
Help Farmer John by finding the longest repeating subsequence in the sequence
of samples. It is guaranteed that at least one subsequence is repeated at least K times.
Input
Line 1: Two space-separated integers: N and K;
Line 2: N+1: N integers, one per line, the quality of the milk on day i appears
on the i-th line.
Output
Line 1: One integer, the length of the longest pattern which occurs at least K
times.
8 2 4
1
2
3
2
3
2
3
1
Source: USACO 2006 December Gold
ID for Online Judge: POJ 3261
Hint
Given a sequence of integers whose length is N, and an integer K, you are required
to calculate the length of the longest repeating subsequences repeated at least K
times in the sequence, and the subsequences can be overlapping.
The problem is a typical problem for suffix arrays. And dichotomy is also used
in solving the problem.
board—one segment with only one color. We can do the following two operations
on the board:
In our daily life, we have very few words to describe a color (red, green, blue,
yellow…), so you may assume that the total number of different colors T is very small.
To make it simple, we express the names of colors as color 1, color 2, … color T. At the
beginning, the board was painted in color 1. Now the rest of the problem is left to you.
Input
The first line of input contains L (1≤L≤100000), T (1≤T≤30) and O (1≤O≤100000).
Here O denotes the number of operations. Following O lines, each contains “C A
B C” or “P A B” (here A, B, and C are integers, and A may be larger than B) as an
operation defined previously.
Output
Output the results of the output operation in order; each line contains a number.
2 2 4 2
C 1 1 2 1
P 1 2
C 2 2 2
P 1 2
Source: POJ Monthly, 2006.03.26, dodo
ID for Online Judge: POJ 2777
Hint
Initially, the board is colored with color 1. Then update operations and query opera-
tions are dealt with one by one.
Obviously, the problem is a typical problem for visible segments. Its solution is
the same as the solution to 7.2.3.2 Mayor’s Posters. Because the upper limit of the
number of colors is 30, a bitwise operation can be used to improve the efficiency.
Practice for Advanced Data Structures ◾ 425
Input
There are several test cases in the input. Each test case starts with two integers
N (0<N≤500000) and K (1≤K≤N) on the first line. The next N lines contain the
names of the children (consisting of at most 10 letters) and the integers (non-zero
with magnitudes within 108) on their cards in increasing order of the children’s
numbers, a name, and an integer separated by a single space in a line with no lead-
ing or trailing spaces.
Output
Output one line for each test case containing the name of the luckiest child and the
number of candies he/she gets. If ties occur, always choose the child who jumps out
of the circle first.
4 2 Sam 3
Tom 2
Jack 4
Mary -1
Sam 1
Source: POJ Monthly, 2006.07.30, Sempr
ID for Online Judge: POJ 2886
Hint
The key to the problem is: after the i-th child jumps out of the circle, who is the
(i+1)-th child jumping out of the circle? A segment is used to represent children.
A child jumping out of the circle can be implemented by updating a single point
in a segment tree.
426 ◾ Algorithm Design Practice for Collegiate Programming
First, we calculate the numbers of factors for each integer in [1, N ]. For exam-
ple, Mike is the sixth child who jumps out of the circle. He will get four candies.
Four is the number of positive integers that perfectly divide into 6 (factors for 6 are
1, 2, 3, and 6). It can be calculated in O(Nlog(N)).
Suppose the i-th child jumps out of the circle, and his position is now (in the
circle there are n−i+1 children, before he/she jumps out of the circle). After the i-th
child jumps out of the circle, there are n−i children in the circle. The i-th child
jumping out of the circle is implemented by deleting the now-th element in the
corresponding intervals. Suppose the root for the segment is i, and the interval that
vertex i corresponds to is [l, r]; the algorithm is as follows:
After finding the sequence number for the vertex for the now-th element, the
number of elements for vertices in the path from the vertex to the root −1.
Ikki has abstracted the interval operations emerging from his job as a tiny
programming language. He wants you to implement an interpreter for him. The
language maintains a set S, which starts out empty and is modified as specified by
the following commands:
Command Semantics
U T S←S∪T
I T S←S∩T
D T S←S−T
C T S←T−S
S T S←S⊕T
Input
The input contains exactly one test case, which consists of between 0 and 65,535
(inclusive) commands of the language. Each command occupies a single line and
appears like
X T
where X is one of “U”, “I”, “D”, “C”, and “S”, and T is an interval in one of
the forms (a,b),(a,b],[a,b) and [a,b](a,b∈Z, 0≤a≤b≤65,535), which take their usual
meanings. The commands are executed in the order they appear in the input.
End of file (EOF) indicates the end of input.
Output
Output the set S as it is after the last command is executed as the union of a
minimal collection of disjoint intervals. The intervals should be printed on one line
separated by single spaces and appear in increasing order of their endpoints. If S is
empty, just print “empty set” and nothing else.
U [1,5] (2,3)
D [3,3]
S [2,4]
C (1,5)
I (2,3]
Source: PKU Local 2007 (POJ Monthly, 2007.04.28), frkstyc
ID for Online Judge: POJ 3225
428 ◾ Algorithm Design Practice for Collegiate Programming
Hint
In the problem, four set operations, union, intersection, relative complementation,
and symmetric difference, are given. Initially a set S is empty. After a sequence of
set operations, S is the union of a minimal collection of disjoint intervals.
A segment tree is used to represent the universal set. “An interval is in the set”
is represented as 1, “An interval isn’t in the set” is represented as 0, and “Some parts
for an interval are in the set” is represented as −1. Because there are open intervals,
half-open intervals, and closed intervals, in the segment there are not only intervals,
but also points, that is, the number of vertices should be doubled.
Two operations are used to simplify set operations.
Change(l, r, c): An interval [l, r] is added into the set, or taken out from the set
(c ==1, added; and c ==0, taken out)
Reverse(l, r): An interval [l, r] is reversed. If the interval is in the set, then it is
taken out; else it is added into the set.
Operation ‘U’ corresponds to Change(l, r, 1);
Operation ‘I’ corresponds to Change(1, l−1, 0) and Change(r+1, n, 0);
Operation ‘D’ corresponds to Change(l, r, 0);
Operation ‘C’ corresponds to Change (0, l−1, 0); Change(r+1, n, 0); Reverse(l, r);
Operation ‘S’ corresponds to Reverse(l, r);
Input
The first line of the input contains exactly one positive integer d equal to the num-
ber of data sets, 1≤d≤20. The data sets follow.
The first line of each data set contains exactly one integer n, 1≤n≤8000, equal
to the number of vertical line segments. Each of the following n lines consists
Practice for Advanced Data Structures ◾ 429
of exactly three non-negative integers separated by single spaces: yi', yi", xi —the
y-coordinate of the beginning of a segment, y-coordinate of its end, and its
x-coordinate, respectively. The coordinates satisfy 0≤yi'<yi"≤8000, 0≤xi ≤8000.
The segments are disjoint.
Output
The output should consist of exactly d lines, one line for each data set. Line i should
contain exactly one integer equal to the number of triangles in the i-th data set.
1 1
5
0 4 4
0 3 1
3 4 2
0 2 2
0 2 3
Source: ACM Central Europe 2001
ID for Online Judges: POJ 1436, ZOJ 1391, UVA 2441
Hint
The solution to the problem is similar to the solution to 7.4.3 Count Color. The
interval [l, r] on the Y-axis is regarded as a segment tree, and the projection for a
vertical line on the Y-axis is regarded as a segment. The number of triangles is
calculated by enumerating segments from left to right.
7.4.7 Crane
ACM has bought a new crane (crane—jeřáb). The crane consists of n segments of
various lengths, connected by flexible joints. The end of the i-th segment is joined
to the beginning of the i+1-th one, for 1≤i<n. The beginning of the first segment
is fixed at point with coordinates (0, 0) and its end at point with coordinates (0, w),
where w is the length of the first segment. All of the segments lie always in one
plane, and the joints allow arbitrary rotation in that plane. After a series of unpleas-
ant accidents, it was decided that the software that controls the crane must contain
a piece of code that constantly checks the position of the end of the crane and stops
the crane if a collision should happen.
430 ◾ Algorithm Design Practice for Collegiate Programming
Your task is to write a part of this software that determines the position of the
end of the n-th segment after each command. The state of the crane is determined
by the angles between consecutive segments. Initially, all of the angles are straight,
i.e., 180°. The operator issues commands that change the angle in exactly one joint.
Input
The input consists of several instances, separated by single empty lines.
The first line of each instance consists of two integers 1≤n≤10,000 and c≥0 sep-
arated by a single space—the number of segments of the crane and the number of
commands. The second line consists of n integers l1, …, ln (1≤li≤100) separated by
single spaces. The length of the i-th segment of the crane is li. The following c lines
specify the commands of the operator. Each line describing the command consists
of two integers s and a (1≤s<n, 0≤a≤359) separated by a single space—the order to
change the angle between the s-th and the s+1-th segment to a degrees (the angle is
measured counterclockwise from the s-th to the s+1-th segment).
Output
The output for each instance consists of c lines. The i-th of the lines consists of
two rational numbers x and y separated by a single space—the coordinates of the
end of the n-th segment after the i-th command, rounded to two digits after the
decimal point.
The outputs for each two consecutive instances must be separated by a single
empty line.
2 1 5.00 10.00
10 5
1 90 -10.00 5.00
-5.00 10.00
3 2
5 5 5
1 270
2 90
Source: CTU Open 2005
ID for Online Judge: POJ 2991
Hint
A segment tree is used to represent the problem. The root for the segment tree is the
interval [1, n] representing n segments. Each node in the segment tree represents
Practice for Advanced Data Structures ◾ 431
an interval [l, r]. In a node there are two pointers, where its left pointer points to
the coordinates of the starting point for segment l, and its right pointer points
to the coordinates of the end point for segment r. Obviously, after a command
is executed, the right pointer of the root is the coordinates of the end of the n-th
segment.
7.4.8 Is It a Tree?
A tree is a well-known data structure that is either empty (null, void, nothing) or is
a set of one or more nodes connected by directed edges between nodes, satisfying
the following properties:
There is exactly one node, called the root, to which no directed edges point.
Every node except the root has exactly one edge pointing to it.
There is a unique sequence of directed edges from the root to each node.
For example, consider Figure 7.16, in which nodes are represented by circles and
edges are represented by lines with arrowheads. The first two of these are trees, but
the last is not.
In this problem, you will be given several descriptions of collections of nodes
connected by directed edges. For each of these, you are to determine if the collec-
tion satisfies the definition of a tree or not.
Input
The input will consist of a sequence of descriptions (test cases) followed by a pair
of negative integers. Each test case will consist of a sequence of edge descriptions
followed by a pair of zeros. Each edge description will consist of a pair of integers;
the first integer identifies the node from which the edge begins, and the second
integer identifies the node to which the edge is directed. Node numbers will always
be greater than zero.
5 1 3 2 5
3 6 2 8 7 6 3 6 2
8 4 9 5 4 8 4
Figure 7.16
432 ◾ Algorithm Design Practice for Collegiate Programming
Output
For each test case display the line “Case k is a tree.” or the line “Case k is not a
tree.”, where k corresponds to the test case number (they are sequentially numbered
starting with 1).
Sample Input Sample Output
68 53 52 64 56 00 Case 1 is a tree.
Case 2 is a tree.
81 73 62 89 75 74 78 76 00 Case 3 is not a tree.
38 68 64 53 56 52 00
-1 -1
Source: ACM 1997 North Central Regionals
IDs for Online Judges: POJ 1308, ZOJ 1268, UVA 615
Hint
The problem is solved based on the definition of a tree.
When edges are input, in-degrees and out-degrees for nodes are calculated. If
there exists a node whose in-degree is larger than 1, or the number of nodes whose
in-degree is 0 is larger than 1, the case is not a tree. After all edges are input, if there
is no above case, the case is a tree.
Input
The input consists of a sequence of one or more postal routes. A route is composed
of a sequence of street names (strings), one per line, and is terminated by the string
“deadend ” which is NOT part of the route. The first and last letters of each street
name specify the two intersections for that street, and the length of the street name
indicates the cost of traversing the street. All street names will consist of lowercase
alphabetic characters.
For example, the name foo indicates a street with intersections f and o of length
3, and the name computer indicates a street with intersections c and r of length 8.
No street name will have the same first and last letter, and there will be at most one
street directly connecting any two intersections. As specified, the number of inter-
sections with odd degree in a postal route will be at most two. In each postal route,
there will be a path between all intersections, i.e., the intersections are connected.
Output
For each postal route, the output should consist of the cost of the minimal tour that
visits all streets at least once. The minimal tour costs should be output in the order
corresponding to the input postal routes.
One 11
two 114
three
deadend
mit
dartmouth
linkoping
tasmania
york
emory
cornell
duke
kaunas
hildesheim
concord
arkansas
williams
glasgow
deadend
Source: Duke Internet Programming Contest 1992
ID for Online Judge: UVA 117
434 ◾ Algorithm Design Practice for Collegiate Programming
Input
The first line in the input contains the number of test cases, at most 20. Each test
case starts with a line containing two numbers, V and E: the number of vertices
(1≤V≤100) and edges (1≤E≤500) in the graph. The vertices are numbered from
1 to V. Then follow E lines specifying the edges. Each such line will be in the format
a b type where a and b are two integers specifying the endpoints of the edge. type
will either be the character “U”, if the edge is undirected, or “D”, if the edge is
directed. In the latter case, the edge starts at a and ends at b.
Output
If an Euler circuit exists, output an order in which the vertices can be traversed
on a single line. The vertex numbers should be delimited with a single space, and
Practice for Advanced Data Structures ◾ 435
the start and end vertex should be included both at the beginning and the end of
the sequence. Since most graphs have multiple solutions, any valid solution will be
accepted. If no solution exists, output the line “No Euler circuit exists”. Output a
blank line between each test case.
2 1 3 4 2 5 6 5 4 1
6 8
1 3 U No Euler circuit exists
1 4 U
2 4 U
2 5 D
3 4 D
4 5 U
5 6 D
5 6 U
4 4
1 2 D
1 4 D
2 3 U
3 4 U
Source: 2004 ICPC Regional Contest Warmup 1
ID for Online Judge: UVA 10735
Each matched H’s edge of (e, v) will contribute to the in-degree of vertex v in
the directed graph, and unmatched edge (e, u) contributes to the out-degree of u.
Since we want to make the in-degree and out-degree of each vertex equal,
each vertex must have an equal number of matched and unmatched edges in H.
Additionally, each directed edge has to be matched with its respective head from G.
After finding a matching in H, satisfying the outlined constraints, we can assign
direction to each undirected G’s edge and find that the Euler tour is the resulting
directed graph with any standard algorithm. If a matching doesn’t exist, there will
be no Euler tour in the original graph.
Input
The input contains T test cases. The first line of the input contains the integer T.
The first line of each test case contains an integer N (5≤N≤100), giving the
number of beads my sister was able to collect. Each of the next N lines contains two
integers describing the colors of a bead. Colors are represented by integers ranging
from 1 to 50.
Output
For each test case in the input, first output the test case number as shown in the
sample output. Then, if you apprehend that some beads may be lost, just print the
sentence “some beads may be lost” on a line by itself. Otherwise, print N lines
with a single bead description on each line. Each bead description consists of two
Green
White
White
Green
Green
Blue
Red
Red
Figure 7.17
Practice for Advanced Data Structures ◾ 437
integers giving the colors of its two ends. For 1≤i≤N−1, the second integer on line
i must be the same as the first integer on line i +1. Additionally, the second integer
on line N must be equal to the first integer on line 1. Since there are many solutions,
any one of them is acceptable.
Print a blank line between two successive test cases.
2 Case #1
5 some beads may be lost
1 2
2 3 Case #2
3 4 2 1
4 5 1 3
5 6 3 4
5 4 2
2 1 2 2
2 2
3 4
3 1
2 4
Source: ACM Shanghai 2000, University of Valladolid New Millenium Contest
IDs for Online Judges: UVA 10054, UVA 2036
Hint
A graph is constructed as follows: each color is represented as a node, and each bead
is represented as an edge. The problem requires you to determine whether the graph
is an Euler graph or not.
The problem is similar to 7.3.1.2 Catenyms.
“Oh no!” cried Doraemon. “My door is broken, and my small propellers have all
run out of batteries...” Well, that means Nobita has got to go without Doraemon’s
magic tools. “Ah, I still have this. It may well be useful.” From his fourth-dimensional
pocket, Doraemon takes out a map of their living area. He then marks on it the
places where Nobita has to visit by asterisks (‘*’), and where Jyian or his teacher
may appear by crosses (‘X’). Now Nobita’s job is simple—he has to find the shortest
route, through which he would not visit any of the “crosses”, and he could finish the
maximum number of the jobs (if not all) given by his mum. What he needs is just
a computer program that works out the path.
Imagine that you are Nobita and write the program.
Input
The input file contains no more than 20 test cases. The details of each set are given
as follows:
The first line of each case contains two integers r and c (1≤r,c≤20), which are
the number of rows and columns of the map respectively. The next r lines, each with
c characters, give the map itself. For each character, a space “ ” stands for an open
space; a hash mark “#” stands for an obstructing wall; the capital letter “S” stands
for the position of Nobita’s house, which is where his journey is to start and end;
the capital letter “X” stands for a dangerous place; and an asterisk “*” stands for a
place he has to visit. The perimeter of the map is always closed, i.e., there is no way
to get out from the coordinate of the “S”. The number of places that Nobita has to
visit is at most 10.
The input file is terminated by a null case where r = c = 0. This case should not
be processed.
Output
For each test case, if Nobita cannot visit any target places at all, just print the
line “Stay home!”. Otherwise, your program should output the lexicographically
smallest shortest path so that the number of target places that Nobita visits is maxi-
mized. Use the letters ‘N’, ‘S’, ‘E’, and ‘W’ to denote north, south, east and west
respectively. Note that by “north” we mean facing upwards. You can be sure that
the length of a correct output path will never exceed 200.
5 5 WWSSEEWWNNEE
##### EEWW
# S# Stay home!
# XX#
# *#
Practice for Advanced Data Structures ◾ 439
#####
5 5
#####
#* X#
###X#
#S *#
#####
5 5
#####
#S X#
# X#
# #*#
#####
0 0
Source: Programming Contest for Newbies 2005
ID for Online Judge: UVA 10818
Hint
The problem is a Traveling Salesperson problem, that is, the problem is NP-complete.
Because the number of places that Nobita has to visit is at most 10, a simple search
suffices.
The problem is similar to 7.3.2.2 Nuts for Nuts. Suppose Nobita’s current posi-
tion is (x, y) and the sequence of nodes that Nobita goes through is z. (x, y, z)
constitutes a state. Initially, the position of Nobita’s house (Sx, Sy) and z=0 is as the
initial state and added into a queue q. Then BFS is used. And hash technology is
also used to avoid repetitions.
Input
The input consists of a number of test cases. The first line of each test case contains
two integers h and w giving the height and width of the map, respectively, in miles.
For simplicity, each map is divided into grid points that are a mile square. The next
h lines contain w characters, each describing one square on the map. Each point on
the map is one of the following:
Blackbeard can only travel in the four cardinal directions; that is, he cannot
travel diagonally. Blackbeard travels at a nice slow pace of one mile (or square) per
hour, but he sure can dig fast, because digging up a treasure incurs no time penalty
whatsoever.
The maximum dimension of the map is 50 by 50. The input ends with a case
where both h and w are 0. This case should not be processed.
Output
For each test case, simply print the least number of hours Blackbeard needs to col-
lect all his treasure and return to the landing point. If it is impossible to reach all
the treasures, print out −1.
7 7 10
~~~~~~~ 32
~#!###~
~...#.~
~~....~
~~~.@~~
.~~~~~~
...~~~.
10 10
Practice for Advanced Data Structures ◾ 441
~~~~~~~~~~
~~!!!###~~
~##...###~
~#....*##~
~#!..**~~~
~~....~~~~
~~~....~~~
~~..~..@~~
~#!.~~~~~~
~~~~~~~~~~
0 0
Source: A Special Contest 2005
ID for Online Judge: UVA 10937
Hint
The problem is also a Traveling Salesperson problem. The solution to the problem is
the same as the solution to 7.3.2.2 Nuts for Nuts. BFS, hash technology, and state
compression are used to solve the problem.
Chapter 8
443
444 ◾ Algorithm Design Practice for Collegiate Programming
1. Dot product.
Suppose coordinates for points are as follows: A(x1, y1), B(x2, y2), C(x3, y3),
D(x4, y4). Vector AB=(x 2 −x1, y2 −y1)=(x AB , y AB ), where its magnitude
AB = x AB
2
+ y AB
2
. Vector CD=(x4 −x3, y4 −y3)=(xCD, yCD), where its magni-
tude CD = xCD 2
+ yCD
2
. Vectors AB and CD are shown in Figure 8.1.
The dot product of AB and CD is defined by AB • CD =xAB×xCD+yAB×yCD=
|AB|×|CD|×cos(a), where a is the angle between vector AB and vector CD,
AB • CD
a = acos , 0°≤a≤180°. Obviously, if the dot product AB • CD
| AB | × | CD |
is negative, the angle a between vector AB and vector CD is an obtuse angle;
if the dot product AB • CD is positive, the angle a between vector AB and
vector CD is an acute angle; and if the dot product AB • CD is zero, vector
AB and vector CD are vertical.
2. Cross product.
In Figure 8.2, there are two vectors, P1 and P2.
B(x2, y2)
C(x3, y3)
Figure 8.1
y
P1 + P2(x1 + x2, y1 + y2)
P1(x1, y1)
P2(x2, y2)
0 x
Figure 8.2
Practice for Computational Geometry ◾ 445
y y
P1 + P2(x1 + x2, y1 + y2)
P1(x1, y1)
y' P' (x – x , y – y ) P' + P' (x + x – 2x
1 1 0 1 0 1 2 1 2 0,
y1 + y2 – 2y0)
Figure 8.3
446 ◾ Algorithm Design Practice for Collegiate Programming
P1
P2
P2
P1
P0 P1 P2
P0 P0
(a) (b) (c)
Figure 8.4
8.1.1.1 Transmitters
In a wireless network with multiple transmitters sending on the same frequencies, it
is often a requirement that signals don’t overlap, or at least that they don’t conflict.
One way of accomplishing this is to restrict a transmitter’s coverage area. This prob-
lem uses a shielded transmitter that only broadcasts in a semicircle.
A transmitter T is located somewhere on a 1000-square-meter grid. It broad-
casts in a semicircular area of radius r. The transmitter may be rotated any amount,
but not moved. Given N points anywhere on the grid, compute the maximum
number of points that can be simultaneously reached by the transmitter’s signal.
Figure 8.5 shows the same data points with two different transmitter rotations.
All input coordinates are integers (0−1000). The radius is a positive real number
greater than 0. Points on the boundary of a semicircle are considered within that
semicircle. There are 1−150 unique points to examine per transmitter. No points are
at the same location as the transmitter.
Input
Input consists of information for one or more independent transmitter problems.
Each problem begins with one line containing the (x, y) coordinates of the trans-
mitter followed by the broadcast radius, r. The next line contains the number of
points N on the grid, followed by N sets of (x, y) coordinates, one set per line. The
end of the input is signaled by a line with a negative radius; the (x, y) values will
be present but indeterminate. Figure 8.5 represents the data in the first two example
data sets below, though they are on different scales. Figures 8.5(a) and 8.5(c) show
transmitter rotations that result in maximal coverage.
T T
T
Figure 8.5
Practice for Computational Geometry ◾ 447
Output
For each transmitter, the output contains a single line with the maximum number
of points that can be contained in some semicircle.
25 25 3.5 3
7 4
25 28 4
23 27
27 27
24 23
26 23
24 29
26 29
350 200 2.0
5
350 202
350 199
350 198
348 200
352 200
995 995 10.0
4
1000 1000
999 998
990 992
1000 999
100 100 −2.5
Source: ACM Mid-Central USA 2001
IDs for Online Judges: POJ 1106, ZOJ 1041, UVA 2290
Analysis
Suppose the point for the transmitter is p0. Because the transmitter may be
rotated any amount, and broadcasts in a semicircular area of radius r, a straight
line connecting any point and p0 can be regarded
asthe lower boundary line for
the semicircular. If the straight line containing p0 pi is the lower boundary line
448 ◾ Algorithm Design Practice for Collegiate Programming
for the semicircular, point pj in the semicircular area must meet the following
conditions:
1. pj must be
in
the
semicircular
area whose lower boundary line contains p0 pi ,
that is, p0 pi ^ p0 p j ≥ 0;
2. The distance between pj and p0 must be less than the radius, that is, p0 p j ≤ r .
Each time point i is as a starting point. By using cross product, the number
of points
si in the semicircular area can be calculated. If the straight line contain-
ing p0 pi is as the lower boundary line for the semicircular, these points are in the
semicircular area.
Obviously, the maximum number of points that can be contained in some
semicircle are S = max{ si }.
1≤i ≤n
Program
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
const double epsi = 1e-10;
const double pi = acos(-1.0);
const int maxn = 50005;
struct Point { //Struct for point calculation
double x, y;
Point(double _x = 0, double _y = 0): x(_x), y(_y) { }
// Point vector
Point operator -(const Point &op2) const { //Vector
reduction
return Point(x - op2.x, y - op2.y);
}
double operator ^(const Point &op2) const { //Cross
product for 2 point vectors
return x * op2.y - y * op2.x;
}
};
inline int sign(const double &x) { //return positive,
negative, or 0 mark for x
if (x > epsi) return 1;
if (x < -epsi) return -1;
return 0;
}
Practice for Computational Geometry ◾ 449
The absolute value of the cross product P1^P2 for vector P1 and P2 is the
area of the parallelogram whose points are the origin (0, 0), P1, P2, and P1+P2
(Figure 8.6). And the area of the triangle whose points are origin, P1 and P2
P1 ^ P2
S∆(0,0) P1P2 = .
2
450 ◾ Algorithm Design Practice for Collegiate Programming
y
P1 + P2(x1 + x2, y1 + y2)
P1(x1, y1)
P2(x2, y2)
0 x
Figure 8.6
Therefore, the cross product can be used to calculate the area of a polygon.
Points can be sorted clockwise or counterclockwise as p0 ... pn−1, and pn=p0. The
n−2
∑P ^ P i i +1
i =1
area of the polygon is S = , where vector Pi is p0 pi , 1≤i≤n−1.
2
8.1.1.2 Area
You are going to compute the area of a special kind of polygon. One vertex of the
polygon is the origin of the orthogonal coordinate system. From this vertex, you
may go step by step to the following vertexes of the polygon until you go back to
the initial vertex. For each step you may go North, West, South, or East with a step
length of one unit, or go Northwest, Northeast, Southwest, or Southeast with a
step length of the square root of two.
For example, Figure 8.7 shows a legal polygon to be computed and its area is 2.5.
Input
The first line of input is an integer t (1≤t≤20), the number of the test polygons.
Each of the following lines contains a string composed of digits 1−9 describing how
the polygon is formed by walking from the origin. Here 8, 2, 6, and 4 represent
Figure 8.7
Practice for Computational Geometry ◾ 451
North, South, East and West, while 9, 7, 3, and 1 denote Northeast, Northwest,
Southeast, and Southwest respectively. Number 5 only appears at the end of the
sequence, indicating the end of walking. You may assume that the input polygon is
valid, which means that the endpoint is always the start point and the sides of the
polygon are not cross to each other. Each line may contain up to 1000000 digits.
Output
For each polygon, print its area on a single line.
4 0
5 0
825 0.5
6725 2
6244865
Source: POJ Monthly, 2004.05.15 Liu Rujia@POJ
ID for Online Judge: POJ 1654
Analysis
Suppose points for the polygon are p0 , p1 ,..., pn −1, where p0 is (0, 0) and pn=p0. Based
on the sequence of sides for the polygon,
pi pi +1 is the i+1-th side in the polygon,
0≤i≤n−1; and the n-th side is pn−1 p0 . From (0, 0), the vectors for points in the poly-
gon P0, P1, …, Pn−1 with respect to point p0 are calculated
Calculate the cross product for two vectors for the front and the rear of each side
n −1
∑P ^ P i i +1
i =0
Pi^Pi+1(0≤i≤n−1). The area for the polygon is S = .
2
Program
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
452 ◾ Algorithm Design Practice for Collegiate Programming
#include <iostream>
#include <string>
using namespace std;
const double epsi = 1e-10;
const double pi = acos(-1.0);
const int maxn = 100005;
inline int sign(const double &x) { //positive or negative
if (x > epsi) return 1;
if (x < -epsi) return -1;
return 0;
}
struct Point { //Calculation for points
long long x, y;
Point(double _x = 0, double _y = 0): x(_x), y(_y) { }
//construct points
Point operator +(const Point &op2) const { // Vector
addition
return Point(x + op2.x, y + op2.y);
}
long long operator ^(const Point &op2) const { // Cross
product
return x * op2.y - y * op2.x;
}
};
int main() {
int test = 0;
string s;
long long ans;
scanf ("%d\n", &test ); // the number of the test
polygons
for (; test; test --) { //every polygon is dealt with
cin >> s; //polygon string
ans = 0;
Point p = Point( 0 , 0) , p1; // the origin
for (int i = 0 ; i < s.size() ; i ++) {
if ( s[i] == '1') p1 = p+Point(-1, -1); // Southwest
if ( s[i] == '2') p1 = p+Point(0, -1); // South
if ( s[i] == '3') p1 = p+Point(1, -1);
// Southeast
if ( s[i] == '4') p1 = p + Point(-1,0); // West
if ( s[i] == '5') p1 = Point(0, 0); // the end of
walking
if ( s[i] == '6') p1 = p + Point(1, 0); // East
if ( s[i] == '7') p1 = p+Point(-1, 1);
// Northwest
if ( s[i] == '8') p1 = p + Point(0, 1); // North
if ( s[i] == '9') p1 = p + Point(1, 1);
// Northeast
ans += p ^ p1; //Accumulation for Cross product
p = p1; //continue to walk
Practice for Computational Geometry ◾ 453
}
if (ans<0 ) ans = -ans; //absolute value for area
cout<<ans/2; //output area
if (ans % 2 ) cout << ".5"; //odd
cout << endl;
}
return 0;
}
Figure 8.8
last thrown stick is always on top, but he wants to find all the sticks that are on top.
Stan’s sticks are quite thin, so thin that their thickness can be neglected (Figure 8.9).
Input
Input consists of a number of cases. The data for each case start with 1≤n≤100000,
the number of sticks for this case. The following n lines contain four numbers each;
these numbers are the planar coordinates of the endpoints of one stick. The sticks
are listed in the order in which Stan has thrown them. You may assume that there
are not more than 1000 top sticks. The input is ended by the case with n=0. This
case should not be processed.
Output
For each input case, print one line of output listing the top sticks in the format given
in the sample. The top sticks should be listed in order in which they were thrown.
Figure 8.9 illustrates the first case from input.
5 Top sticks: 2, 4, 5.
1 1 4 2 Top sticks: 1, 2, 3.
2 3 3 1
1 -2.0 8 4
1 4 8 2
3 3 6 -2.0
3
0 0 1 1
1 0 2 1
2 0 3 1
0
Source: Waterloo local 2005.09.17
IDs for Online Judges: POJ 2653, ZOJ 2551
Huge input, scanf is recommended.
Practice for Computational Geometry ◾ 455
Figure 8.9
Analysis
The sticks are listed in the order in which Stan has thrown them. Each stick i is
enumerated in ascending order of numbers (i.e., bottom-up), 1≤i≤n:
Each stick j which is over stick i is enumerated, i+1≤j≤n. If there is a stick that
stick i intersects with, then there is a stick on top of stick i, and stick i+1 is enumer-
ated. If there is no stick on top of stick i, stick i is a stick on top.
Two crossings
are used to determine
whether
two
sticks
intersect or not. Suppose
stick i is p1i p2i , and stick j is p1j p2j . If p1i p2i and p1j p2j intersect, the two following
conditions must hold:
j j i i i i i j
1. p
1 p2 crosses
p1 p2 , that is, positive and negative signs for p1 p2 ^ p1 p1 and
p1i p2i ^ p1i p2j are different, or one of the two cross products is 0;
i i j j j j j i
2. p p1 p2 , that is, positive and negative signs for p1 p2 ^ p1 p1 and
1 p2 crosses
p1j p2j ^ p1j p2i are different, or one of the two cross products is 0.
Program
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
456 ◾ Algorithm Design Practice for Collegiate Programming
#include <iostream>
using namespace std;
const double epsi = 1e-10; // Infinitesimal
const double pi = acos(-1.0);
const int maxn = 100005; //the upper limit of the number of
sticks
inline int sign(const double &x) {
if (x > epsi) return 1;
if (x < -epsi) return -1;
return 0;
}
//structure and calculation for point
struct Point {
double x, y;
Point(double _x = 0, double _y = 0): x(_x), y(_y) { }
//construct a point
Point operator +(const Point &op2) const {
return Point(x + op2.x, y + op2.y);
}
Point operator -(const Point &op2) const {
return Point(x - op2.x, y - op2.y);
}
double operator *(const Point &op2) const {
return x * op2.x + y * op2.y;
}
Point operator *(const double &d) const {
return Point(x * d, y * d);
}
Point operator /(const double &d) const {
return Point(x / d, y / d);
}
double operator ^(const Point &op2) const { // cross
product for vectors
return x * op2.y - y * op2.x;
}
bool operator !=(const Point &op2) const {
return sign (op2.x - x) != 0 || sign( op2.y - y) != 0;
}
};
inline double sqr(const double &x) { //x2
return x * x;
}
inline double mul(const Point &p0, const Point &p1,
const Point &p2) {
// cross product for p0 p1 and p1 p2
return (p1 - p0) ^ (p2 - p0);
}
inline double dis2(const Point &p0, const Point &p1) {
return sqr(p0.x - p1.x) + sqr(p0.y - p1.y);
}
Practice for Computational Geometry ◾ 457
inline double dis(const Point &p0, const Point &p1) { // p0 p1
return sqrt(dis2(p0, p1));
}
inline int cross( const Point &p1 , const Point &p2 , const
Point &p3 , const Point
&p4 , Point &p) { //determine
whether p1 p2 crosses p3p4
double a1 = mul( p1, p2 , p3), a2 = mul( p1, p2 , p4 ) ;
if
(sign
(
a1 ) ==0 && sign ( a2 ) == 0) return 2; //if
p1 p2 and p3p4 coincide, return 2
if (sign ( a1 ) == sign ( a2 )) return 0;
//if p1 p2
doesn't cross p3p4 , return
0
return 1; // p1 p2 crosses p3p4
}
int n;
Point p1[maxn] , p2[maxn] , tp; //a sequence of coordinates
for sticks p1[] and p2[]
int main() {
int test = 0; //number of test cases
while ( scanf ("%d", &n ) && n ) { //number of sticks
printf("Top sticks:");
bool fl = false ;
for ( int i = 1 ; i <= n ; i ++) // a sequence of
coordinates for n sticks
scanf("%lf %lf %lf %lf" , &p1[i].x , & p1[i].y , &
p2[i].x ,& p2[i].y);
for ( int i = 1 ; i <= n ; i ++) { // Each stick i is
enumerated bottom-up, 1≤i≤n
bool flag = false ;
for (int j = i+1 ; j <= n ; j ++) // Each stick j
which is over stick i is enumerated
if ( cross ( p1[i] , p2[i] , p1[j] , p2[j] , tp ) == 1
&& cross ( p1[j] , p2[j] , p1[i] , p2[i] , tp ) == 1) { flag =
true; break; }
if (flag == false && fl == true ) printf(",");
if (flag == false ) printf(" %d", i ), fl = true;
}
printf(".\n");
}
return 0;
}
P2(x2, y2)
P0(x0, y0)
Figure 8.10
Based on this information, the intersection point when two line segments
intersect can be calculated. For example, in Figure 8.11, point P is the inter-
section point for line segment AB and line segment CD.
DD' is a vertical line for segment line AB from point D, and CC' is a
vertical line for line segment AB from point C. Because ∆DD'P ∼ ∆CC'P,
DD ' DP . Because S |DD ' | × | AB | | CC ' | × | AB |
= ∆ABD = , and S∆ABC = ,
CC ' PC 2 2
| DP | S ∆ABD | AD ^ AB | | mul(D , B , A ) |
= = =
.
| PC | S ∆ACB | AC ^ AB | | mul(C , B , A ) |
Because DP = x D − x p = y D − y p ,
PC x P − xC y P − yC
S ∆ABD × xc + S ∆ABC × x D mul(D , B , A ) × xC − mul(C , B , A ) × x D
xp = = , and
S ∆ABD + S ∆ABC mul(D , B , A ) − mul(C , B , A )
S ∆ABD × y c + S ∆ABC × y D mul(D , B , A ) × y C − mul(C , B , A ) × y D
yp = = .
S ∆ABD + S ∆ABC mul(D , B , A ) − mul(C , B , A )
B
D C´
P
D´
C
Figure 8.11
Practice for Computational Geometry ◾ 459
are parallel, 2) intersect in a line because they are on top of one another (i.e., they
are the same line), 3) intersect in a point. In this problem you will use your algebraic
knowledge to create a program that determines how and where two lines intersect.
Your program will repeatedly read in four points that define two lines in the x-y
plane and determine how and where the lines intersect. All numbers required by
this problem will be reasonable, say between −1000 and 1000.
Input
The first line contains an integer N between 1 and 10 describing how many pairs of
lines are represented. The next N lines will each contain eight integers. These integers
represent the coordinates of four points on the plane in the order x1 y1 x 2 y2 x3 y3 x4 y4.
Thus, each of these input lines represents two lines on the plane: the line through
(x1, y1) and (x 2, y2) and the line through (x3, y3) and (x4, y4). The point (x1, y1) is
always distinct from (x 2, y2). Likewise with (x3, y3) and (x4, y4).
Output
There should be N+2 lines of output. The first line of output should read
“INTERSECTING LINES OUTPUT”. There will then be one line of output for
each pair of planar lines represented by a line of input, describing how the lines
intersect: “NONE”, “LINE”, or “POINT”. If the intersection is a point, then your
program should output the x and y coordinates of the point, correct to two decimal
places. The final line of output should read “END OF OUTPUT:”.
Analysis
The problem requires you to determine the relation between a pair of lines: they
are parallel, they are the same line, or they intersect; and if they intersect, you need
to output the x and y coordinates of the intersection point. One crossing is used to
460 ◾ Algorithm Design Practice for Collegiate Programming
determine
whether the two lines are parallel or the same line (whether p3 p4 crosses
p1 p2 or not):
Program
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const double epsi = 1e-10; // Infinitesimal
inline int sign(const double &x) { // positive and negative
signs for x
if (x > epsi) return 1;
if (x < -epsi) return -1;
return 0;
}
struct Point { // structure and calculation for point
double x, y;
Point(double _x = 0, double _y = 0): x(_x), y(_y) { }
//Construct point
Point operator -(const Point &op2) const { // subtraction
for vectors
return Point(x - op2.x, y - op2.y);
}
double operator ^(const Point &op2) const { //cross
product
return x * op2.y - y * op2.x;
}
};
inline double sqr(const double &x) { // x2
return x * x;
}
inline double mul(const Point
&p0,const
Point
&p1,const Point
&p2){ //cross product for p0 p1 and p0 p2
Practice for Computational Geometry ◾ 461
For edge vector p1 p2 , suppose Ap = x − x , B B = y − y , and
1 p2 2 1 p1 p2 p1 p2 2 1
p1 p2
=−
C p ; and for edge vector p1 p3 , suppose Ap = x − x , B = y − y ,
1 p2 1 p3 3 1 p1 p3 3 1
2
p1 p3
and C p =− ; p1 is as the origin. The intersection point of perpendicu-
1 p3
2
lar bisectors for side p1 p2 and side p1 p3 in the triangle is p1∗ = ( x1∗ , y1∗ ), where
× B −C × B
C p × A −C × A
C p
1 p3 p1 p2 p1 p2 p1 p3 1 p3 p1 p2 p1 p2 p1 p3
x1∗ = − × B − B × A
, and y1∗ = − × A − B × A
.
Ap
1 p3 p1 p2 p1 p3 p1 p2 Bp
1 p3 p1 p2 p1 p2 p1 p3
( x − h )2 + ( y − k )2 = r 2 (1)
x 2 + y 2 + cx + dy − e = 0 (2)
Input
Each line of input to your program will contain the x and y coordinates of three
points, in the order Ax, Ay, Bx, By, Cx, Cy. These coordinates will be real numbers
separated from each other by one or more spaces.
Output
Your program must print the required equations on two lines using the for-
mat given in the sample below. Your computed values for h, k, r, c, d, and e in
Equations 1 and 2 above are to be printed with three digits after the decimal
point. Plus and minus signs in the equations should be changed as needed to
avoid multiple signs before a number. Plus, minus, and equal signs must be
separated from the adjacent characters by a single space on each side. No other
spaces are to appear in the equations. Print a single blank line after each equa-
tion pair.
Practice for Computational Geometry ◾ 463
Analysis
On a plane, if three points aren’t on a straight line, the three points are points of a
triangle, and the circle through the three points is a circumcircle.
For equation 1, (x−h)2+(y−k)2=r2, (h, k) is the Cartesian coordinate for the cen-
ter of the circumcircle, and r is the radius of the circumcircle.
For equation 2, x 2+y2+cx+dy−e=0, c=−2×h, d=−2×k, e=h2+k 2−r2.
The key to the problem is to calculate the center (h, k) of the circumcircle for
ΔABC. Distances between the center and the points of the triangle are same. The
radius r is the distance between the center and any point of the triangle.
Program
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const double epsi = 1e-10; //precision
inline int sign(const double &x) { //positive or negative
sign for x
if (x > epsi) return 1;
if (x < -epsi) return -1;
return 0;
}
struct Point { // structure and calculation for point
double x, y;
Point(double _x = 0, double _y = 0): x(_x), y(_y) { }
//point (x, y)
464 ◾ Algorithm Design Practice for Collegiate Programming
Figure 8.12
Input
The first line of the input file contains one integer S (0<S<3500), which indicates
how many sets of input there are. The next S lines contain S sets of input. Each
input contains one integer N (0≤N<231).
Output
For each set of input, you should output in a single line the maximum number of
pieces of land possible to get for the value of N.
4 1
1 2
2 4
3 8
4
Source: Math & Number Theory Lovers’ Contest
ID for Online Judge: UVA 10213
Practice for Computational Geometry ◾ 467
Analysis
The number of pieces of land is the number of faces. Euler’s Formula v−e+f =2 is
used to solve the problem, where v is the number of vertices, e is the number of
edges, and f is the number of faces.
First, the number of vertices v is calculated. There are n points on the ellipse’s
boundary. For a point x on the boundary, there are n−1 straight lines connecting
point x and other points. For a straight line l, there are i points on the left, and
there are n−2−i points on the right. Because all these points are connected with one
another with straight lines, there are at most i×(n−i−2) points on a straight line.
n−3
Second, the number of edges e is calculated. There are n points on the elliptical
shaped land’s boundary. There are n edges on the boundary. There are n straight
lines connecting adjacent points. There are no intersection points on these edges.
For other straight lines connecting points, there are i×(n−i−2) intersection points
on a straight line. On a straight line, there are i×(n−i−2)+1 edges. Therefore,
n−3
e = 2×n+
n
2 ∑ i × (n − i − 2) + 1.
i =1
Euler’s Formula v−e+f =2 is used to solve the problem. The maximum number
n 4 − 6n 3 + 23n 2 −18n
of pieces of land f = +1.
24
Because the upper limit for n is 231, the high-precision method is also used.
Program
# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <string>
# include <cmath>
# include <algorithm>
using namespace std;
typedef long long int64;
int64 m=1e8; //High-precision number: a decimal number with
8-digit
struct Bigint{ // High-precision number
468 ◾ Algorithm Design Practice for Collegiate Programming
a.s[i]=d/b;d%=b;
}
while(a.l&&!a.s[a.l]) a.l--; //omit 0
return a;
}
Bigint operator *(Bigint a,Bigint b){ // a[]*b[]
Bigint c; memset(c.s,0,sizeof(c.s))
for(int i=0;i<=a.l;i++){
for(int j=0;j<=b.l;j++){
c.s[i+j]+=a.s[i]*b.s[j];
if(c.s[i+j]>m){ //carry
c.s[i+j+1]+=c.s[i+j]/m;
c.s[i+j]%=m;
}
}
}
c.l=a.l+b.l+10;
while(!c.s[c.l]&&c.l)c.l--;
while(c.s[c.l]>m){
c.s[c.l+1]+=c.s[c.l]/m;
c.s[c.l++]%=m;
}
return c;
}
int v;
void work(){
ans.read(v);tmp.read(24); //ans: number of points
ans=ans*ans*ans*ans+23*(ans*ans)+tmp-6*(ans*ans*ans)-18*ans;
//formula
ans=ans/24; //calculate and output the number of faces
ans.print();printf("\n");
}
int main(){
int casen;scanf("%d",&casen); //number of test cases
while(casen--){ //test cases are dealt with one by one
scanf("%d",&v); //number of points
work(); //calculate and output the number of faces
}
return 0;
}
R2 R3
R1
The steps for calculating the area for the union of rectangles are as follows:
Figure 8.14 Discrete points A, B, C, and D are intersection points for sides of
rectangles and Y-axis.
Practice for Computational Geometry ◾ 471
l1 l2 l3 l4
Figure 8.15 The plane is divided into three vertical strips by straight lines l1, l2,
l3, and l4.
Segments of discrete units are distances between two adjacent discrete points in the
ordered sequence of discrete points. For example, in Figure 8.14, the Y-axis for A is 1,
the Y-axis for B is 2, the Y-axis for C is 3, and the Y-axis for D is 4. After the discretiza-
tion, lengths for segment AB, BC, and CD are 1.
Sweep: First, the plane is divided into vertical strips, and each vertical strip is
one-dimensional. In Figure 8.15, the plane is divided into three vertical strips by
straight lines l1, l2, l3, and l4.
Each vertical strip’s section can be regarded as a little modification for two adja-
cent vertical strips’ sections. In Figure 8.16, the section for vertical strip 2 = the sec-
tion for vertical strip 1 + segment AB = the section for vertical strip 3 + segment CD.
l1 l2 l3 l4
Figure 8.16
472 ◾ Algorithm Design Practice for Collegiate Programming
[1, 4]
[1, 2] [2, 4]
[2, 3] [3, 4]
Segment tree: A segment tree is a rooted binary tree, where each vertex repre-
a +b
sents an interval [a, b]. For each vertex, if (b−a)>1, suppose c = , and roots
2
for its left subtree and right subtree represent intervals [a, c] and [c, b] respectively.
In Figure 8.17, interval [1, 4] can be divided into intervals [1, 2] and [2, 4]. And
interval [2, 4] can be divided into intervals [2, 3] and [3, 4].
Because vertical strips can be represented as segments, a segment tree can be
used to store vertical strips. Calculating the area for union of n rectangles can be
implemented by insertion and deletion in a segment tree.
(5, 6, 3)
(4, 4, 3)
4
(5.5, 4.5, 1)
0 4 8 x
Figure 8.18
Write a program that finds the area of coverage by a given collection of antenna
locations.
Input
The input contains multiple data sets, each representing a collection of antenna
locations. A data set is given in the following format.
n
x1 y1 r1
x2 y2 r2
…………
xn yn rn
The first integer n is the number of antennas, such that 2≤n≤100. The coordi-
nate of the i-th antenna is given by (xi, yi), and its power is ri. xi, yi and ri are frac-
tional numbers between 0 and 200 inclusive.
The end of the input is indicated by a data set with 0 as the value of n.
Output
For each data set, your program should output its sequence number (1 for the first
data set, 2 for the second, etc.) and the area of the coverage region. The area should
be printed with two digits to the right of the decimal point, after rounding it to
two decimal places.
The sequence number and the area should be printed on the same line with no
spaces at the beginning and end of the line. The two numbers should be separated
by a space.
474 ◾ Algorithm Design Practice for Collegiate Programming
3 1 52.00
4.0 4.0 3.0 2 36.00
5.0 6.0 3.0
5.5 4.5 1.0
2
3.0 3.0 3.0
1.5 1.5 1.0
0
Source: ACM Asia Regional Contest Tokyo 1998
IDs for Online Judges: ZOJ 1659, UVA 688
Analysis
Each antenna’s coverage is a square whose center is (xi, yi) and the length of its side
is 2×ri. The area of coverage by n antennas’ locations is the area for the union of n
corresponding squares. That is, the problem requires you to calculate the area for
the union of n corresponding squares.
The area for the union of n corresponding squares is calculated by sweeping in
the vertical direction. Discretization is on the Y-axis. The plane is divided into sev-
eral vertical strips by sweeping on the X-axis. A segment tree is used to accumulate
areas of vertical strips.
Program
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const double epsi = 1e-10;
const int maxn = 100 + 10;
struct Line { //coverage area
double x, y1, y2; // x-coordinate for the left or right,
y-coordinates for the above side and below sides,
1 x-coordinate for the left node
s=
−1 x-coordinate for the right node
Practice for Computational Geometry ◾ 475
int s;
Line(double _a=0, double _b=0, double _c=0, int _d=0):
x(_a),y1(_b),y2(_c),s(_d){ }
//construct a segment
bool operator <(const Line &op2) const { //Sorting in
ascending order for x-coordinates
return x < op2.x;
}
};
extern double ly[maxn << 1]; //ly[ ] stores y-coordinates
for the above side and below sides of a square covered by
antennas, capacity is 2maxn
class SegmentTree { // Segment tree
int cover; // the flag for an open interval
SegmentTree *child[2]; //left, right children pointers
if (child[0]) {
child[0]->die();
delete child[0];
child[1]->die();
delete child[1];
}
}
};
int cs(0); //initialize the number of test cases
int n, tot, ty; //n: number of antennas, tot: the length
of l[], ty: the length of ly[]
Line l[maxn << 1]; //l[] stores vertical strips
double ly[maxn << 1]; //ly[] stores y-coordinates
SegmentTree *seg_tr; //Pointer for the segment tree
int main() {
while (scanf("%d", &n), n) { // number of antennas
tot = ty = 0;
for (int i = 0; i < n; ++i) {
double x, y, r;
scanf("%lf%lf%lf", &x, &y, &r); //the i-th antenna
l[tot++] = Line(x - r, y - r, y + r, 1); //store strip
l[tot++] = Line(x + r, y - r, y + r, -1);
ly[ty++] = y-r, ly[ty++]=y + r;
//stores y-coordinates
}
sort(l, l + tot); //sort strips from left to right
sort(ly, ly + ty); // sort y-coordinates top-down
ty = unique(ly, ly + ty) - ly; //eliminate duplicate
double ans = 0; //initialize the area of the coverage
region
seg_tr = new SegmentTree();
seg_tr->setup(0, ty - 1); //set up a segment for
interval [0, ty-1]
for (int i = 0, j; i < tot; i = j) { // Enumerate
strips in l[]
if (i) ans += seg_tr->len * (l[i].x-l[i-1].x);
//accumulate area of the coverage region
j = i; //Enumerate strips, [l, r, k] is inserted
into the segment tree
while (j < tot && fabs(l[i].x - l[j].x) <= epsi) {
seg_tr->paint(lower_bound(ly,ly+ty,l[j].y1)-
ly,lower_bound(ly,ly+ty,l[j].y2) -ly,l[j].s);
++j;
}
}
seg_tr->die(); delete seg_tr; //delete a segment
printf("%d %.2lf\n", ++cs, ans); // the area of the
coverage region
}
return 0;
}
Practice for Computational Geometry ◾ 477
8.2.2.1 Atlantis
There are several ancient Greek texts that contain descriptions of the fabled island
Atlantis. Some of these texts even include maps of parts of the island. But unfor-
tunately, these maps describe different regions of Atlantis. Your friend Bill has to
know the total area for which maps exist. You (unwisely) volunteered to write a
program that calculates this quantity.
Input
The input consists of several test cases. Each test case starts with a line con-
taining a single integer n (1≤n≤100) of available maps. The n following lines
describe one map each. Each of these lines contains four numbers x1; y1; x 2; y2
(0≤x1<x 2≤100000; 0≤y1<y2≤100000), not necessarily integers. The values (x1; y1)
and (x 2; y2) are the coordinates of the top-left and bottom-right corners of the
mapped area, respectively.
The input file is terminated by a line containing a single 0. Don’t process it.
Output
For each test case, your program should output one section. The first line of each sec-
tion must be “Test case #k”, where k is the number of the test case (starting with 1).
The second one must be “Total explored area: a”, where a is the total explored area
(i.e., the area of the union of all rectangles in this test case), printed exact to two
digits to the right of the decimal point.
Output a blank line after each test case.
478 ◾ Algorithm Design Practice for Collegiate Programming
2 Test case #1
10 10 20 20 Total explored area: 180.00
15 15 25 25.5
0
Source: ACM Mid-Central European Regional Contest 2000
IDs for Online Judges: POJ 1151, ZOJ 1128, UVA 2184
Analysis
An available map in the problem is represented as a rectangle. The total explored
area is the area for the union of these rectangles.
The plane is divided into several rectangles (Figure 8.19). Areas of these rect-
angles are calculated respectively. The sum of areas is the total explored area (the
area of the union of all rectangles). This is shown in Figure 8.20.
The algorithm is as follows:
For each map, its left boundary’s x-coordinate and right boundary’s x-coordinate
are stored in a sequence q in ascending order.
For each map, its bottom edge’s y-coordinate, top edge’s y-coordinate, and
x-coordinates for endpoints of edges are stored in a sequence f. The flag for bottom
edges is 1, and the flag for top edges is −1. And f is sorted in ascending order of
y-coordinates, to make f store horizontal strips from bottom to top.
Then, each horizontal strip is taken out from f and the segment [xl, xr]
(x-coordinates for endpoints of the edge) is inserted into the segment tree. There
are two fields for vertices for the segment tree:
len, the length of the union of intervals;
mark: the mark of the union of intervals;
When a horizontal strip is added, the area covered by a horizontal strip is accu-
mulated into the total explored area.
Figure 8.19
Practice for Computational Geometry ◾ 479
Figure 8.20
Program
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn = 500; //The upper limit of the number of
maps*2
struct node {
double x; //y-coordinate for horizontal strip
int l, r, t; //l, r: x-coordinates for two points in q, t:
the flag for bottom edge and top edge
} f[maxn]; // horizontal strips
int n; // the number of maps
double q[maxn], x1[maxn], yy1[maxn], x2[maxn], yy2[maxn];
//q stores sorted x- coordinates, for the i-th map, the
coordinate for the top left corner (x1[i],yy1[i]), the
coordinate for the lower right corner (x2[i],yy2[i])
struct segment {
int mark;
double len; //the length of the union for intervals
} tree[maxn * 20]; //segment tree
int cmp(node a, node b) { //Comparison function for f[]
return a.x < b.x;
}
int insert(const int k,const int l,const int r,const int
lc,const int rc,const int t) { //horizontal strip[l, r]
is inserted into segment tree (k:root, interval [lc, rc]),
t: mark for bottom edge and top edge
if (lc<=l && r<=rc) { //[lc, rc] covers [l, r]
tree[k].mark += t;
} else {
if ((l+r)/2>=lc)insert(k*2,l,(l+r)/2, lc,rc,t);
480 ◾ Algorithm Design Practice for Collegiate Programming
L5 L1
ax + by + c > 0 L2
ax + by + c > 0 L4
L3
(a) (b) (c)
Figure 8.21
y–c≤0
x+c≥0 x–c≤0
y+c≥0
Figure 8.22
482 ◾ Algorithm Design Practice for Collegiate Programming
Bu
e3
A Au e
1
Bl e4
e2 Inner side e1
e3 Inner side
B Al
(a) (b)
Figure 8.23
[Figure 8.23(b)]. Suppose there is a vertical sweep line sweeping from left to right.
At any time, there are at most four points of intersection of the sweep line and the
two convex polygons. For example, in Figure 8.23(a), the upper point and lower
point of intersection of the sweep line and convex polygon A are Au and Al respec-
tively; and the upper point and lower point of intersection of the sweep line and
convex polygon A are Bu and Bl respectively. Obviously, the points of intersection
of the sweep line and the intersection of two convex polygons are Au and Bl. Sides
containing Au, Al, Bu, and Bl are e1, e2, e3, and e4, respectively.
In this section, there are two kinds of experiments for the intersection of
half-planes:
a[i] a[i + 1]
p2 p2 p2
p1 p1 p1
a[i] a[i – 1] a[i]
Figure 8.24
The time complexity using a cutting line to divide the plane A to generate a
half-plane is O(n). The intersection of n half-planes can be calculated by using the
following method n times.
Suppose the plane A is a square whose points’ coordinates are (−103, −103),
(10 , −103), (103, 103) and (−103, 103), and the four points are stored in a[]. The
3
cutting line for H1 is used to divide A to generate a convex polygon whose points
are stored in b[], b[] is assigned to a[], and b[] is cleared out. Then the cutting line
for H2 is used to divide A to generate a new convex polygon whose points are stored
in b[], ......, and so on. After the cutting line for Hn is used to divide A to generate
a convex polygon, its points are stored in b[]. The time complexity is O(n2). This
algorithm is called the On-Line Algorithm for Intersection of Half-Planes.
Figure 8.25
polygon. But he still wants to minimize the uncovered area by selecting the best
placing for his carpets, and he asks you to help.
You need to place two carpets in the room so that the total area covered by both
carpets is the maximum possible. The carpets may overlap, but they may not be cut
or folded (including cutting or folding along the floor border)—feng shui tells you
to avoid straight lines. See Figure 8.25.
Input
The first line of the input file contains two integer numbers n and r—the number
of corners in George’s room (3≤n≤100) and the radius of the carpets (1≤r≤1000,
both carpets have the same radius). The following n lines contain two integers xi
and yi each—coordinates of the i-th corner (−1000≤xi,yi≤1000). Coordinates of all
corners are different, and adjacent walls of the room are not colinear. The corners
are listed in clockwise order.
Output
Write four numbers x1, y1, x 2, y2 to the output file, where (x1, y1) and (x 2, y2) denote
the spots where carpet centers should be placed. Coordinates must be precise up to
four digits after the decimal point.
If there are multiple optimal placements available, return any of them. The
input data guarantees that at least one solution exists.
5 2 −2 3 3 2.5
−2 0
−5 3
0 8
7 3
5 0
4 3 3 5 7 3
0 0
Practice for Computational Geometry ◾ 485
0 8
10 8
10 0
Source: ACM Northeastern Europe 2006, Northern Subregion
ID for Online Judge: POJ 3384
Analysis
Two circles are placed in a convex polygon so that the total area covered by the two
circles is the maximum possible. The idea for solving this problem is to push sides
for the convex polygon inward, and a new convex polygon is generated. Obviously,
the two circles can be placed in the convex polygon, but they may not be cut or
folded. The on-line algorithm for the intersection of half-planes is used to solve the
problem.
Initially, the covered area plan is an infinitely
great
square. Then each side pi pi +1
is enumerated anticlockwise, 0≤i≤n−1, pn=p0. pi pi +1 is pushed r inward, and the
r
side qi qi +1 is a side for the new convex polygon ( pi pi +1 is rotated 90° × , and
pi pi +1
qi qi +1 is generated). qi qi +1 is used to divide plan. Repeat the step until n sides are
dealt with. Finally, plan is the new convex polygon.
Then distances between all pairs of points for the convex polygon are enumer-
ated. Suppose the distance between a pair of points q1 and q2 is the longest. Points
q1 and q2 are the spots where carpet centers should be placed. Obviouly, the total
area covered by the two circles is maximal.
Program
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <ctime>
#include <climits>
#include <utility>
486 ◾ Algorithm Design Practice for Collegiate Programming
#include <algorithm>
using namespace std;
const double epsi = 1e-10; // infinitesimal
const double pi = acos(-1.0); //180°
const int maxn = 100 + 10; //the upper limit of the number
of points
inline int sign(const double &x) { // x is positive,
negative, or zero
if (x > epsi) return 1;
if (x < -epsi) return -1;
return 0;
}
inline double sqr(const double &x) { //x2
return x * x;
}
struct Point { //Structure for points
double x, y;
Point(double _x = 0, double _y = 0): x(_x), y(_y) { }
Point operator +(const Point &op2) const {
return Point(x + op2.x, y + op2.y);
}
Point operator -(const Point &op2) const {
return Point(x - op2.x, y - op2.y);
}
double operator *(const Point &op2) const { //Dot Product
return x* op2.x + y*op2.y;
}
Point operator *(const double &d) const {
return Point(x * d, y * d);
}
Point operator /(const double &d) const {
return Point(x / d, y / d);
}
double operator ^(const Point &op2) const { // vector
product
return x * op2.y - y * op2.x;
}
bool operator ==(const Point &op2) const { //coincidence
or not
return sign(x - op2.x) == 0 && sign(y - op2.y) == 0;
}
};
inline double mul(const Point &p0, const
Point &p1,
const
Point &p2) // vector product for p1 p0 and p2 p0
{
return (p1 - p0) ^ (p2 - p0);
}
inline double dot(const Point &p0, const
Point
&p1, const
Point &p2) // Dot Product for p1 p0 and p2 p0
Practice for Computational Geometry ◾ 487
{
return (p1 - p0) * (p2 - p0);
} 2
inline double dis2(const Point &p0, const Point &p1) { // p1 p0
return sqr(p0.x - p1.x) + sqr(p0.y - p1.y);
}
inline
double dis(const Point &p0, const Point &p1) {
// p1 p0
return sqrt(dis2(p0, p1));
}
inline double dis(const Point &p0, const Point &p1, const
Point &p2) {
if(sign(dot(p1, p0, p2))<0)
return
dis(p0, p1); // if the
°
included angle
for p 1 p 0 and p 1 p 2 is larger than 90 , then
return p1 p0
if (sign(dot(p2,p0, p1))<0)
return
dis(p0, p2); // if the
°
included angle
for p 2 p0 and p 2 p1 is larger than 90 , then
return p2 p0
return fabs(mul(p0, p1, p2) / dis(p1, p2)); //the length
of the vertical line from p0 to p1 p2
}
inline Point rotate(const Point &p, const double &ang) {
//return the point that point p is rotated degree ang
return Point(p.x * cos(ang) - p.y * sin(ang), p.x *
sin(ang) + p.y * cos(ang));
}
inline void translation(const Point &p1, const Point &p2,
const double &d, Point &q1, Point &q2)
{ // p2 p1 is pushed d inward and q 2q 1 is formed
q1 = p1 + rotate(p2 - p1, pi / 2) * d / dis(p1, p2);
q2 = q1 + p2 - p1;
}
inline void cross(const Point &p1, const Point &p2, const
Point &p3, const Point &p4, Point &q)
{ //the intersection point q for p1 p2 and p3p4
double s1 = mul(p1, p3, p4), s2 = mul(p2, p3, p4);
q.x = (s1 * p2.x - s2 * p1.x) / (s1 - s2);
q.y = (s1 * p2.y - s2 * p1.y) / (s1 - s2);
}
inline int half_plane_cross(Point*a, int n,Point *b, const
Point &p1, const Point &p2) { // points for A are listed
anticlockwise in a[], the current cutting line is p1 p2, and
points are listed anticlockwise in b[] after A is divided
by p1 p2 .
int newn = 0;
for (int i = 0, j; i < n; ++i) {
if (sign(mul(a[i], p1, p2)) >= 0) { // a[i] is added
into b[]
b[newn++] = a[i];
488 ◾ Algorithm Design Practice for Collegiate Programming
continue;
}
j = i-1; if (j == -1) j = n-1; //point j is the left
adjacent point for point i
if (sign(mul(a[j], p1, p2))>0) //the intersection
point for p1 p2 and a[j]a[i] is added into b[]
cross(p1, p2, a[j], a[i], b[newn++]);
j = i + 1; if (j == n) j = 0; // point j is the right
adjacent point for point i
if (sign(mul(a[j],
p1,
p2)) > 0) // the intersection
point for p1 p2 and a[j]a[i] is added into b[]
cross(p1, p2, a[j], a[i], b[newn++]);
}
return newn;
}
int n; // number of points
double r; //radius
Point p[maxn]; //the sequence of points for a convex
polygon
int t[2];
Point plane[2][maxn], q1, q2;
int main() {
scanf("%d%lf", &n, &r); // the number of corners and the
radius of the carpets
for (int i = 0; i < n; ++i) // coordinates of corners
scanf("%lf%lf", &p[i].x, &p[i].y);
p[n] = p[0];
int o1 = 0, o2;
t[0] = 4; //Initially the covered area plan is a square
initial
t[0] = 4;
plane[0][0] = Point(-1e3, -1e3);
plane[0][1] = Point(1e3, -1e3);
plane[0][2] = Point(1e3, 1e3);
plane[0][3] = Point(-1e3, 1e3);
for (int i = 0; i < n; ++i) {
o2 = o1 ^ 1;
translation(p[i + 1], p[i], r, q1, q2); // pi pi+1 is
pushed r inward and forms q 2q 1
t[o2] = half_plane_cross(plane[o1], t[o1], plane[o2],
q1, q2);
o1 = o2;
}
double maxd = -1, curd;
for (int i=0; i<t[o1];++i) //distances between all pairs
of points for the convex polygon are enumerated, the distance
between a pair of points q1 and q2 is the longest
for (int j = i; j < t[o1]; ++j) {
curd = dis2(plane[o1][i], plane[o1][j]);
if (sign(curd - maxd) > 0) {
Practice for Computational Geometry ◾ 489
maxd = curd;
q1 = plane[o1][i], q2 = plane[o1][j];
}
}
printf("%.10lf %.10lf %.10lf %.10lf\n", q1.x, q1.y, q2.x,
q2.y); //q1 and q2 are the spots where carpet centers
return 0;
}
Figure 8.26
1π 3π
4 c 4
c –3π c –1π c
4 4
Figure 8.27
490 ◾ Algorithm Design Practice for Collegiate Programming
For the half-plane ax+by≤(≥)c, where a, b, and c are constants, its polar angle
is atan2(b, a). If there are several half-planes whose polar angles are the same, one
half-plane is selected based on c. For example, in Figure 8.27(e), the plane whose c
is the least is selected.
The insection of half-planes is a convex polygon, where lines whose polar angles
1 1
are in − π, π constitute the upper convex hull, and lines whose polar angles
2 2
1 1
are in −π, − π ∪ π, π constitute the lower convex hull (Figure 8.28).
2 2
We can calculate a convex polygon in ascending order of polar angles (i.e.,
counterclockwise). The algorithm is as follows:
Suppose array a stores boundaries (Ai, Bi, and Ci for Ai x+Bi y+Ci =0, 1≤i≤n) for
n half-planes H1, H2, ……, Hn. The convex polygon for the intersection of n half-
planes H1∩H2∩…∩Hn is stored by b[ ] and c[ ], where b[ ] is a deque that stores
straight line equations for boundaries, c[ ] stores vertices, and h and t are the front
and rear for the deque b[ ] respectively.
Step 1: Pretreatment for a[]: Sort a[] using polars as the first key, and distances
from the origin to boundaries as the second key. If there are more than
one boundary with the same polar angle, the boundary with the shortest
distance from the origin to the boundary is selected. If Ai =Bi =0, and if Ci >0,
the line Ai x+Bi y+Ci =0 is removed; and if Ci≤0, the program exits.
Step 1: Step 1 is to determine the sequence for intersections of half-planes, and
eliminate cases that intersections of half-planes don’t exist and coincide.
Step 2: The first two boundaries are added into queue b[ ] as b[0] and b[1], and
the insection point for the two boundaries is stored into c[1], h=0, and t=1.
Step 3: Boundaries a[3]…a[n] (half-planes) are dealt with one by one:
1. While the deque isn’t empty, and when c[t] is substituted in boundary a[i],
the equation is negative; then the rear for the deque is removed (t −−);
2. While the deque isn’t empty, and when c[h+1] is substituted in bound-
ary a[i], the equation is negative; then the front for the deque is removed
(h++);
Figure 8.28
Practice for Computational Geometry ◾ 491
3. Boundary a[i] is added into deque b[] (b[++t]=a[i]), and the insection
point for b[t] and b[t−1] is put into c[t]. It is to guarantee Ai x+Biy+Ci≥0
when insection points in c[] are substituted in each line.
Step 4: The front and the rear for queues b[] and c[] are joined. Redundant half-
planes are removed.
1. While the deque isn’t empty, and when c[t] is substituted in boundary
b[h], the equation is negative, and the rear for the deque is removed (t −−);
2. While the deque isn’t empty, and when c[h+1] is substituted in boundary
b[t], the equation is negative, and the front for the queue is removed from
the queue (h++);
3. If the deque is empty (h+1≥t), then the program exits; else for the convex
polygon, p0 is the insection point for b[h] and b[t], and insection points
p1 … pi −h are c[h+1]…c[t], and pi −h+1 = p0.
Input
The number of tasks T that your program needs to solve will be on the first row of
the input file. Input data for each task start with an integer N, 5≤N≤1500. Each
of the next N rows of the input will contain the coordinates of a vertex of the
polygon—two integers that fit in 16-bit integer type, separated by a single space.
Figure 8.29
492 ◾ Algorithm Design Practice for Collegiate Programming
Following the row with the coordinates of the last vertex for the task comes the line
with the number of vertices for the next test, and so on.
Output
For each test, you must write on one line the required surface—a number with
exactly two digits after the decimal point (the number should be rounded to the
second digit after the decimal point).
1 80.00
7
0 0
4 4
4 7
9 7
13 -1
8 -6
4 -4
Source: ACM Southeastern Europe 2002
IDs for Online Judges: POJ 1279, ZOJ 1369, UVA 2512
Analysis
Based on the problem description “for a given gallery, to write a program which
finds the surface of the area of the floor, from which each point on the walls of the
gallery is visible”, the surface of the area of the floor consists of a set of points with
the following property:
Suppose s is a point on the boundary of the gallery, and v is a point in the set. A
line segment connecting s and v must be in the gallery.
The gallery is a polygon. And the surface of the area of the floor is the insec-
tion of left half-planes divided by sides for the polygon. If the polygon is a convex
polygon, the surface of the area of the floor is the polygon itself. And if the polygon
isn’t a convex polygon, the surface of the area of the floor is a subset for the polygon,
and may be an empty set.
Practice for Computational Geometry ◾ 493
Program
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn=2100;
const double eps=1e-10;
struct Point { //Structure for points
double x, y;
Point(double _x = 0, double _y = 0): x(_x), y(_y) { }
//point
double operator ^(const Point &op2) const { //cross product
return x * op2.y - y * op2.x;
}
};
struct StraightLine{ //Intersection of half-planes
double A, B, C; //equation of line Ax+By+C=0
StraightLine(double _a=0, double _b=0, double _c=0):A(_a),
B(_b), C(_c) { } //line
Input
Input consists of up to 50 lines, each containing an x, y coordinate pair followed
by “Hotter”, “Colder”, or “Same”. Each pair represents a position within the room,
which may be assumed to be a square with opposite corners at (0,0) and (10,10).
Output
For each line of input, print a line giving the total area of the region in which the
object may have been placed, to two decimal places. If there is no such region,
output 0.00.
Analysis
Suppose the position of the placed object is P, and player A moves into D(x 2, y2)
from C(x1, y1). The equation for the perpendicular bisector for the line segment CD
is substituted by P(x, y).
In the current round, if player B announces “Hotter”, then for the position of
P(x, y) |CP|>|DP| holds, that is,
if player B announces “Colder”, then for the position of P(x, y), |CP|<|DP|
holds, that is,
if player B announces “Same”, then for the position of P(x, y), |CP|=|DP| holds,
that is,
2 × ( x 2 − x1 ) × x + 2 × ( y 2 − y1 ) × y + x12 + y12 − x 22 − y 22 = 0.
Program
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn=21000;
const double eps=1e-10;
struct Point { //structure for points
double x, y;
Point(double _x = 0, double _y = 0): x(_x), y(_y) { }
double operator ^(const Point &op2) const { //cross
product
return x * op2.y - y * op2.x;
}
};
struct StraightLine{ // the intersection of half-planes
double A, B, C; //equation of line Ax+By+C
StraightLine(double _a=0, double _b=0, double _c=0): A(_a),
B(_b), C(_c) { }//construct equation of line
double f(const Point &p) const { // the equation of line
is substituted by point p
return A * p.x + B * p.y + C;
}
498 ◾ Algorithm Design Practice for Collegiate Programming
double rang() const{ //return the polar angle for the line
return atan2(B, A);
}
double d() const{ //the distance from origin to line
Ax+By+C=0
return C / (sqrt(A * A + B * B));
}
Point cross(const StraightLine &a) const { // intersection
point
double xx = - (C * a.B - a.C * B) / (A * a.B - B * a.A);
double yy = - (C * a.A - a.C * A) / (B * a.A - a.B * A );
return Point(xx, yy);
}
};
StraightLine b[maxn], SL[maxn],S[maxn]; // SL[]: the
sequence of lines for half-planes, S[]: stores half-planes,
b[]: the sequence of lines for the current intersection of
half-planes
Point c[maxn], d[maxn]; // d[]: the sequence of points for
the intersection of half-planes, c[]: the sequence of points
for the current intersection of half-planes
int n; //number of points for a polygon
inline int sign(const double &x){ //x is positive or
negative
if (x > eps) return 1;
if (x < -eps) return -1;
return 0;
}
int cmp(StraightLine a, StraightLine b){ //comparing lines
a and b, polar angles are as the first key, distances from the
origin to lines are as the second key
if (sign( a.rang() - b.rang() ) != 0) return a.rang()
< b.rang();
else return a.d() < b.d();
}
int half_plane_cross(StraightLine *a, int n, Point *pt) {
//input a sequence of lines for a polygon a, whose length
is n. By polar angles, return a sequence of lines pt and its
length for the inner convex polygon a
sort(a+1,a+n+1,cmp); // a is sorted, where polar angles
are as the first key, distances from the origin to lines are
as the second key
int tn = 1; //initialize the length of a
for (int i = 2; i <= n; i ++){ //enumerating adjacent
sides for the polygon, sides whose polar angles are same, or
A=B=0 and C>0, are deleted (C≤0, exit)
if (sign( a[i].rang() - a[i-1].rang() )!=0) a[++tn]=a[i];
// polar angles for adjacent sides are different
if (sign(a[tn].A)==0 && sign(a[tn].B)==0) // A=B=0
if (sign( a[tn].C )==1) tn --;
Practice for Computational Geometry ◾ 499
else return - 1;
}
n=tn; //the length for a
int h = 0 , t = 1;
b[0] = a[1]; //line 1 and line 2 are stored in b[]
b[1] = a[2];
c[1] = b[1].cross(b[0]); //the intersection point for
line 1 and line 2 is stored in c[]
for (int i = 3; i <= n; i ++){ //enumerate line 3…line n
while (h < t && sign( a[i].f( c[t] ) )<0) t -- ;
while (h<t && sign( a[i].f(c[h+1] ))<0) h++ ;
b[ ++ t] = a[i]; //line i is added into the rear for b
c[t] = b[t].cross( b[t-1] ); //the intersection for the
two lines at the rear of b is added into c
}
while (h < t && sign( b[h].f( c[t] ) )<0) t --;
while (h < t && sign( b[t].f( c[h+1] ) )<0) h ++;
if (h+1 >= t) return -1; //the queue is empty
pt[0] = b[h].cross( b[t] ); //the first point for the
convex polygon
for(int i=h;i<t;i++) pt[i-h+1]=c[i+1];
pt[t - h + 1] = pt[0];
return t - h + 1; //number of points for the convex
polygon
}
int main(){
ios::sync_with_stdio(false);
double x1, x2, y2, y1, ans=0;
int n, m; //n: number of half-planes, m: number of points
for the intersection of half-planes
n=0; //initially 4 half-planes for [0, 10]*[0, 10]
SL[++n] = StraightLine(0, 1, 0);
SL[++n] = StraightLine(1, 0, 0);
SL[++n] = StraightLine(0, -1, 10);
SL[++n] = StraightLine(-1, 0, 10);
double px=0,py=0,nx, ny; //position for before moving
(px,py) and after moving (nx,ny)
string c; // player B announces
char s;
while (cin >> nx >> ny){ // a position where play A enters
cin >> c ; // player B announces
if (c[0] == 'C' ) //a corresponding plane is added based
on player B announces
SL[++n]=StraightLine(-2*(nx-px),-2*(ny-py),-(px*px+py*py-
nx*nx-ny*ny));
else if (c[0]=='H' )
SL[++n]=StraightLine(2*(nx-px), 2*(ny-py) ,(px*px+py*py-
nx*nx -ny*ny));
else SL[++n]=StraightLine(-2*(nx-px),-2*(ny-py),-
(px*px+py*py-nx* nx-ny*ny)),
500 ◾ Algorithm Design Practice for Collegiate Programming
SL[++n]=StraightLine(2*(nx-px),2*(ny-py),(px*px+py*py-nx
*nx-ny*ny));
px = nx ; py = ny ; //(nx, ny) will be the next
position where player A enters
ans=0; //initialize the area for the intersection of
half-planes
for (int i = 1 ; i <= n ; i ++) S[i] = SL[i];
m = half_plane_cross(S, n, d); //intersection of
half-planes
if (m==-1) printf("0.00\n"); //the intersection doesn't
exist
else {
for (int i = 0; i < m; i ++) ans += d[i] ^ d[i+1];
printf("%.2lf\n", ans / 2);
}
}
return 0;
}
1. Convex hull: Finding the smallest convex hull containing all given points.
2. Finding the farthest pair of points in a convex hull.
p10
p11 p p7 p6
9 p5
p8
p12 p3
p4
p2
p1
p0
Figure 8.30
Practice for Computational Geometry ◾ 501
1. First, the point in Q with the minimum y-coordinate is selected. If there are
more than one point with the minimum y-coordinate, the leftmost point is
selected. The selected point is denoted as p0, and p0 is as the first vertice for
the convex hull CH(Q).
2. Second, other points in Q are sorted by polar angle in counterclockwise order.
By calculating the cross product (pi−p0)^(pj−p0) (i.e., Mul(pi, pj, p0)), we can
determine whose polar angle is larger.
If (pi−p0)^(pj−p0)>0, then the polar angle for pj is larger than the polar angle
for pi, with respect to p0; and pi is scanned before pj.
If (pi−p0)^(pj−p0)<0, then the polar angle for pj is less than the polar angle for
pi, with respect to p0; and pj is scanned before pi.
If (pi−p0)^(pj−p0)==0, then the polar angle for pj is the same as the polar angle
for pi, with respect to p0. The point which is farther from p0 is scanned.
And the other points are removed.
Suppose pointers are sorted as a sequence { p1 , …., pn−1 }. If n≤2, the convex hull
is empty; else the sequence { p1 , …., pn−1 } is scanned.
A stack S is used to store candidate vertices in computing the convex hull.
Initially, points p0, p1, and p2 are pushed into stack S one by one. Then points
{ p3 , …., pn −1 } are scanned one by one. Suppose pi is the current scanned point,
and ptop is the point at the top of the stack S. Because vertices are traversed counter-
clockwise, if ptop is a vertice of the convex hull CH(Q), a left turn should be made
from ptop to pi. If it is a nonleft turn, ptop isn’t a vertice of the convex hull CH(Q),
and should be popped from S. After vertices making nonleft turns are popped, pi is
pushed into S. Then the next point pi+1 is scanned. Finally, points in S are vertices of
the convex hull CH(Q). The sequence from the bottom to the top in S are vertices
of the convex hull CH(Q) in counterclockwise order.
By calculating the vector product ( pi − ptop −1 ) ^ ( ptop − ptop −1 ) (i.e., Mul(pi, ptop,
ptop−1)), where ptop−1 is the point next to the top of S. If ( pi − ptop −1 ) ^ ( ptop − ptop −1 ) ≥ 0,
ptop makes a nonleft turn.
8.4.1.1 Wall
Once upon a time there was a greedy king who ordered his chief architect to build a
wall around the king’s castle. The king was so greedy that he would not listen to his
architect’s proposals to build a beautiful brick wall with a perfect shape and nice tall
towers. Instead, he ordered the architect to build the wall around the whole castle
using the least amount of stone and labor, but demanded that the wall should not
come closer to the castle than a certain distance, as shown in Figure 8.31. If the
502 ◾ Algorithm Design Practice for Collegiate Programming
Figure 8.31
king finds that the architect has used more resources to build the wall than was
absolutely necessary to satisfy those requirements, then the architect will lose his
head. Moreover, he demanded that the architect introduce at once a plan of the wall
listing the exact amount of resources that are needed to build the wall.
Your task is to help the poor architect to save his head, by writing a program
that will find the minimum possible length of the wall that he could build around
the castle to satisfy the king’s requirements.
The task is somewhat simplified by the fact that the king’s castle has a polyg-
onal shape and is situated on flat ground. The architect has already established
a Cartesian coordinate system and has precisely measured the coordinates of all
castle’s vertices in feet.
Input
The first line of the input file contains two integer numbers N and L separated
by a space. N (3≤N≤1000) is the number of vertices in the king’s castle, and
L (1≤L≤1000) is the minimal number of feet that the king allows for the wall to
come close to the castle.
The next N lines describe the coordinates of the castle’s vertices in a clock-
wise order. Each line contains two integer numbers Xi and Yi separated by a
space (−10000≤Xi,Yi≤10000) that represents the coordinates of the i-th vertex.
All vertices are different, and the sides of the castle do not intersect anywhere
except for vertices.
Output
Write to the output file the single number that represents the minimal possible
length of the wall in feet that could be built around the castle to satisfy the king’s
Practice for Computational Geometry ◾ 503
requirements. You must present the integer number of feet to the king, because the
floating numbers are not invented yet. However, you must round the result in such
a way that it is accurate to 8 inches (1 foot is equal to 12 inches), since the king will
not tolerate any larger error in the estimates.
9 100 1628
200 400
300 400
300 300
400 300
400 400
500 400
500 200
350 200
200 200
Source: ACM Northeastern Europe 2001
IDs for Online Judges: POJ 1113, ZOJ 1465, UVA 2453
Analysis
The shape for the king’s castle is a polygon. The architect is required to build a wall
around the king’s castle. And the minimum number of feet that the king allows for
the wall to come close to the castle is L.
First, a convex hull is computed by Graham’s scan. The inputs for the algo-
rithm are the castle’s vertices. The built wall is a polygon with rounded corners
around the convex hull. Edges for the polygon are parallel to the edges of the
convex hull. Lengths of two parallel edges are the same. And the distance for two
parallel edges is L. For the wall, each round corner is an arc connecting two adja-
cent edges, whose radius is L, and the center of the circle is a vertex for the convex
hull. For a round corner, the sum of the radius angle and its corresponding interior
angle for the convex hull is 180°. Because the sum of degrees of interior angles in
a convex polygon with n edges is (n−2)×180°, the sum of degrees of radius angles is
360°. Therefore, the sum of the lengths of arcs is the circumference of a circle whose
radius is L.
The minimal possible length of the wall is the girth of the convex hull + the
circumference of a circle whose radius is L.
504 ◾ Algorithm Design Practice for Collegiate Programming
Program
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const double epsi = 1e-8; //infinitesimal
const double pi = acos(-1.0); //Radian value for π
const int maxn = 1000 + 10;
struct Point { //Calculation for point
double x, y; // coordinate
Point(double _x = 0, double _y = 0): x(_x), y(_y) { }
double operator ^(const Point &op2) const { // vector
product for two point vectors
return x * op2.y - y * op2.x;
}
};
inline int sign(const double &x) {
if (x > epsi) return 1;
if (x < -epsi) return -1;
return 0;
}
inline double sqr(const double &x) { //calculate x2
return x * x;
}
inline double mul(const Point &p0, const Point &p1,const Point
&p2){// vector product for p0 p1 and p0 p2
return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);
//(p1 - p0) ^ (p2 - p0);
}
inline double dis2(const Point &p0, const Point &p1) {
2
// p0 p1
return sqr(p0.x - p1.x) + sqr(p0.y - p1.y);
}
inline
double dis(const Point &p0, const Point &p1) {
// p0 p1
return sqrt(dis2(p0, p1));
}
int n, l; //n: the number of vertices in the king's castle,
l: the minimal number of feet that king allows for the wall to
come close to the castle
Point p[maxn], convex_hull_p0; // p[]: a sequence for
vertices for the polygon, convex_hull_p0: the point with the
minimum y-coordinate
inline bool convex_hull_cmp(const Point &a, const Point &b) {
Practice for Computational Geometry ◾ 505
pj
j
pi+2 pj+1
pj+2
pi+1
i
pi
Figure 8.32
pair of points must be two vertices for the convex hull. The distance between the
farthest pair of vertices for a convex hull is called the diameter of a convex hull.
For a convex hull, each pair of vertices can be enumerated to find the farthest
pair of vertices. The method of rotating calipers is the optimal algorithm for finding
the farthest pair of vertices of the convex hull.
Suppose P is a convex polygon with n vertices, and L is a line. If L intersects P,
and the interior of P lies completely on one side of L, L is a line of support for P. It
is shown in Figure 8.32. If L intersects P at a vertex v, or an edge e; v or e admits L.
A pair of vertices pi, pj∈P is an antipodal pair if it admits parallel lines of support
for P. In Figure 8.32, an antipodal pair admits parallel lines of support. Lines of
support can be rotated to generate the next antipodal pair. Suppose angles that the
lines of support at pi and pj make with edges pi pi+1 and pj pj+1 are θi and θj respectively.
If θj<θi, and the lines of supports are rotated by angle θj, then pj+1 and pi become
the next antipodal pair. If θj=θi, then three new antipodal pairs are generated.
Therefore, there are three cases that lines of support interest P, shown in Figure 8.33,
Figure 8.34, and Figure 8.35, respectively. In the case shown in Figure 8.33, there is
Figure 8.33
Practice for Computational Geometry ◾ 507
Figure 8.34
an antipodal pair; in the case shown in Figure 8.34, there are two antipodal pairs;
and in the case shown in Figure 8.35, there are four antipodal pairs.
The diameter of a convex polygon P is the greatest distance between parallel lines
of support of P. The diameter of a convex polygon P is the greatest distance between
an antipodal pair of P. Therefore we need to check each antipodal pair. Initially
qa is the vertices for P with the minimum y-coordinate, and qb is the vertices for P
with with the maximum y-coordinate. Obviously, qa and qb are an antipodal pair.
Suppose dab is the distance between qa and qb; Ca is the circle of radius dab centered at
qa, and Cb is the circle of radius dab centered at qb; La is the tangent to Ca at qa, and Lb
is the tangent to Cb at qb; L is the line through qa and qb. By the definition of tangent
line, La ⊥L and Lb⊥L. Therefore, La and Lb are lines of support of P. La and Lb rotate
to generate new antipodal pairs. The process that La and Lb rotate is continued until
we come full circle to the starting position. Suppose qa and qb are the farthest pair of
points. La and Lb are parallel lines of support that intersect qa and qb respectively. La
and Lb can be rotated to generate each antipodal pair. This is shown in Figure 8.36.
For a convex polygon, suppose u[0] is the lowest point, and if there are more
than one lowest point, u[0] is the rightmost point for the lowest points; and u[2] is
the highest point, and if there are more than one highest point, u[0] is the leftmost
point for the highest points. Obviously u[0] and u[2] is an antipodal pair. The
algorithm calculating the distance for the farthest pair of points ret is as follows:
Calculate the sequence of vertices for convex hull;
Calculate u[0] and u[2], and initialize ret as pu[0]pu[2] ;
Rotation degree sumang=0;
Figure 8.35
508 ◾ Algorithm Design Practice for Collegiate Programming
qb
Lb
L Ca
p
P
qa Cb
La
Figure 8.36
while (sumang≤2π) {
calculate the current rotation degree curang to generate a
new antipodal pair u[0] and u[2];
sumang+=curang; //accumulation
ret=max(ret, pu[0]pu[2] ); //adjust the distance for the
farthest pair of points ret
}
Output the distance for the farthest pair of points ret;
Input
Line 1: A single integer, N;
Line 2: N+1: Two space-separated integers x and y specifying the coordinate of each
farm.
Practice for Computational Geometry ◾ 509
Output
Line 1: A single integer that is the squared distance between the pair of farms that
are farthest apart from each other.
4 2
0 0
0 1
1 1
1 0
Source: USACO 2003 Fall
ID for Online Judge: POJ 2187
Farm 1 (0, 0) and farm 3 (1, 1) have the longest distance (square root of 2).
Analysis
In this problem, there are N (2≤N≤50,000) points. The problem requires you to
compute the maximum distance among all pairs of points. Obviously, the pair of
points with the maximum distance must be two points for the convex hull. First,
the convex hull of the set of N points is computed. Then the maximum distance
among all pairs of points for the convex hull is computed. If each pair of points is
enumerated, it will take more time. For this problem, rotating calipers is suitable to
compute the maximum distance among all pairs of points for the convex hull. The
program is shown as follows.
Program
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <cstdlib>
using namespace std;
#define N 50005 // the upper limit for the number of points
struct point{ // p[]: a sequence of coordinates
int x,y;
}p[N];
510 ◾ Algorithm Design Practice for Collegiate Programming
int main(){
int i,j,res=0; // res: the maximum distance
struct point begin; // the point with the minimum
y-coordinate
scanf("%d",&n); // number of farms
begin.x = begin.y = 10005; //Initialization for the
point with the minimum y-coordinate in convex hull
for(i = 1;i<=n;i++){ //Input every farm's coordinate
scanf("%d %d",&p[i].x,&p[i].y);
if(p[i].y < begin.y){ //adjust begin, note down the
sequence number j
begin = p[i];
j = i;
}else if(p[i].y==begin.y && p[i].x<begin.x){
begin = p[i];
j = i;
}
}
if(n==2){ //output the distance between two points
printf("%d\n",dis(p[1],p[2]));
return 0;
}
p[j] = p[1];
p[1] = begin;
sort(p+2,p+n+1,cmp); //Sorting point 2 … point n
Practice for Computational Geometry ◾ 511
8.5 Problems
8.5.1 Segments
Given n segments in the two-dimensional space, write a program that determines
if there exists a line such that after projecting these segments on it, all projected
segments have at least one point in common.
Input
Input begins with a number T showing the number of test cases and then, T test
cases follow. Each test case begins with a line containing a positive integer n≤100
showing the number of segments. After that, n lines containing four real numbers
x1 y1 x 2 y2 follow, in which (x1, y1) and (x 2, y2) are the coordinates of the two end-
points for one of the segments.
Output
For each test case, your program must output “Yes!”, if a line with the desired prop-
erty exists and must output “No!” otherwise. You must assume that two floating-
point numbers a and b are equal if |a−b| <10 -8.
512 ◾ Algorithm Design Practice for Collegiate Programming
3 Yes!
2 Yes!
1.0 2.0 3.0 4.0 No!
4.0 5.0 6.0 7.0
3
0.0 0.0 0.0 1.0
0.0 1.0 0.0 2.0
1.0 1.0 2.0 1.0
3
0.0 0.0 0.0 1.0
0.0 2.0 0.0 3.0
1.0 1.0 2.0 1.0
Source: Amirkabir University of Technology Local Contest 2006
ID for Online Judge: POJ 3304
Hint
The problem description is equivalent to determining whether there is a line l inter-
secting with n segments or not. If there is a line l intersecting with n segments, let
line m be perpendicular to line l, and line m is the line that the problem requires
you to find.
For segment i, its endpoints are p2×i and p2×i+1, 0≤i≤n−1. Each pair of endpoints
pi and pj (0≤i<j≤2n−1) is enumerated: if the line through pi and pj intersects with
or coincides with n segments, then all projected segments have at least one point in
common, and “Yes!” is output; else the next pair of points is enumerated. If there is
no line with the desired property, “No!” is output.
8.5.2 Titanic
It is a historical fact that during the legendary voyage of “Titanic”, the wireless
telegraph machine delivered six warnings about the danger of icebergs. Each of the
telegraph messages described the point where an iceberg had been noticed. The first
five warnings were transferred to the captain of the ship. The sixth one came late
at night, and the telegraph operator did not notice that the coordinates mentioned
were very close to the current ship’s position.
Write a program that will warn the operator about the danger of icebergs!
Practice for Computational Geometry ◾ 513
Input
The input messages are of the following format:
Message #<n>.
Received at <HH>:<MM>:<SS>.
Current ship’s coordinates are
<X1>^<X2>'<X3>" <NL/SL>
and <Y1>^<Y2>'<Y3>" <EL/WL>.
An iceberg was noticed at
<A1>^<A2>'<A3>" <NL/SL>
and <B1>^<B2>'<B3>" <EL/WL>.
===
Here <n> is a positive integer, <HH>:<MM>:<SS> is the time of the message
reception, <X1>^<X2>'<X3>"<NL/SL> and <Y1>^<Y2>'<Y3>"<EL/WL> means
“X1 degrees X2 minutes X3 seconds of North (South) latitude and Y1 degrees Y2
minutes Y3 seconds of East (West) longitude.”
Output
Your program should print to the output file message in the following format:
The distance to the iceberg: <s> miles,
where <s> should be the distance between the ship and the iceberg (that is the
length of the shortest path on the sphere between the ship and the iceberg). This
distance should be printed up to (and correct to) two decimal digits. If this distance
is less than (but not equal to!) 100 miles, the program should print one more line
with the text: “DANGER!”
Hint
For simplicity of calculations, assume that the Earth is an ideal sphere with the
diameter of 6875 miles completely covered with water. Also, you can be sure that
lines in the input file break exactly as shown in the input samples. The ranges of
the ship and the iceberg coordinates are the same as the usual range for geographi-
cal coordinates, i.e., from 0 to 90 degrees inclusively for NL/SL and from 0 to
180 degrees inclusively for EL/WL.
Hint
The problem requires you to calculate the distance between two points on a sphere.
The formula calculating spherical distance is used to solve the problem directly.
If the distance is less than 100 miles, the program should print one more line with
the text: “DANGER!”
8.5.3 Intervals
In the ceiling in the basement of a newly open developers’ building, a light source
has been installed. Unfortunately, the material used to cover the floor is very sensi-
tive to light. It turns out that its expected lifetime is decreasing dramatically. To
avoid this, authorities have decided to protect light-sensitive areas from strong light
by covering them. The solution was not very easy because, as is common, in the
basement there are different pipelines under the ceiling, and the authorities want to
install the covers just on those parts of the floor that are not shielded from the light
by pipes. To cope with the situation, the first decision was to simplify the real situ-
ation and, instead of solving the problem in 3-D space, to construct a 2-D model
first (see Figure 8.37).
Ceiling
Floor
Figure 8.37
Practice for Computational Geometry ◾ 515
Within this model, the x-axis has been aligned with the level of the floor. The
light is considered to be a point light source with integer coordinates [bx, by]. The
pipes are represented by circles. The center of the circle i has the integer coordi-
nates [cxi, cyi] and an integer radius ri. As pipes are made from solid material, circles
cannot overlap. Pipes cannot reflect the light and the light cannot go through the
pipes. You have to write a program that will determine the non-overlapping inter-
vals on the x-axis where there is, due to the pipes, no light from the light source.
Input
The input consists of blocks of lines, each of which except the last describes one
situation in the basement. The first line of each block contains a positive integer
number N<500 expressing the number of pipes. The second line of the block con-
tains two integers bx and by separated by one space. Each of the next N lines of the
block contains integers cxi, cyi and ri, where cyi+ri<by. Integers in individual lines are
separated by one space. The last block consists of one line containing n=0.
Output
The output consists of blocks of lines, corresponding to the blocks in the input
(except the last one). One empty line must be put after each block in the output.
Each of the individual lines of the blocks in the output will contain two real num-
bers, the endpoints of the interval where there is no light from the given point light
source. The reals are exact to two decimal places and separated by one space. The
intervals are sorted according to increasing x-coordinate.
6 0.72 78.86
300 450 88.50 133.94
70 50 30 181.04 549.93
120 20 20
270 40 10 75.00 525.00
250 85 20
220 30 30 300.00 862.50
380 100 100
1
300 300
300 150 90
1
300 300
390 150 90
0
Source: ACM Central Europe 1996
IDs for Online Judges: POJ 1375, ZOJ 1309, UVA 313
516 ◾ Algorithm Design Practice for Collegiate Programming
Hint
Suppose the point light source is node b, and the center and the radius of the circle
i are pi and ri respectively. There are two tangent lines from node b for the circle i,
where the x-coordinates for the intersection points for two tangent lines and X-axis
are Li and Ri respectively.
First, for circle i, 1≤i≤n, Li and Ri are calculated. Then circles are sorted in ascend-
ing order for Li: order[0..n−1]. Finally, each circle in order[0..n−1] is analyzed one by
one to determine the interval where there is no light from the given point light source.
75
71
61
47
38
14
0 0
0 20 40 85 100
Figure 8.38
Practice for Computational Geometry ◾ 517
Input
The input will consist of one case. The first line will be an integer n (0≤n≤30)
specifying the number of interior walls, followed by n lines containing the integer
endpoints of each wall x1 y1 x 2 y2. The four enclosing walls of the pyramid have fixed
endpoints at (0,0); (0,100); (100,100), and (100,0) and are not included in the list
of walls. The interior walls always span from one exterior wall to another exterior
wall and are arranged such that no more than two walls intersect at any point. You
may assume that no two given walls coincide. After the listing of the interior walls,
there will be one final line containing the floating-point coordinates of the treasure
in the treasure room (guaranteed not to lie on a wall).
Output
Print a single line listing the minimum number of doors that need to be created, in
the format shown below.
7 Number of doors = 2
20 0 37 100
40 0 76 100
85 0 0 75
100 90 0 90
0 71 100 61
0 14 100 38
100 47 47 100
54.5 55.4
Source: ACM East Central North America 1999
IDs for Online Judges: POJ 1066, ZOJ 1158, UVA 754
Hint
For each interior wall, the line segment connecting the treasure and its endpoint
can be regarded as a route for archeologists entering the treasure room. The number
of intersection points for the line segment and interior walls is the number of doors
which archeologists need to create for interior walls.
The i-th interior wall is represented as an edge vector p1i p2i , 0≤i≤n−1, where p1i
and p2i are endpoints for the i-th interior wall; and the floating-point coordinate of
the treasure in the treasure room is p.
The line segment connecting the treasure
and the starting point for the i-th inte-
rior wall is represented as an edge vector pp1i , 0≤i≤n−1. Suppose Ai is the number of
intersection points for the line segment and interior walls. A=min{A1, A 2, …, An}.
518 ◾ Algorithm Design Practice for Collegiate Programming
8.5.5 Intersection
You are to write a program that has to decide whether a given line segment inter-
sects a given rectangle.
Here’s an example:
The line is said to intersect the rectangle if the line and the rectangle have at
least one point in common. The rectangle consists of four straight lines and the area
in between, as shown in Figure 8.39. Although all input values are integer numbers,
valid intersection points do not have to lay on the integer grid.
Input
The input consists of n test cases. The first line of the input file contains the number
n. Each following line contains one test case of the format:
where (xstart, ystart) is the start and (xend, yend) the end point of the line and (xleft,
ytop) the top-left and (xright, ybottom) the bottom-right corner of the rectangle. The
(0, 0) X
eight numbers are separated by a blank. The terms “top left” and “bottom right” do
not imply any ordering of coordinates.
Output
For each test case in the input file, the output file should contain a line consisting
either of the letter “T” if the line segment intersects the rectangle, or the letter “F”
if the line segment does not intersect the rectangle.
1 F
4 9 11 2 1 5 7 1
Source: ACM Southwestern European Regional Contest 1995
IDs for Online Judges: POJ 1410, UVA 191
Hint
Suppose the given line segment is pt1 pt 2 , where the start point for the line segment
is pt1 and the end point is pt2. Based on the left-top and the right-bottom corners
for the given rectangle, the left-bottom corner, the right-top corner, and four edges
for the rectangle are calculated.
The rectangle consists of four straight lines and the area in between. If pt1 and
pt2 are in the area for the rectangle, the line intersects the rectangle. And if the line
segment intersects any edge for the rectangle, the line segment intersects the rect-
angle. Otherwise, the line segment doesn’t intersect the rectangle.
The pictures transmitted by the Discovery space ship depict that plants in the
Y1999 planet grow in special points on the planet. Analysis of several thousands
520 ◾ Algorithm Design Practice for Collegiate Programming
Input
The first line of the input is M, the number of test cases to be solved (1≤M≤10). For
each test case, the first line is N, the number of plants in that test case (1≤N≤50),
followed by N lines for each plant data. Each plant data consists of three integers:
the first number is the unique plant index (1..N), followed by two positive integers
x and y representing the coordinates of the plant. Plants are sorted by the increasing
order on their indices in the input file. Suppose that the values of coordinates are
at most 100.
Output
Output should have one separate line for the solution of each test case. A solution is
the number of plants on the solution path, followed by the indices of visiting plants
in the path in the order of their visits.
Plant A
Starting
point
Figure 8.40
Practice for Computational Geometry ◾ 521
2 10 8 7 3 4 9 5 6 2 1 10
10 14 9 10 11 5 12 8 7 6 13 4 14 1 3 2
1 4 5
2 9 8
3 5 9
4 1 7
5 3 2
6 6 3
7 10 10
8 8 1
9 2 4
10 7 6
14
1 6 11
2 11 9
3 8 7
4 12 8
5 9 20
6 3 2
7 1 6
8 2 13
9 15 1
10 14 17
11 13 19
12 5 18
13 7 3
14 10 16
Source: ACM Tehran 1999
IDs for Online Judges: POJ 1696, ZOJ 1429
Hint
Suppose N plants are a0, a1, …, aN −1. A with the coordinates (xA, yA) is the plant with
the least y-coordinate. M11 starts from point (0, yA) heading towards plant A. Therefore
A is as the first plant a0. Then from ai, i≥0, the next plant is analyzed one by one: based
on ai, the remaining plants are sorted as ai+1, …, aN −1, where the first key is the direc-
tion, and the second key is the distance between ai and the plant. The next plant is ai+1.
quarter of the plane, such that their sides make 45 degrees with x and yaxes, and one
of their vertices is on the y=0 line. Let bi be the x coordinates of the bottom vertex of
Si. First, put S1 such that its left vertex lies on x=0. Then, put S1, (i>1) at minimum bi
such that
bi > bi−1 and
the interior of Si does not have intersection with the interior of S1 ... Si−1.
The goal is to find which squares are visible, either entirely or partially, when
viewed from above. In Figure 8.41, the squares S1, S2, and S4 have this property.
More formally, Si is visible from above if it contains a point p, such that no square
other than Si intersects the vertical half-line drawn from p upwards.
Input
The input consists of multiple test cases. The first line of each test case is n (1≤n≤50),
the number of squares. The second line contains n integers between 1 to 30, where
the i-th number is the length of the sides of Si. The input is terminated by a line
containing a zero number.
Output
For each test case, output a single line containing the index of the visible squares in
the input sequence, in ascending order, separated by blank characters.
4 1 2 4
3 5 1 4 1 3
3
2 1 2
0
Source: ACM Tehran 2006
IDs for Online Judges: POJ 3347, UVA 3799
S2
S4
S1
b1 b2 b3 b4 x
S3
Figure 8.41
Practice for Computational Geometry ◾ 523
Si
Sj
lefi regi x
Figure 8.42
Hint
Suppose the length of one side for the i-th square is li, and projections on the x-axis
for its left end and right end are lef i and rigi, respectively, 0≤i≤n−1. This is shown in
Figure 8.42. If the i-th square is visible, the visible interval is [lei, rii].
Because of the precision of real numbers, the sides of squares are expanded 2
times. Obviously, lef 0 =0, and rig0 =2×l0.
First, for other squares, their lef i and rigi are calculated: lef i = max {rig j − l i − l j },
0 ≤ j ≤i −1
rigi=lef i+2×li, 1≤i≤n−1.
Then, based on lef i and rigi, visible intervals for all squares are calculated:
lei = max {rig j , lef i }, rii = min {rig i , lef j }.
0≤ j ≤i −1 i +1≤ j ≤n −1
Finally, every square is analyzed. If lei<rii, then the (i+1)th square is visible; else
it is invisible.
8.5.8 Pipe
The GX Light Pipeline Company started to prepare bent pipes for the new trans-
galactic light pipeline. During the design phase of the new pipe shape, the com-
pany ran into the problem of determining how far the light can reach inside each
component of the pipe. Note that the material which the pipe is made from is not
transparent and is not light reflecting.
Each pipe component consists of many straight pipes connected tightly together.
For programming purposes, the company developed the description of each com-
ponent as a sequence of points [x1; y1], [x 2; y2], . . ., [xn; yn], where x1<x 2<. . .<xn. These
are the upper points of the pipe contour. The bottom points of the pipe contour
consist of points with y-coordinate decreased by 1. To each upper point [xi; yi], there
is a corresponding bottom point [xi; yi−1] (see Figure 8.43). The company wants to
find, for each pipe component, the point with maximal x-coordinate that the light
will reach. The light is emitted by a segment source with endpoints [x1; y1−1] and
[x1;y1] (endpoints are emitting light, too). Assume that the light is not bent at the
pipe bent points and the bent points do not stop the light beam.
524 ◾ Algorithm Design Practice for Collegiate Programming
[x4, y4]
[x2, y2]
[x3, y3]
[x1, y1]
Figure 8.43
Input
The input file contains several blocks, each describing one pipe component. Each
block starts with the number of bent points 2≤n≤20 on a separate line. Each of the
next n lines contains a pair of real values xi, yi separated by space. The last block is
denoted with n=0.
Output
The output file contains lines corresponding to blocks in the input file. To each
block in the input file, there is one line in the output file. Each such line contains
either a real value, written with precision of two decimal places, or the message
“Through all the pipe.”. The real value is the desired maximal x-coordinate of the
point where the light can reach from the source for the corresponding pipe compo-
nent. If this value equals to xn, then the message “Through all the pipe.” will appear
in the output file.
4 4.67
0 1 Through all the pipe.
2 2
4 1
6 4
6
0 1
2 -0.6
5 -4.45
7 -5.57
12 -10.8
17 -16.55
0
Source: ACM Central Europe 1995
IDs for Online Judges: POJ 1039, UVA 303
Practice for Computational Geometry ◾ 525
Hint
Given a pipe component, the problem requires you to find the point with maximal
x-coordinate that the light will reach, or the light can be through all the pipe.
There are n pairs of points: the upper point [xi, yi], and its corresponding bottom
point [xi, yi−1], 1≤i≤n. Such a light must be through an upper point and a bottom
point. Therefore, enumeration is used to solve the problem. Lines through an upper
point and a bottom point are enumerated.
Input
The input contains several pictures. Each picture describes at most 26 shapes, each
specified on a separate line. The line begins with an uppercase letter that uniquely
identifies the shape inside the corresponding picture. Then there is a kind of the
shape and two or more points, everything separated by at least one space. Possible
shape kinds are as follows:
Square: Followed by two distinct points giving the opposite corners of the
square.
Rectangle: Three points are given; there will always be a right angle between the
lines connecting the first point with the second and the second with the third.
A B S
X
Figure 8.44
526 ◾ Algorithm Design Practice for Collegiate Programming
Line: Specifies a line segment; two distinct end points are given.
Triangle: Three points are given; they are guaranteed not to be colinear.
Polygon: Followed by an integer number N (3≤N≤20) and N points specifying
vertices of the polygon in either clockwise or anticlockwise order. The poly-
gon will never intersect itself and its sides will have non-zero length.
All points are always given as two integer coordinates X and Y separated with a
comma and enclosed in parentheses. You may assume that |X|,|Y|≤10000.
The picture description is terminated by a line containing a single dash (“−”).
After the last picture, there is a line with one dot (“.”).
Output
For each picture, output one line for each of the shapes, sorted alphabetically by its
identifier (X ). The line must be one of the following:
Please note that there is an additional comma for more than two intersections.
A, B, etc. are all intersecting shapes, sorted alphabetically.
Print one empty line after each picture, including the last one.
Hint
Enumeration is used to solve the problem. All pairs of different shapes are enumer-
ated. A square, a triangle, or a polygon is represented as a set of lines. That is, two
shapes are intersected if and only if their lines are intersected.
Input
Input consists of a series of piece descriptions. Each piece description consists of the
following data:
On a line for each vertex, listed in order, the X and Y position of vertex. The end
of input is indicated by a number of polygon vertices less than three.
528 ◾ Algorithm Design Practice for Collegiate Programming
Output
For each piece description, print a single line containing the string:
“HOLE IS ILL-FORMED” if the hole contains protrusions.
“PEG WILL FIT” if the hole contains no protrusions and the peg fits in the
hole at the indicated position.
“PEG WILL NOT FIT” if the hole contains no protrusions but the peg will not
fit in the hole at the indicated position.
Hint
Suppose the position for the peg is peg, its radius is r; and the sequence for vertices
of the polygon are p0, …, pn, where pn=p0.
2. Determine whether the position for the peg is in the polygon or not.
The necessary condition that the peg fits in the hole is that the position for
the peg is in the polygon. Suppose peg is a line segment
from the origin to
vertex peg. Initially c0 and c1 are 0. Each side pi +1 pi (0≤i≤n−1) of the polygon
is enumerated. If pi+1 pi ^ peg < 0, c0++; and if pi +1 pi ^ peg > 0 , c1++. After
all sides are enumerated, if (c0!=0&&c1!=0), then the position for the peg
isn’t in the polygon.
3. Determine whether the peg fits in the hole or not.
If the position for the peg is in the polygon, then the distance from peg to
p
i peg ^ pi pi +1
sides for the polygon m = min is calculated. If r>m, then
0 ≤i ≤ n −1
pi pi +1
the peg can’t fit in the hole; else the peg can fit in the hole.
8.5.11 Triangle
A lattice point is an ordered pair (x, y) where x and y are both integers. Given the
coordinates of the vertices of a triangle (which happen to be lattice points), you are
to count the number of lattice points which lie completely inside of the triangle
(points on the edges or vertices of the triangle do not count).
Input
The input test file will contain multiple test cases. Each input test case consists of
six integers x1, y1, x 2, y2, x3, and y3, where (x1, y1), (x 2, y2), and (x3, y3) are the coor-
dinates of vertices of the triangle. All triangles in the input will be non-degenerate
(will have positive area), and −15000≤ x1, y1, x 2, y2, x3, y3 ≤15000. The end-of-file is
marked by a test case with x1 = y1 = x 2 = y2 = x3 = y3 = 0 and should not be processed.
Output
For each input case, the program should print the number of internal lattice points
on a single line.
0 0 1 0 0 1 0
0 0 5 0 0 5 6
0 0 0 0 0 0
Source: Stanford Local 2004
ID for Online Judge: POJ 2954
530 ◾ Algorithm Design Practice for Collegiate Programming
Hint
Suppose p1, p2, and p3 are vertices of a triangle. Then the area for the triangle is
p1 ^ p2 + p2 ^ p3 + p3 ^ p1
S = . Suppose g ( pi p j ) is the number of points on pi,
2
pj, and pi p j .
pi . y − p j . y pi . x − p j . x = 0
g ( pi p j ) = pi . x − p j . x pi . y − p j . y = 0 . .
(
gcd pi . y − p j . y , pi . x − p j . x
) otherwise
Based on Pick’s theorem, the area for a triangle S∆ = the number of internal
g ( p1 p2 ) + g ( p2 p3 ) + g ( p3 p1 )
lattice points + − 1. Therefore, the number of internal
2
g ( p1 p2 ) + g ( p2 p3 ) + g ( p3 p1 )
lattice points = S∆ − + 1.
2
8.5.12 Ants
Young naturalist Bill studies ants in school. His ants feed on plant-louses that live
on apple trees. Each ant colony needs its own apple tree to feed itself.
Bill has a map with coordinates of n ant colonies and n apple trees. He knows
that ants travel from their colony to their feeding places and back using chemically
tagged routes. The routes cannot intersect each other, or ants will get confused and
get to the wrong colony or tree, thus spurring a war between colonies.
Bill would like to connect each ant colony to a single apple tree so that all n
routes are non-intersecting straight lines. In this problem, such a connection is
always possible. Your task is to write a program that finds such a connection.
In Figure 8.45, ant colonies are denoted by empty circles and apple trees are
denoted by filled circles. One possible connection is denoted by lines.
Input
The first line of the input file contains a single integer number n (1≤n≤100)—the
number of ant colonies and apple trees. It is followed by n lines describing n ant
colonies, followed by n lines describing n apple trees. Each ant colony and apple
tree is described by a pair of integer coordinates x and y (−10,000≤x, y≤10,000) on a
Cartesian plane. All ant colonies and apple trees occupy distinct points on a plane.
No three points are on the same line.
Practice for Computational Geometry ◾ 531
2
2
4 1 4
1
5 5
3
Figure 8.45
Output
Write to the output file n lines with one integer number on each line. The number
written on the i-th line denotes the number (from 1 to n) of the apple tree that is
connected to the i-th ant colony.
5 4
-42 58 2
44 86 1
7 28 5
99 34 3
-13 -59
-47 -44
86 74
68 -75
-68 60
99 -60
Source: ACM Northeastern Europe 2007
IDs for Online Judges: POJ 3565, UVA 4043
Hint
Suppose ai is the position for ant colony i, bj is the position for apple tree j, and 1≤i,
j≤n. Set x consisits of n ant colonies, and set y consisits of n apple trees. The weight
of edge (ai, bj) is − ai b j . Then a KM algorithm is used to calculate the maximum
matching.
532 ◾ Algorithm Design Practice for Collegiate Programming
Input
The input data for the illustrated chamber would appear as follows:
2
42789
7 3 4.5 6 7
The first line contains the number of interior walls. Then there is a line for each
such wall, containing five real numbers. The first number is the x coordinate of the
wall (0<x<10), and the remaining four are the y coordinates of the ends of the door-
ways in that wall. The x coordinates of the walls are in increasing order, and within
each line, the y coordinates are in increasing order. The input file will contain at least
one such set of data. The end of the data comes when the number of walls is −1.
Output
The output should contain one line of output for each chamber. The line should
contain the minimal path length rounded to two decimal places past the decimal
point, and always showing two decimal places past the decimal point. The line
should contain no blanks.
10
9
8
7 7
6
5 5
4.5
3
2
0
0 4 7 10
Figure 8.46
Practice for Computational Geometry ◾ 533
1 10.00
5 4 6 7 8 10.06
2
4 2 7 8 9
7 3 4.5 6 7
-1
Source: ACM Mid-Central USA 1996
IDs for Online Judges: POJ 1556, ZOJ 1721, UVA 393
Hint
There are 4n+2 vertices, where p0 =(0, 5), p4×n+1=(10, 5), p4×i −3 p4×i −2 is the first door
for the i-th wall, and p4×i −1 p4×i is the second door for the i-th wall (1≤i≤n).
The distance between each pair of vertices pi and pj is calculated (0≤i<4×n+1,
i<j≤4×n+1), d ij = pi p j . If the intersection point for pi p j and the k-th wall
(pi.x≤p4×k .x≤pj.x) isn’t at p4×k −3 p4×k −2 or p4×k −1 p4×k , then dij=∞.
Then the Floyd algorithm is used to calculate the shortest distance between
each pair of vertices dij.
Finally, d0,4n+1 is the minimal path length.
8.5.14 Toys
Calculate the number of toys that land in each bin of a partitioned toy box.
Mom and dad have a problem—their child John never puts his toys away when
he is finished playing with them. They gave John a rectangular box to put his toys
in, but John is rebellious and obeys his parents by simply throwing his toys into the
box. All the toys get mixed up, and it is impossible for John to find his favorite toys.
John’s parents came up with the following idea. They put cardboard partitions
into the box. Even if John keeps throwing his toys into the box, at least toys that
get thrown into different bins stay separated. Figure 8.47 shows a top view of an
example toy box.
Figure 8.47
534 ◾ Algorithm Design Practice for Collegiate Programming
For this problem, you are asked to determine how many toys fall into each par-
tition as John throws them into the toy box.
Input
The input file contains one or more problems. The first line of a problem consists
of six integers, n m x1 y1 x 2 y2. The number of cardboard partitions is n (0<n≤5000)
and the number of toys is m (0<m≤5000). The coordinates of the upper-left corner
and the lower-right corner of the box are (x1, y1) and (x 2, y2), respectively. The fol-
lowing n lines contain two integers per line, Ui Li, indicating that the ends of the
i-th cardboard partition is at the coordinates (Ui, y1) and (Li, y2). You may assume
that the cardboard partitions do not intersect each other and that they are specified
in sorted order from left to right. The next m lines contain two integers per line, xj yj
specifying where the j-th toy has landed in the box. The order of the toy locations
is random. You may assume that no toy will land exactly on a cardboard partition
or outside the boundary of the box. The input is terminated by a line consisting of
a single 0.
Output
The output for each problem will be one line for each separate bin in the toy box.
For each bin, print its bin number, followed by a colon and one space, followed by
the number of toys thrown into that bin. Bins are numbered from 0 (the leftmost
bin) to n (the rightmost bin). Separate the output of different problems by a single
blank line.
5 6 0 10 60 0 0: 2
3 1 1: 1
4 3 2: 1
6 8 3: 1
10 10 4: 0
15 30 5: 1
1 5
2 1 0: 2
2 8 1: 2
5 5 2: 2
40 10 3: 2
7 9 4: 2
4 10 0 10 100 0
20 20
40 40
60 60
Practice for Computational Geometry ◾ 535
80 80
5 10
15 10
25 10
35 10
45 10
55 10
65 10
75 10
85 10
95 10
0
Source: ACM Rocky Mountain 2003
IDs for Online Judges: POJ 2318, UVA 2910
Hint
Suppose the coordinates of the ends of the i-th cardboard partition are p'i and p"i
respectively, 0≤i≤n−1; and the coordinates of the upper-right corner and the lower-
right corner of the box are p'n and p"n respectively.
For each input toy, dichotomy is used to calculate the bin ret in which John
throws the toy. After m toys are input, the numbers of toys thrown into each bin
are calculated.
8.5.15 Area
Being well known for its highly innovative products, Merck would definitely be a
good target for industrial espionage. To protect its brand new research and devel-
opment facility, the company has installed the latest system of surveillance robots
patrolling the area. These robots move along the walls of the facility and report
suspicious observations to the central security office. The only flaw in the system
a competitor agent could find is the fact that the robots radio their movements
unencrypted. Not being able to find out more, the agent wants to use that informa-
tion to calculate the exact size of the area occupied by the new facility. It is public
knowledge that all the corners of the building are situated on a rectangular grid and
that only straight walls are used. Figure 8.48 shows the course of a robot around
an example area.
You are hired to write a program that calculates the area occupied by the new
facility from the movements of a robot along its walls. You can assume that this
536 ◾ Algorithm Design Practice for Collegiate Programming
Figure 8.48
area is a polygon with corners on a rectangular grid. However, your boss insists that
you use a formula that he is proud to have found somewhere. The formula relates
the number I of grid points inside the polygon, the number E of grid points on the
edges, and the total area A of the polygon. Unfortunately, you have lost the sheet
on which he had written down that simple formula for you, so your first task is to
find the formula yourself.
Input
The first line contains the number of scenarios.
For each scenario, you are given the number m, 3≤m<100, of movements of
the robot in the first line. The following m lines contain pair “dx dy” of integers,
separated by a single blank, satisfying −100≤dx, dy≤100 and (dx, dy)!=(0, 0). Such
a pair means that the robot moves on to a grid point dx units to the right and dy
units upwards on the grid (with respect to the current position). You can assume
that the curve along which the robot moves is closed and that it does not intersect
or even touch itself except for the start and end points. The robot moves anticlock-
wise around the building, so the area to be calculated lies to the left of the curve.
It is known in advance that the whole polygon would fit into a square on the grid
with a side length of 100 units.
Output
The output for every scenario begins with a line containing “Scenario #i:” where
i is the number of the scenario starting at 1. Then print a single line containing
I, E, and A, the area A rounded to one digit after the decimal point. Separate the
three numbers by two single blanks. Terminate the output for the scenario with
a blank line.
Practice for Computational Geometry ◾ 537
2 Scenario #1:
4 0 4 1.0
1 0
0 1 Scenario #2:
-1 0 12 16 19.0
0 -1
7
5 0
1 3
-2 2
-1 0
0 -3
-3 1
0 -3
Source: ACM Northwestern Europe 2001
IDs for Online Judges: POJ 1265, ZOJ 1032, UVA 2329
Hint
Given a polygon on a rectangular grid, the number I of grid points inside the poly-
gon, the number E of grid points on the edges, and the total area A of the polygon
are required to be calculated.
Based on Pick’s theorem, the total area A of the polygon is I+E/2−1. The total
area A of the polygon is the sum of all cross products for vectors from the origin to
each pair of adjacent vertices. E=gcd(abs(x 2−x1), abs(y2−y1)). Finally I is calculated.
House
Tree
Hedge
Property line
Figure 8.49
Input
Because each object is a line, it is represented in the input file with a left and right
x coordinate followed by a single y coordinate:
<x1><x 2><y>
Output
For each house, your program should print a line containing the length of the lon-
gest continuous segment of the property line from which the entire house can be
seen to a precision of two decimal places. If there is no section of the property line
where the entire house can be seen, print “No View”.
2 6 6 8.80
0 15 0 No View
3
1 2 1
3 4 1
12 13 1
1 5 5
Practice for Computational Geometry ◾ 539
0 10 0
1
0 15 1
0 0 0
Source: ACM Mid-Atlantic 2004
IDs for Online Judges: POJ 2074, ZOJ 2325, UVA 3112
Hint
The key to the problem is to calculate the line equation through two points and the
intersection point for two lines.
On the property line, each obstruction corresponds to a line segment where the
house can’t be seen, as dotted lines in Figure 8.50. All corresponding dotted lines
are sorted and scanned to calculate the result.
Input
The first line contains the number of test cases.
House
Tree
Hedge
Property line
Figure 8.50
540 ◾ Algorithm Design Practice for Collegiate Programming
Figure 8.51
Each test case consists of eight integers not exceeding 10,000 by absolute value,
x1, y1, x 2, y2, x3, y3, x4, y4. (x1, y1), (x 2, y2) are the endpoints of one board, and (x3, y3),
(x4, y4) are the endpoints of the other one.
Output
For each test case, output a single line containing a real number with precision up
to two decimal places—the amount of rain collected.
2 1.00
0 1 1 0 0.00
1 0 2 1
0 1 2 1
1 0 1 2
Source: POJ Monthly, 2006.04.28, Dagger@PKU_RPWT
ID for Online Judge: POJ 2826
Hint
Two wooden boards (line segments) constitute a container. The problem requires
you to calculate the amount of rain that the container can collect.
Cases are shown in Figure 8.52.
Figure 8.52
Practice for Computational Geometry ◾ 541
p1 + (0, 1)
p1 + (0, 1)
p1
p1
tp p3
tp p3
p p
p4 p4
p2
p2
The rain can’t be collected. The shaded area is collected rain.
Figure 8.53
Suppose two wooden boards (line segments) are p1 p2 and p3 p4 respectively,
where p1.y≥p2.y, p3.y≥p4.y, and p1.y≥p3.y.
If there is no intersection point for p1 p2 and p3 p4 , the rain can’t be collected;
Suppose the intersection point for p1 p2 and p3 p4 is p, and the intersection point
for p1 p2 and the horizontal line is tp (as shown in Figure 8.53). If signs for pp1 ^ pp3
and p1 ( p1 + (0,1)) ^ p1 p3 are the same, or p1 ( p1 + (0,1)) and p1 p3 coincide, then the
rain can’t be collected; else the amount of collected rain is S∆tpp3 p .
w1
(x1, y1)
4 1 3
s2
4 1
2
4
3 1
3 2 (u2, v2)
(u1, v1) 2 3 2
4
s1
1
w2
(x2, y2)
Figure 8.54
542 ◾ Algorithm Design Practice for Collegiate Programming
Input
The input file contains twelve floating-point numbers: x1 y1 u1 v1 w1 s1 x 2 y2 u2 v2 w2
s2, where (x, y) and (u, v)—coordinates of back-left and forward-left corners of the
car, w—width of the car, s—speed of the car.
Constraints
1≤xi,yi,ui,vi,wi≤106,0≤si≤106. Input data is such that a crash certainly happens.
Initially cars don’t have common points.
Output
The output file must contain two integers: p1 p2, where p is the number of the part
which first contacted the other one (if two parts came into contact simultaneously,
output the lesser of the part numbers).
1 1 10 1 1 20 2 1
40 1 50 1 1 10
Source: ACM Northeastern Europe 2005, Far-Eastern Subregion
ID for Online Judge: POJ 3433
Hint
Two cars go at their speeds. Suppose one car stops, and the other car goes at a rela-
tive speed (see Figure 8.55).
Then the moving trail is determined. There are three cases: The first car’s point
comes into contact with the second car’s side; the second car’s point comes into
contact with the first car’s side; or two cars’ points crash together.
w1
(x1, y1)
4 1
s
3
3 2 (u2, v2)
(u1, v1) 2 4
1
w2
(x2, y2)
Figure 8.55
◾◾ Colonel Bill, with a score of 7 for shooting, 5 for knife throwing and 3 for
harmonica playing, and
◾◾ Rabid Jack, with a score 10 for shooting, 6 for knife throwing and 8 for har-
monica playing
Then a Hero with score 8 for shooting, 7 for knife throwing, and 3 for har-
monica playing can defeat both of them. However, someone with a score of 8 for
shooting, 6 for knife throwing, and 8 for harmonica playing cannot be the Hero.
Moreover, the Hero cannot be a member of the evil society.
544 ◾ Algorithm Design Practice for Collegiate Programming
Your task is to determine whether there is a member in the Union who can be
the Hero. If so, then you have to count how many members are potential heroes.
Input
The input contains several blocks of test cases. Each block begins with a line con-
taining two integers: the number 1≤n≤100000 of members in the Society of Evil
Mysterious Strangers and the maximum value 2≤m≤100000 of the scores. The next
n lines describe these members. Each line contains three integers between 1 and m:
the scores for the three skills.
The input is terminated by a block with n=m=0.
Output
For each test case, you have to output a single line containing the number of members
in the Union who satisfy the requirements for becoming a Hero. If there is no such
member, then output ‘0’. It can be assumed that the output is always at most 1018.
3 10 848
2 8 5 19
6 3 5 999999999992
1 3 9
1 3
2 2 2
1 10000
2 2 2
0 0
Source: ACM Central Europe 2005
IDs for Online Judges: POJ 2944, UVA 3525
Hint
There are M 3 gunmen characterized by three different skills, each ranging from
1 to M. A subset containing N of these gunmen are The Bad Guys. We want to
select one of the other gunmen to be a Hero. The Hero must beat each of the Bad
Guys in at least one skill (not necessarily the same skill for all Bad Guys).
The task is to compute the number of gunmen that can be selected to be the
Hero.
Practice for Computational Geometry ◾ 545
Consider a Bad Guy with skills [a, b, c]. The set of gunmen that can’t beat him is
a cuboid with opposite corners [1,1,1] and [a, b, c]. The union U of all these cuboids
is exactly the set of gunmen that can’t be heroes. Thus the answer is M 3 minus the
volume of U.
We can compute the volume of U in O(MlogM) by sweeping in one direction
and maintaining the intersection of the sweeping plane and U in some tree-like
structure.
In C++, STL sets can be used, so there is no need to implement the tree-like
structure.
Input
The input is a sequence of building triples. All coordinates of buildings are positive
integers less than 10,000, and there will be at least one and at most 5,000 build-
ings in the input file. Each building triple is on a line by itself in the input file. All
integers in a triple are separated by one or more spaces. The triples will be sorted
by Li, the left x-coordinate of the building, so the building with the smallest left
x-coordinate is first in the input file.
0 5 10 15 20 25 30 0 5 10 15 20 25 30
Figure 8.56
546 ◾ Algorithm Design Practice for Collegiate Programming
Output
The output should consist of the vector that describes the skyline as shown in
Figure 8.56. In the skyline vector (v1, v2, v3, …, vn−2, vn−1, vn), the vi such that i is an
even number represents a horizontal line (height). The vi such that i is an odd number
represents a vertical line (x-coordinate). The skyline vector should represent the “path”
taken, for example, by a bug starting at the minimum x-coordinate and traveling hori-
zontally and vertically over all the lines that define the skyline. Thus the last entry in
the skyline vector will be a 0. The coordinates must be separated by a blank space.
1 11 5 1 11 3 13 9 0 12 7 16 3 19 18 22 3 23 13 29 0
2 6 7
3 13 9
12 7 16
14 3 25
19 18 22
23 13 29
24 4 28
Source: Internet Programming Contest 1990
ID for Online Judge: UVA 105
Hint
The sweep line method is used to solve the problem.
Suppose the current building is represented by an ordered triple (left, height,
right), the right border for the skyline is rightmost, and for each point i on the bot-
tom, a[i] is its height for the current skyline, 1≤i≤rightmost.
After a building triple is input, a[i] in the interval (left≤i≤right) and rightmost
are adjusted: a[i]=max{a[i], height}(left≤i≤right); rightmost=max{rightmost, right}.
Then the sweep line method is used to enumerate points on the bottom. If
a[i]≠a[i−1], then output i and a[i]. Finally, rightmost+1 and 0 are output.
8.5.21 Lining Up
“How am I ever going to solve this problem?” said the pilot.
Indeed, the pilot was not facing an easy task. She had to drop packages at spe-
cific points scattered in a dangerous area. Furthermore, the pilot could only fly over
the area once in a straight line, and she had to fly over as many points as possible.
All points were given by means of integer coordinates in a two-dimensional space.
Practice for Computational Geometry ◾ 547
The pilot wanted to know the largest number of points from the given set that all
lie on one line. Can you write a program that calculates this number?
Your program has to be efficient!
Input
The input consists of several cases. The first line of each case is an integer N
(1<N<700), and then follow N pairs of integers. Each pair of integers is separated
by one blank and ended by a newline character. The input ended by N=0.
Output
Output one integer for each input case, representing the largest number of points
that all lie on one line.
1 1 3
2 2
3 3
9 10
10 11
Source: ACM 1994 East-Central Regionals
IDs for Online Judges: POJ 1118, UVA 270
Hint
Given n distinct points in a two-dimensional plane, find the maximum number of
points which lie in an arbitrary line.
An algorithm whose time complexity is O(n2lg(n)) is as follows:
The initial step to solve this problem is by sorting the points based on their
y-coordinates in ascending order. In case of ties, sort the points based on their
x-coordinates in ascending order.
The next step is to give each point a turn to become a pivot point. In each turn,
create a new set based on the remaining points (the ones which have greater indices
than the pivot point index) and sort these points angularly with respect to the pivot
point. Using the fact that this new set is sorted angularly, a simple O(n) algorithm
can be devised to find the maximum number of points on a line whose bottom-left
endpoint is the pivot.
548 ◾ Algorithm Design Practice for Collegiate Programming
One may ask why the points whose indices are less than pivot point are omitted
during each pivot turn. Those points can be safely ignored without worrying that the
final result won’t be optimal. When an earlier point is a part of the optimal line, then
the optimal result should have already been computed in an earlier pivot turn (remem-
ber the fact that the points were initially sorted based on their Cartesian coordinates).
8.5.22 Triathlon
A triathlon is an athletic contest consisting of three consecutive sections that should
be completed as fast as possible as a whole. The first section is swimming, the
second section is riding a bicycle, and the third one is running.
The speed of each contestant in all three sections is known. The judge can choose
the length of each section arbitrarily provided that no section has zero length. As a
result, sometimes she could choose their lengths in such a way that some particular
contestant would win the competition.
Input
The first line of the input file contains integer number N (1≤N≤100), denoting the
number of contestants. Then N lines follow, and each line contains three integers
Vi, Ui, and Wi (1≤Vi, Ui, Wi≤10000), separated by spaces, denoting the speed of i-th
contestant in each section.
Output
For every contestant, write to the output file one line, that contains the word “Yes”
if the judge could choose the lengths of the sections in such a way that this par-
ticular contestant would win (i.e., she is the only one who would come first), or the
word “No” if this is impossible.
9 Yes
10 2 6 Yes
10 7 3 Yes
5 6 7 No
3 2 7 No
6 2 6 No
3 5 7 Yes
8 4 6 No
10 4 2 Yes
1 8 7
Source: ACM Northeastern Europe 2000
IDs for Online Judges: POJ 1755, ZOJ 2052, UVA 2218, URAL 1062
Practice for Computational Geometry ◾ 549
Hint
Suppose lengths of swimming, riding bicycle, and running are A, B and C (A, B,
C>0) respectively. If the i-th contestant can win, for any other contestant j (i≠ j),
A B C A B C
+ + < + + .
vi ui wi v j u j w j
A B C A B C
+ + < + +
vi ui wi v j u j w j
1 A 1 B 1 1 A 1 B 1
⇒ × + × + < × + × +
vi C ui C wi v j C u j C w j
1 1 A 1 1 B 1 1
⇒ − × + − × + − < 0.
v j vi C u j ui C w j wi
A B
If and are regarded as variables x and y respectively, the above formula is
C C
an inequality representing a half-plane. If the intersection of half-planes is a convex
polygon, then the i-th contestant can win. The algorithm is as follows:
For the i-th contestant (1≤i≤n), there are n+2 line equations (Ak x+Bky+Ck =0)
representing half-planes H1, H2, ..., Hn+2, where the first n−1 line equations repre-
(
sent that the i-th contestant defeats the j-th contestant: Ak = u1j − u1i − w1j − w1i , )
( )
Bk = v1j − v1i − w1j − w1i , C k = w1j − w1i , 1≤j≤n, j≠i, and 1≤k≤n−1; and the last three
line equations represent x=0 (An=1, Bn=0, Cn=0), y=0 (An+1=0, Bn+1=1, Cn+1=0), and
x+y=1 (An+2=−1, Bn+2=−1, Cn+2=1).
If the intersection of n+2 half-planes H1∩H2∩…∩Hn+2 is a convex polygon,
then the i-th contestant can win; else the i-th contestant can’t win.
as a point as well. Your program is given the corners of the hall (the vertices of
the polygon), and must check if there is a location for the scoreboard (a point
inside the polygon) such that the scoreboard can be viewed from any point on
the edges of the polygon.
Input
The first number in the input line, T, is the number of test cases. Each test case is
specified on a single line of input in the form n x1 y1 x 2 y2 ... xn yn where n (3≤n≤100)
is the number of vertices in the polygon, and the pair of integers xi yi sequence speci-
fies the vertices of the polygon sorted in order.
Output
The output contains T lines, each corresponding to an input test case in that order.
The output line contains either “YES” or “NO” depending on whether the score-
board can be placed inside the hall conforming to the problem conditions.
2 YES
4 0 0 0 1 1 1 1 0 NO
8 0 0 0 2 1 2 1 1 2 1 2 2 3 2 3 0
Source: ACM Tehran 2006 Preliminary
ID for Online Judge: POJ 3335
Hint
The hall is in the form of a simple polygon. The rotating scoreboard is placed some-
where in the hall such that a spectator sitting anywhere on the boundary of the hall
can view the scoreboard. That is, the rotating scoreboard is placed at the core for the
simple polygon. This problem is similar to 8.3.2.1 Art Gallery.
Figure 8.57
Input
The input is a sequence of datasets followed by a line containing a single zero. Each
dataset specifies a polygon, and is formatted as follows:
n
x1 y1
x 2 y2
…
xn yn
The first line is the number of vertices, n, which satisfies 4≤n≤50. Subsequent
n lines are the x- and y-coordinates of the n vertices. They are integers and satisfy
0 ≤xi≤10000 and 0 ≤yi≤10000 (i=1, …, n). Line segments (xi, yi)–(xi + 1, yi + 1)
(i=1, …, n−1) and the line segment (xn, yn)–(x1, y1) form the border of the polygon
in the counterclockwise order. That is, these line segments see the inside of the
polygon in the left of their directions.
552 ◾ Algorithm Design Practice for Collegiate Programming
You may assume that the polygon is simple, that is, its border never crosses or
touches itself. You may also assume that no three edges of the polygon meet at a
single point even when they are infinitely extended.
Output
For each dataset, output “1” if the polygon is star-shaped and “0” otherwise. Each
number must be in a separate line, and the line should not contain any other
characters.
6 1
66 13 0
96 61
76 98
13 94
4 0
45 68
8
27 21
55 14
93 12
56 95
15 48
38 46
51 65
64 31
0
Source: ACM Japan 2006
IDs for Online Judges: POJ 3130, ZOJ 2820, UVA 3617
Hint
Based on the definition of a star shape (a planar shape F is star-shaped if and only
if there exists a point C∈F such that, for any point P∈F, the line segment CP is
contained in F. Such a point C is called a center of F.). If a planar shape F is star-
shaped, then there must exist a core for F, and centers of F constitute the core; and
if there is no core, then F isn’t star-shaped. The intersection of half-planes is used to
calculate the core for a planar shape F. The solution is the same as 8.5.23 Rotating
Scoreboard.
Practice for Computational Geometry ◾ 553
Input
The input contains several floor descriptions. Every description starts with the
number n of vertices that bound the floor (4≤n≤100). The next n lines contain two
integers each, the x and y coordinates for the n vertices, given in clockwise order.
All vertices will be distinct and at corners of the polygon. Thus the edges alternate
between horizontal and vertical.
A zero value for n indicates the end of the input.
Output
For every test case, first output a line with the number of the floor, as shown in the
sample output. Then print a line stating “Surveillance is possible.” if there exists
Invisible
Figure 8.58
554 ◾ Algorithm Design Practice for Collegiate Programming
a position from which the entire floor can be observed, or print “Surveillance is
impossible.” if there is no such position.
Print a blank line after each test case.
4 Floor #1
0 0 Surveillance is possible.
0 1
1 1 Floor #2
1 0 Surveillance is impossible.
8
0 0
0 2
1 2
1 1
2 1
2 2
3 2
3 0
0
Source: ACM Southwestern European Regional Contest 1997
IDs for Online Judges: POJ 1474, ZOJ 1248, UVA 588
Hint
The only requirement for installing the camera is that every part of the room must
be visible from the camera. A ground plan is a polygon. If there exists a core for the
polygon, the camera can be installed in the core. The intersection of half-planes is
used to determine whether there exists a core for the polygon. The solution is the
same as 8.5.23 Rotating Scoreboard.
distance from the sea. In order to simplify the problem, we only consider maps
representable by convex polygons.
Input
The input consists of multiple datasets. Each dataset represents a map of an island,
which is a convex polygon. The format of a dataset is as follows:
n
x1 y1
⋮
xn yn
Every input item in a dataset is a non-negative integer. Two input items in a line
are separated by a space. n in the first line is the number of vertices of the polygon,
satisfying 3≤n≤100. Subsequent n lines are the x- and y-coordinates of the n verti-
ces. Line segments (xi, yi)–(xi+1, yi+1) (1≤i≤n−1) and the line segment (xn, yn)–(x1, y1)
form the border of the polygon in counterclockwise order. That is, these line seg-
ments see the inside of the polygon in the left of their directions. All coordinate
values are between 0 and 10000, inclusive.
You can assume that the polygon is simple, that is, its border never crosses or
touches itself. As stated above, the given polygon is always a convex one.
The last dataset is followed by a line containing a single zero.
Output
For each dataset in the input, one line containing the distance of the most distant
point from the sea should be output. An output line should not contain extra char-
acters such as spaces. The answer should not have an error greater than 0.00001
(10 −5). You may output any number of digits after the decimal point, provided that
the above accuracy condition is satisfied.
4 5000.000000
0 0 494.233641
10000 0 34.542948
10000 10000 0.353553
0 10000
3
0 0
10000 0
(Continued)
556 ◾ Algorithm Design Practice for Collegiate Programming
7000 1000
6
0 40
100 20
250 40
250 70
100 90
0 70
3
0 0
10000 10000
5000 5001
0
Source: ACM Japan 2007
IDs for Online Judges: POJ 3525, UVA 3890
Hint
Given a convex polygon (a map of an island), the problem requires you to find the
most distant point from the sides of the convex polygon, and report its distance
from sides, that is, the radius for the largest circle in the convex polygon.
The problem can be solved by the intersection of half-planes and dichotomy.
The algorithm is as follows:
Suppose line equations for n sides for the convex polygon are Ai x+Biy+Ci=0,
where Ai=yi+1−yi, Bi=xi+1−xi, and Ci=xi×yi+1−xi+1×yi, (1≤i≤n−1); and An=y1−yn,
Bn=x1−xn, and Cn=xn×y1−x1×yn.
Suppose the interval for the distance is [l, r]. Initially the interval is [0, 20000].
Dichotomy is used to calculate the most distance. Suppose mid = l +2r . Sides for
the convex polygon are pushed inward mid: For each line equation for a side for
the convex polygon, Ai x+Biy+Ci=0, Ai and Bi aren’t changed, and Ci is decreased
mid × Ai2 + Bi2 .
If there is an intersection of n half-planes, then the circle with radius mid can be
in the convex polygon, and the right subinterval is searched (l=mid); else the left sub-
interval is searched (r=mid). Repeat the above process until l=r. And l is the distance.
Figure 8.59
Input
In the first line, there’s a single non-negative integer N (N≤20000), denoting the
number of basket chairs. Each of the following lines contains four floating numbers
x1, y1, x 2, y2, which means there’s a basket chair on the line segment of (x1, y1)–(x 2, y2),
and facing to its LEFT (that a point (x, y) is at the LEFT side of this segment means
that (x–x1)×(y–y2)–(x–x 2)×(y–y1)≥0).
Output
Output a single floating number, rounded to one digit after the decimal point. This
is the maximal area of the stage.
558 ◾ Algorithm Design Practice for Collegiate Programming
3 54166666.7
10000 10000 0 5000
10000 5000 5000 10000
0 5000 5000 0
Source: POJ Monthly, Zeyuan Zhu
ID for Online Judge: POJ 2451
Hint
Lines on which n basket chairs are can be regarded as n half-planes. There are four
additional half-planes: x =0, x =10000, y=0, and y=10000. The intersection of n+4
half-planes constitute a polygon. The polygon is the stage. And the audience in
every position of the sides of the polygon can see the stage.
Figure 8.60
Practice for Computational Geometry ◾ 559
Input
The input file will contain records of data for several regions. The first line of each
record contains the number (an integer) of traps for that region. Subsequent lines
of the record contain two real numbers that are the x- and y-coordinates of the
trap locations. Data within a single record will not be duplicated. End of input is
indicated by a region with 0 traps.
Output
Output for a single region is displayed on at least three lines:
First line: The number of the region. (The first record corresponds to Region
#1, the second to Region #2, etc.)
Next line(s): A listing of all the points that appear on the perimeter of the
region. The points must be identified in the standard form
“(x-coordinate, y-coordinate)” rounded to a single decimal place.
The starting point for this listing is irrelevant, but the listing must
be oriented clockwise and begin and end with the same point. For
collinear points, any order which describes the minimum length
perimeter is acceptable.
Last line: The length of the perimeter of the region rounded to 2 decimal places.
One blank line must separate the output from consecutive input records.
3 Region #1:
1 2 (1.0,2.0)−(4.0,10.0)−(5.0,12.3)−(1.0,2.0)
4 10 Perimeter length = 22.10
5 12.3
6 Region #2:
0 0 (0.0,0.0)−(3.0,4.5)−(6.0,2.1)−(2.0,−3.2)−(0.0,0.0)
1 1 Perimeter length = 19.66
3.1 1.3
3 4.5 Region #3:
6 2.1 (0.0,0.0)−(2.0,2.0)−(4.0,1.5)−(5.0,0.0)−(2.5,−1.5)−(0.0,0.0)
2 -3.2 Perimeter length = 12.52
7
1 0.5
5 0
4 1.5
3 -0.2
(Continued)
560 ◾ Algorithm Design Practice for Collegiate Programming
2.5 -1.5
0 0
2 2
0
Source: ACM World Finals 1992
ID for Online Judge: UVA 218
Hint
Given n points in the plane, the smallest perimeter polygon containing all of the
given points is required to be found. It is a straightforward planar Convex Hull
problem. An O(nlogn) solution can solve it.
Input
The input consists of several test cases.
Each test case begins with two integers N, M. (3≤N, M≤10000)
Each of the next N lines contains a pair of coordinates, which describes the
position of a vertex in one convex polygon.
Figure 8.61
Practice for Computational Geometry ◾ 561
Each of the next M lines contains a pair of coordinates, which describes the
position of a vertex in the other convex polygon.
A line with N = M = 0 indicates the end of input.
The coordinates are within the range [−10000, 10000].
Output
For each test case, output the minimal distance. An error within 0.001 is acceptable.
44 1.00000
0.00000 0.00000
0.00000 1.00000
1.00000 1.00000
1.00000 0.00000
2.00000 0.00000
2.00000 1.00000
3.00000 1.00000
3.00000 0.00000
0 0
Source: POJ Founder Monthly Contest, 2008.06.29, Lei Tao
ID for Online Judge: POJ 3608
Hint
Suppose the first convex polygon is p1, and the second convex polygon is p2. The
problem requires you to calculate the minimal distance between the two convex
polygons.
Because p1 and p2 are separated, the algorithm for rotating calipers is used to
solve the problem.
Container
Wasted
Tile
space
Figure 8.62
The UTP authorities are interested to know the percentage of wasted space for
a given tile.
Input
The input file consists of several data blocks. Each data block describes one tile.
The first line of a data block contains an integer N (3≤N≤100) indicating the
number of corner points of the tile. Each of the next N lines contains two integers
giving the (x, y) coordinates of a corner point (determined using a suitable origin
and orientation of the axes) where 0≤x, y≤1000. Starting from the first point given
in the input, the corner points occur in the same order on the boundary of the tile
as they appear in the input. No three consecutive points are colinear.
The input file terminates with a value of 0 for N.
Output
For each tile in the input, output the percentage of wasted space rounded to two
digits after the decimal point. Each output must be on a separate line. Print a blank
line after each output block.
5 Tile #1
0 0 Wasted Space = 25.00 %
2 0
2 2 Tile #2
1 1 Wasted Space = 0.00 %
0 2
5
0 0
0 2
Practice for Computational Geometry ◾ 563
1 3
2 2
2 0
0
Source: BUET/UVA Occidental (WF Warmup) Contest 1, 2001
ID for Online Judge: UVA 10065
Hint
The floor of the container is a convex polygon, and under this constraint it has the
minimum possible space inside to hold the tile it is built for. It is a straightforward
Convex Hull problem.
The convex hull algorithm (choose one of them) is applied to calculate the area
of the convex hull. Then the area that the points cover is calculated. Finally, the
percentage of wasted space is calculated.
8.5.31 Nails
Arash is tired of working hard, so he wants to surround some nails on the wall of
his room by a rubber ribbon to make fun of it! Now, he wants to know what will be
the final length of the rubber ribbon after surrounding the nails. You must assume
that the radius of nails and rubber ribbon is negligible.
Input
The first line of input gives the number of cases, N. N test cases will follow. Each
test case starts with a line containing two integers, the initial length of rubber rib-
bon and the number of nails 0<n≤100, respectively. Each of the next n lines con-
tains two integers denoting the location of a nail. There will be a blank line after
each test case.
Output
Your program must output the final length of rubber ribbon precise to five decimal
digits.
564 ◾ Algorithm Design Practice for Collegiate Programming
2 4.00000
2 4 5.00000
0 0
0 1
1 0
1 1
5 4
0 0
0 1
1 0
1 1
Source: Annual Contest 2006 Qualification Round
ID for Online Judge: UVA 11096
Hint
The problem requires you to find the length of an elastic band around a set of nails
on a 2-D surface. You need to find the convex hull and calculate its perimeter.
The initial length of the elastic is given; remember that it might be longer than
the convex perimeter. Also remember to output in the correct format (to five deci-
mal places).
E E
F F
D B D
A A
C C
B
(a) Convex (b) Not convex
Figure 8.63
To describe the second property, suppose you “take a trip” around the polygon:
start at (0, 0), visit all other vertices exactly once, and arrive at (0, 0). As you visit
each vertex (other than (0, 0)), draw the diagonal that connects the current vertex
with (0, 0), and calculate the slope of this diagonal. Then, within each quadrant,
the slopes of these diagonals will form a decreasing or increasing sequence of num-
bers, i.e., they will be sorted. Figure 8.65 illustrates this point.
Input
The input lists the vertices of a closed convex polygon in the plane. The number
of lines in the input will be at least three but no more than 50. Each line contains
the x and y coordinates of one vertex. Each x and y coordinate is an integer in the
range −999..999. The vertex on the first line of the input file will be the origin, i.e.,
(60, 30)
(80, 20)
(90, 10)
(0, 0)
(90, –20)
(–30, –40)
(–30, –50) (70, –50)
Figure 8.64
566 ◾ Algorithm Design Practice for Collegiate Programming
Slope = 0.5
Slope = 0.25
Slope = 0.111
Slope = –0.222
Slope = 1.333
Slope = –0.714
Slope = –1.2
Slope = 1.667
Slope = 6
Figure 8.65
x=0 and y=0. Otherwise, the vertices may be in a scrambled order. Except for the
origin, no vertex will be on the x-axis or the y-axis. No three vertices are colinear.
Output
The output lists the vertices of the given polygon, one vertex per line. Each vertex
from the input appears exactly once in the output. The origin (0,0) is the vertex on
the first line of the output. The order of vertices in the output will determine a trip
taken along the polygon’s border, in the counterclockwise direction. The output
format for each vertex is (x, y) as shown below.
0 0 (0,0)
70 −50 (−30,−40)
60 30 (−30,−50)
−30, −50 (−10,−60)
80 20 (50,−60)
50 −60 (70,−50)
90 −20 (90,−20)
−30 −40 (90,10)
−10, −60 (80,20)
90 10 (60,30)
Source: ACM Rocky Mountain 2004
IDs for Online Judges: POJ 2007, ZOJ 2352, UVA 3052
Practice for Computational Geometry ◾ 567
Hint
The problem requires you to “take a trip” around the polygon: starting at (0, 0),
visiting all other vertices exactly once in the counterclockwise direction, and finally
arriving at (0, 0).
The problem is solved by sorting polar angles. A cross product is used to sort
polar angles. The program segments are as follows.
Input
The first line of the input file contains a single integer t (1≤t≤10), the number of test
cases, followed by the input data for each test case. The first line of each test case
contains an integer n (1≤n≤1000), which is the number of remaining spikes. Next,
there are n lines, one line per spike, each containing a pair of integers, which are the
x and y coordinates of the spike.
Output
There should be one output line per test case containing “YES” or “NO” depending
on whether the boundary of the farm can be uniquely determined from the input.
568 ◾ Algorithm Design Practice for Collegiate Programming
1 NO
6
0 0
1 2
3 4
2 0
2 4
5 0
Source: ACM Tehran 2002 Preliminary
ID for Online Judge: POJ 1228, ZOJ 1377
Hint
Given a set of points, these points are on the boundary of the convex polygon-
shaped farm. The problem requires you to determine whether the convex hull is a
stable convex hull. A convex hull isn’t stable if a larger convex polygon can be gotten
by adding some points, and the larger convex polygon’ sides contains the given set
of points. Therefore, if a convex hull is stable, then there are at least three points
on each side. If there are only two points on a side, a larger convex polygon can be
gotten by adding a point.
The algorithm is as follows. First, a convex hull is calculated for the set of spikes.
If the number of spikes is less than six, the boundary of the farm can’t be deter-
mined. Second, if there are at least three spikes on each side for the convex hull,
the boundary of the farm can be determined; else the boundary of the farm can’t
be determined.
stayed there until he had found the best possible solution to the problem. The fence
was then built and everyone lived happily ever after.
You are to write a program that solves the problem the wizard faced.
Input
The input contains several test cases, each of which describes a hypothetical for-
est. Each test case begins with a line containing a single integer n, 2≤n≤15, the
number of trees in the forest. The trees are identified by consecutive integers 1 to
n. Each of the subsequent n lines contains four integers xi, yi, vi, li that describe a
single tree. (xi, yi) is the position of the tree in the plane, vi is its value, and li is the
length of fence that can be built using the wood of the tree. vi and li are between
0 and 10,000.
The input ends with an empty test case (n=0).
Output
For each test case, compute a subset of the trees such that, using the wood from
that subset, the remaining trees can be enclosed in a single fence. Find the subset
with minimum value. If more than one such minimum-value subset exists, choose
the one with the smallest number of trees. For simplicity, regard the trees as having
zero diameter.
Display, as shown below, the test case numbers (1, 2, ...), the identity of each tree
to be cut, and the length of the excess fencing (accurate to two fractional digits).
Display a blank line between test cases.
6 Forest 1
0 0 8 3 Cut these trees: 2 4 5
1 4 3 2 Extra wood: 3.16
2 1 7 1
4 1 2 3 Forest 2
3 5 4 6 Cut these trees: 2
2 3 9 8 Extra wood: 15.00
3
3 0 10 2
5 5 20 25
7 −3 30 32
0
Source: ACM World Finals 1999
IDs for Online Judges: POJ 1873, UVA 811
570 ◾ Algorithm Design Practice for Collegiate Programming
Hint
The problem requires you to compute such a subset of the trees that, using the wood
from that subset, the remaining trees can be enclosed in a single fence; and the
subset must be with minimum value.
The fence built around the remaining trees is the convex hull containing all
remaining trees. The search with state compression is used to find which trees
will be cut, and which trees will remain. A binary number i with n digits is
used to represent n trees, 0≤i≤2n −1, where a digit being 0 means that the cor-
responding tree will be cut, and a digit being 1 means that the corresponding
tree will remain. Suppose Pk is the k-th tree’s position, 1≤k≤n; pt[] is used to
store remaining trees (i.e., sequence numbers for digits being 1 in i+1), and the
number of remaining trees is tt; sums of cut trees’ values and lengths are valu
and len respectively; the set of points of the convex hull for pt[] is h, and the
perimeter for the convex hull is ll; ans is the sum of the current cut trees’ values,
anst is the number of cut trees, ansi is the state for trees, and lef is the length of
the excess fencing.
The algorithm is as follows:
All states i for trees are enumerated, (0≤i≤2n−1):
1. In state i, remaining trees are stored in pt[]. Then the sums of cut trees’ values
and lengths as valu and len are calculated;
2. The convex hull for remaining trees pt[] and the perimeter for the convex hull
ll is calculated;
3. If the sum of the cut trees’ lengths can enclose remaining trees (ll≤len), the
current best solution should be adjusted:
Figure 8.66
Unfortunately, this seems hard to fulfill, since Gloomwood Park has many opaque
obstacles, such as large trees, rocks, and so on.
Because the staff of the Zeron company is large, Lilith has a rather intricate prob-
lem to solve: finding a location to hold them all. Therefore, some of her friends help
her to draw a map of the whereabouts of the largest obstacles. To mark out the place,
she will use a ribbon stretched around the obstacles on the circumference of the cho-
sen region. The opaque obstacles should be thought of as points of zero extension.
Figure 8.66 shows the Gloomwood Park from above with black dots represent-
ing obstacles. The picnic area is the region whose circumference is dashed.
Input
The first line of the input contains a single positive integer n, specifying the number
of test scenarios to follow. Each test scenario begins with a line containing an inte-
ger m, the number of obstacles in the park (2<m<100). The next line contains the
coordinates of the m obstacles, in the order x1 y1 x 2 y2 x3 y3 . . . .. All coordinates are
integers in the range [0, 1000]. Each scenario has at least three obstacles that are not
on a straight line, and no two obstacles have the same coordinates.
Output
For each test scenario, one line of output should be generated, stating the area
with one decimal of the largest convex polygon having obstacles as corners, but no
enclosed obstacles.
1 129.0
11
3 3 8 4 12 2 22 3 23 5 24 7 27 12 18 12 13 13 6 10 9 6
Source: ACM Northwestern Europe 2002
IDs for Online Judges: POJ 1259, ZOJ 1562, UVA 2674
572 ◾ Algorithm Design Practice for Collegiate Programming
Hint
Given a set of vertices, the problem requires you to calculate the largest convex
polygon whose vertices are a subset of the set of vertices, and in which there is no
vertex. Suppose the given set of vertices is {pi|0≤i≤n−1}; and f [j][k] is the area of the
largest convex polygon having vertex k and vertex j.
Each vertex pi in the convex hull is enumerated:
For the convex hull, vertex pi is as the bottom vertex, and tp[0…m−1] is the
sequence for vertices in counterclockwise direction.
In tp[] all intervals [k, j] (0≤k≤j−1, 1≤j≤m) are enumerated:
1. If pk+1… p j−1 aren’t on the inside of the convex hull having vertex pi, ver-
tex tp[k] and tp[j] (((mul(tp[k], tp[j], tp[l])≤0)||(mul(p[i], tp[k], tp[l])=0)),
pi tpk ^ pi tp j
k+1≤l≤j−1), then the area f [ j ][k ] = is calculated.
2
2. If pk+1… p j−1 are on the right of tpk tp j and tpl, tpk, and tpj are sorted in coun-
terclockwise direction, then neither the convex polygon having vertices
pi tp j ^ pi tpk
pi, tpk, and tpj its area is s1 = nor the convex polygon hav-
2
ing vertices pi, tpk, and tpl (its area is s2=f [k][l]) contain pk+1… p j−1 , then
f [j][k]=max{f [j][k], s1+s2}.
8.5.36 Triangle
Given n distinct points on a plane, your task is to find the triangle that has the
maximum area, whose vertices are from the given points.
Input
The input consists of several test cases. The first line of each test case con-
tains an integer n, indicating the number of points on the plane. Each of the
following n lines contains two integers xi and yi, indicating the i-th points.
The last line of the input is an integer −1, indicating the end of input, which
should not be processed. You may assume that 1≤n≤50000 and −10 4≤xi,yi ≤10 4
for all i=1 . . . n.
Practice for Computational Geometry ◾ 573
Output
For each test case, print a line containing the maximum area, which contains two
digits after the decimal point. You may assume that there is always an answer which
is greater than zero.
3 0.50
3 4 27.00
2 6
2 7
5
2 6
3 9
2 0
8 0
6 5
−1
Source: ACM Shanghai 2004 Preliminary
IDs for Online Judges: POJ 2079, ZOJ 2419
Hint
First, the set of n vertices for the convex hull based on the given set of points are cal-
culated { p0 , p1 , …, pn−1 } . Obviously, vertices for the triangle with the maximum
area are vertices for the convex hull.
Each vertex pi is enumerated, 0≤i≤n−1:
The other two vertices pk and pj for the triangle are calculated as follows:.
Initially k is (i+1)%n;
The length _j of i−j is enumerated, and j is calculated (for (int _j=1, j=(_j+i)%n;
_j<n−1; _j++, j=(_j+i)% n ))), and pk is calculated based on pi and pj: k is calculated
by “rotating” in counterclockwise direction until p j pi ^ p( k +1)% n pk ≤ 0. The area
pi p j ^ pi pk
for the triangle whose vertices pi, pj, and pk S∆ pi p j pk = . The maximum
2
area for the triangle is adjusted ans = max{ans , S∆ pi p j pk }.
Finally, ans is the maximum area for the triangle.
574 ◾ Algorithm Design Practice for Collegiate Programming
Input
The input file may contain multiple test cases. Each test case begins with a line
containing a positive integer n (<1001) indicating the number of points in this test
case. Then follow n lines, each containing two real numbers giving respectively the
x- and y-coordinates of a point. The input terminates with a test case containing a
value 0 for n which must not be processed.
Output
For each test case in the input, print a line containing the area of the smallest
bounding rectangle rounded to the fourth digit after the decimal point.
3 80.0000
−3.000 5.000 100.0000
7.000 9.000
17.000 5.000
4
10.000 10.000
10.000 20.000
20.000 20.000
20.000 10.000
0
Source: 2001 Regionals Warmup Contest
ID for Online Judge: UVA 10173
Hint
The problem requires you to calculate the area of the smallest rectangle contain-
ing all given points. First, the convex hull containing all given points is calculated.
Then the method of rotating calipers is used to calculate the area of the smallest
rectangle containing all given points:
The rightmost point and the leftmost point are calculated to guarantee the
minimal width covering all points;
Practice for Computational Geometry ◾ 575
The lowest point and the highest point are calculated to guarantee the minimal
height covering all points;
The area of the smallest rectangle containing all given points is calculated
through adjustment in the procedure of rotating calipers.
Input
The first line of the input consists of a positive integer n, which is the number of
datasets that follow. Each dataset consists of three lines; each line contains two
floating-point values which represent the (two-dimensional) coordinate of one ver-
tex of a triangle. So, there are a total of (n×3)+1 lines of input. Note: All input
D E
M
L
A B
O
J
G
C
F N
Figure 8.67
576 ◾ Algorithm Design Practice for Collegiate Programming
triangles will be strongly non-degenerate in that no vertex will be within one unit
of the line through the other two vertices.
Output
For each dataset, you must print out the coordinates of the Exocenter of the input
triangle correct to four decimal places.
2 9.0000 3.7500
0.0 0.0 −48.0400 23.3600
9.0 12.0
14.0 0.0
3.0 4.0
13.0 19.0
2.0 −10.0
Source: ACM Greater New York 2003
IDs for Online Judges: POJ 1673, ZOJ 1821, UVA 2873
Hint
The problem is solved based on the definition of exocenters of triangles.
Let p1a be a vertical line through p1 for p2 p3 , and the intersection point for
p1a and p2 p3 is a. And let p2b
be a vertical line through p2 for p1 p3 , and the
intersection point for p2b and p1 p3 is b. The intersection point o for p1 pa and
p2 pb (the orthocenter of a triangle) is the exocenter of the triangle (Figure 8.68).
p3 b p1
o
a
p2
Figure 8.68
Practice for Computational Geometry ◾ 577
A
P
O
N
H B
C
Figure 8.69
8.5.39 Picture
A number of rectangular posters, photographs, and other pictures of the same shape
are pasted on a wall. Their sides are all vertical or horizontal. Each rectangle can be
partially or totally covered by the others. The length of the boundary of the union
of all rectangles is called the perimeter.
Write a program to calculate the perimeter. An example with seven rectangles
is shown in Figure 8.70.
The corresponding boundary is the whole set of line segments drawn in
Figure 8.71.
The vertices of all rectangles have integer coordinates.
Input
Your program is to read from standard input. The first line contains the number of
rectangles pasted on the wall. In each of the subsequent lines, one can find the integer
Figure 8.70
578 ◾ Algorithm Design Practice for Collegiate Programming
Figure 8.71
coordinates of the lower-left vertex and the upper-right vertex of each rectangle. The
values of those coordinates are given as ordered pairs consisting of an x-coordinate
followed by a y-coordinate. 0≤number of rectangles<5000. All coordinates are in
the range [−10000,10000], and any existing rectangle has a positive area.
Output
Your program is to write to standard output. The output must contain a single
line with a non-negative integer which corresponds to the perimeter for the input
rectangles.
7 228
−15 0 5 10
−5 8 20 25
15 −4 24 14
0 −6 16 4
2 15 10 22
30 10 36 20
34 0 40 16
Source: IOI 1998
ID for Online Judge: POJ 1177
Hint
The problem is solved by the Sweep Line Algorithm.
First, discretization is on the X-axis. The plane is divided into several horizontal
strips by sweeping on the Y-axis. A segment tree is used to accumulate lengths of
these horizontal strips s1.
Practice for Computational Geometry ◾ 579
Second, discretization is on the Y-axis. The plane is divided into several vertical
strips by sweeping on the X-axis. A segment tree is used to accumulate lengths of
these vertical strips s2.
Obviously, the result is s1+s2.
reads the description of cisterns and the volume of water, computes the level to
which the cisterns will be filled with the given amount of water, writes the result.
8m
1m
2m
2m
V = 78 m3 4m
5m
1m
6m
7m
5m
1m
19 m
8m
17 m
15 m
11 m
5m
Figure 8.72
580 ◾ Algorithm Design Practice for Collegiate Programming
Input
The first line of the input contains the number of data sets k, 1≤k≤30. The data sets
follow.
The first line of each data set contains one integer n, the number of cisterns,
1≤n≤50000. Each of the following n lines consists of four non-negative inte-
gers, separated by single spaces: b, h, w, d—the base level of the cistern, and its
height, width, and depth in meters, respectively. The integers satisfy 0≤b≤106 and
1≤h×w×d≤40000. The last line of the data set contains an integer V—the vol-
ume of water in cubic meters to be injected into the network. Integer V satisfies
1≤V≤2×109.
Output
The output should consist of exactly d lines, one line for each data set.
Line i, 1≤i≤d, should contain the level that the water will reach, in meters,
rounded up to two fractional digits, or the word “OVERFLOW”, if the volume of
water exceeds the total capacity of the cisterns.
3 1.00
2 OVERFLOW
0 1 1 1 17.00
2 1 1 1
1
4
11 7 5 1
15 6 2 2
5 8 5 1
19 4 8 1
132
4
11 7 5 1
15 6 2 2
5 8 5 1
19 4 8 1
78
Note: Descriptions for Problem F Fill the Cisterns! in ACM Central
Europe 2001 and Problem D Water Shortage are similar.
Source: ACM Central Europe 2001, ACM Southwestern Europe 2001
IDs for Online Judges: POJ 1434, ZOJ 1389, UVA 2428
Practice for Computational Geometry ◾ 581
Hint
For the i-th cistern, its base level, height, width, and depth are bi, hi, wi, and di,
respectively, 0≤i≤n−1.
First, we need to calculate how much water is in the n cisterns if the height of
the water level is m. Suppose the amount of water is vm.
For the i-th cistern (0≤i≤n−1), if its base level bi ≤ the water level m, then the
water level for the i-th cistern tmp=min{ m−bi, hi}, and vm+=tmp×wi×di.
Dichotomy is used to calculate the level that the water will reach. Suppose the
interval for the water level is [l, r]. Initially, the interval for the water level is [0,
∞]. Let mid=(l+r)/2, and calculate the amount of filled water vmid that makes the
water level to be mid. If vmid≥V (the volume of water in cubic meters to be injected
into the network), then the left subinterval is searched; else the right subinterval
is searched. Repeat the procedure until the search ends and l is the level that the
water will reach.
The total area of all simple polygons constructed by these rectangles is 18.
Input
The input consists of multiple test cases. A line of four −1’s separates each test
case. An extra line of four −1’s marks the end of the input. In each test case, the
582 ◾ Algorithm Design Practice for Collegiate Programming
rectangles are given one by one in a line. In each line for a rectangle, four non-
negative integers are given. The first two are the x and y coordinates of the lower-left
corner. The next two are the x and y coordinates of the upper-right corner.
Output
For each test case, output the total area of all simple polygons in a line.
0 0 4 4 18
1 1 5 2 10
1 1 2 5
−1 −1 −1 −1
0 0 2 2
1 1 3 3
2 2 4 4
−1 −1 −1 −1
−1 −1 −1 −1
Source: ACM Taiwan 2001
IDs for Online Judges: POJ 1389, UVA 2447
Hint
First, the convex hull containing all rectangles’ points are calculated. Then
the method of rotating calipers is used to calculate the total area of all simple
polygons.
8.5.42 Squares
A square is a four-sided polygon whose sides have equal length and adjacent sides
form 90-degree angles. It is also a polygon such that rotating about its center by
90 degrees gives the same polygon. It is not the only polygon with the latter prop-
erty, however, as a regular octagon also has this property.
So we all know what a square looks like, but can we find all possible squares that
can be formed from a set of stars in a night sky? To make the problem easier, we will
assume that the night sky is a two-dimensional plane, and each star is specified by
its x and y coordinates.
Practice for Computational Geometry ◾ 583
Input
The input consists of a number of test cases. Each test case starts with the integer
n (1≤n≤1000) indicating the number of points to follow. Each of the next n lines
specify the x and y coordinates (two integers) of each point. You may assume that
the points are distinct and the magnitudes of the coordinates are less than 20000.
The input is terminated when n=0.
Output
For each test case, print on a line the number of squares one can form from the
given stars.
4 1
1 0 6
0 1 1
1 1
0 0
9
0 0
1 0
2 0
0 2
1 2
2 2
0 1
1 1
2 1
4
−2 5
3 7
0 0
5 2
0
Source: ACM Rocky Mountain 2004
IDs for Online Judges: POJ 2002, ZOJ 2347, UVA 3047
Hint
Suppose m is the container storing coordinates for all given stars; where the i-th
star’s coordinate is (ai, bi), 0≤i≤n−1. Initially ans=0.
584 ◾ Algorithm Design Practice for Collegiate Programming
After the i-th star’s coordinate (ai, bi) is input, the first i−1 stars’ coordinates (aj,
bj), 0≤j≤i−1, are enumerated:
If (ai+bi−bj, bi+aj−ai) and (bi+aj−bj, aj+bj−ai) are in the container m, then ans++;
If (ai+bj−bi, bi−aj+ai) and (aj+bj−bi, ai+bj−aj) are in the container m, then ans++;
ans
Finally, the number of squares one can form from the given stars is .
2
Input
There are no more than 25 test cases. Each case starts with a line containing an
integer N>=4, which is the number of instructions in the test case. The following
N pairs of integers give the instructions and appear on a single line separated by
single spaces. The first pair is the first instruction that gives the coordinates of the
Practice for Computational Geometry ◾ 585
starting position. You may assume there are no more than 300 instructions in each
test case, and all the integer coordinates are in the range (−300, 300). The input is
terminated when N is 0.
Output
For each test case, there will be one output line in the format:
Hint
The problem is solved by Euler’s formula: for any convex polyhedron, the number
of vertices and faces together is exactly two more than the number of edges. That
is, V−E+F=2.
First, the number of vertices V is calculated. We calculate coordinates for inter-
section points, sort all points, and eliminate recurring points.
Then the number of edges E is calculated. Initially, E is the number of input
edges (N−1). Then, for each vertex v, if v is on a line segment and isn’t an endpoint
for the line segment, E++.
Finally, the number of faces F is calculated and output.
Figure 8.73
586 ◾ Algorithm Design Practice for Collegiate Programming
Input
The input consists of several test cases each describing a forest. The first line of each
description contains five integers, xmin, ymin, xmax, ymax, and n. The first four
numbers represent the minimal and maximal coordinates of the fence in the x- and
y-directions (xmin<xmax, ymin<ymax). The fence is rectangular and its sides are
parallel to the coordinate axes. The fifth number n represents the number of trees
in the forest (1≤n≤100).
The next n lines describe the positions and dimensions of the n trees. Each
line contains four integers, xi, yi, di, and hi, representing the position of the
Height
Space occupied
Circular base: by tree after cutting
the original
position of
the tree
Figure 8.74
Practice for Computational Geometry ◾ 587
tree’s center (xi, yi), its base diameter di, and its height hi. No tree bases touch
each other, and all the trees are entirely inside the fence, not touching the fence
at all.
The input is terminated by a test case with xmin=ymin=xmax =ymax =n=0. This test
case should not be processed.
Output
For each test case, first print its number. Then print the maximum number of trees
that can be cut down, one after another, such that no fallen tree touches any other
tree or the fence. Follow the format in the sample output given below. Print a blank
line after each test case.
0 0 10 10 3 Forest 1
3 3 2 10 2 tree(s) can be cut
5 5 3 1
2 8 3 9
0 0 0 0 0
Source: ACM World Finals 2001
ID for Online Judge: UVA 2235
Hint
The polar angle for the central axis of a rectangle is used to represent the state that
a tree is cut down, as shown in Figure 8.75.
Figure 8.75
588 ◾ Algorithm Design Practice for Collegiate Programming
di
hi
ri ri
bi = tan–1 ( h )
i
Figure 8.76
Other trees or the fence may prevent a tree from falling. Because the number
of trees in the forest n≤100, each tree is enumerated. We calculate the range for the
polar angle that the tree can’t be cut down.
In Figure 8.76, for the i-th tree, its radius of the original base of the tree is ri,
the length of its central axis is hi, the length for the line segment from the centre
of the circle to the another endpoint for the rectangle is di, and the included angle
for the line segment and its central axis is bi. States that trees or the fence prevent a
tree from falling are as follows.
There are two states that the fence can prevent a tree from falling.
Case 1: The distance between the center of a circle and the fence is in [0, hi].
The range for the included angle for two dotted lines (the polar angle for the
(
central axis of a rectangle) is mid − cos −1 dist( ) )
di
(
+ bi , mid + cos −1 dist
di
( )
+ bi
)
(as shown in Figure 8.77), where the distance between the center of a circle and
the fence is dist, and the polar angle for the vertical line is mid.
Fence
dist
hi di hi
bi
Figure 8.77
Practice for Computational Geometry ◾ 589
Figure 8.78
Case 2: The distance between the center of a circle and the fence is [hi, di].
The rectangle (tree) can also be perpendicular to the fence. When the tree is
rotated, it can touch the fence (Figure 8.78). Then the polar angle for the central
axis of a rectangle is mid − cos −1 ( ) + b , mid + cos ( ) + b .
di
dist i
−1 di
dist i
For tree j, there are two cases that tree j prevents tree i fall.
Case 1: It is similar to the above Case 1 (Figure 8.79):
Suppose the distance between centers of two circles is dist, and the
polar angle for j with respect to i is mid. If the height of the tree exceeds
dist 2 + (ri + r j )2 , then hi = dist 2 + (ri + r j )2 . The range for the polar angle
for the central axis of a rectangle that will prevent the tree from falling is
( )
mid − cos −1 dist
di
( )
+ bi , mid + cos −1 dist
di
+ bi .
Case 2: It is similar to the above Case 2.
Figure 8.79
Chapter 9
591
592 ◾ Algorithm Design Practice for Collegiate Programming
Level 0 State A
1 2 1
1 1 3 2 3 3
3 2 1 1 3
1 1 2
1 1 1 1 1 1 2 1 2 2
Figure 9.1
1. Evaluating Function g(x): The cost from the initial state to the current state x;
2. Heuristic Function h(x): The estimated cost from the current state x to goal
states.
594 ◾ Algorithm Design Practice for Collegiate Programming
Therefore, if a state space is regarded as a graph, a state space tree can be regarded
as a problem for the shortest path.
9.1.1 Robot
The Robot Moving Institute is using a robot in their local store to transport dif-
ferent items. Of course, the robot should spend only the minimum time necessary
when traveling from one place in the store to another. The robot can move only
along a straight line (track). All tracks form a rectangular grid, as shown in Figure 9.2.
Neighboring tracks are one meter apart. The store is a rectangle N×M meters and
it is entirely covered by this grid. The distance of the track closest to the side of the
store is exactly one meter. The robot has a circular shape with diameter equal to
1.6 meters. The track goes through the center of the robot. The robot always faces
north, south, west, or east. The tracks are in the south-north and in the west-east
directions. The robot can move only in the direction it faces. The direction in which
it faces can be changed at each track crossing. Initially, the robot stands at a track
crossing. The obstacles in the store are formed from pieces occupying 1m×1m on
the ground. Each obstacle is within a 1×1 square formed by the tracks. The move-
ment of the robot is controlled by two commands—GO and TURN.
The GO command has one integer parameter n in {1, 2, 3}. After receiving this
command, the robot moves n meters in the direction it faces.
The TURN command has one parameter, which is either left or right. After
receiving this command, the robot changes its orientation by 90° in the direction
indicated by the parameter.
The execution of each command lasts one second.
Help researchers of RMI to write a program which will determine the minimal
time in which the robot can move from a given starting point to a given destination.
Figure 9.2 The circle is the Robot, the black squares are obstacles, and the
heavy lines are the path that the Robot moves through.
Practice for State Space Search ◾ 595
Input
The input consists of blocks of lines. The first line of each block contains two
integers M≤50 and N≤50, separated by one space. In each of the next M lines
there are N numbers one or zero separated by one space. One represents obstacles
and zero represents empty squares. (The tracks are between the squares.) The
block is terminated by a line containing four positive integers B1 B2 E1 E2, each
followed by one space and the word indicating the orientation of the robot at the
starting point. B1 and B2 are the coordinates of the square in the north-west cor-
ner of which the robot is placed (starting point). E1 and E2 are the coordinates
of square to the north-west corner of which the robot should move (destination
point). The orientation of the robot when it has reached the destination point
is not prescribed. We use (row, column)-type coordinates, i.e., the coordinates
of the upper left (the most north-west) square in the store are 0,0 and the lower
right (the most south-east) square are M−1, N−1. The orientation is given by the
words north or west or south or east. The last block contains only one line with
N=0 and M=0.
Output
The output contains one line for each block except the last block in the input. The
lines are in the order corresponding to the blocks in the input. The line contains
a minimal number of seconds in which the robot can reach the destination point
from the starting point. If there does not exist any path from the starting point to
the destination point, the line will contain −1.
9 10 12
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 1 0
0 0 0 1 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 1 0 0 0 0
0 0 0 1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 1 0
7 2 2 7 south
0 0
Source: ACM Central Europe 1996
IDs for Online Judges: POJ 1376, ZOJ 1310, UVA 314
596 ◾ Algorithm Design Practice for Collegiate Programming
Analysis
First, for a test case, in the area whose coordinate for the upper-left corner is (0, 0),
and the coordinate for the lower-right corner is (M−1, N-1), we find grids that the
Robot can’t move through. The Robot has a circular shape with diameter equal to
1.6 meter, and row 0, row M−1, column 0, and column N-1 are boundaries for the
Robot. Therefore, in the area whose coordinate for the upper-left corner is (1, 1),
and the coordinate for the lower-right corner is (M−2, N-2), if there is an obstacle
at (i, j), the Robot can’t move through (i−1, j), (i. j−1), and (i−1, j−1). That is, (i−1, j),
(i. j−1), and (i−1, j−1) should also be set as obstacles. See Figure 9.3.
State (x, y, s, step): The current coordinate (x, y) at which the Robot is, the
current orientation s that the Robot faces; and the number of commands that has
been executed is step.
A successor function move[ ][ ][ ]: After the Robot moves j meters in direc-
tion i, the horizontal increment is move[i][j][0] meters, the vertical increment is
move[i][j][1] meters, and the orientation is move[i][j][2]. That is, the Robot moves
from (x, y), and moves j meters in direction i, then the coordinate for the Robot is
(x+move[i][j][0], y+move[i][j][1]), and the orientation that the Robot faces is move[i]
[j][2]. In order to avoid repeated searches, if the coordinate and the orientation
hasn’t appeared before, then the command is valid, a new state is generated, and
the number of commands for the new state equals the number of commands for the
previous state + 1; else the state is omitted.
Obviously, move[ ][ ][ ] are contestant arrays.
{{0, 0, 1}, {0, 0, 2}, {1, 0, 0}, {2, 0, 0}, {3, 0, 0}},
{{0, 0, 0}, {0, 0, 3}, {0, 1, 1}, {0, 2, 1}, {0, 3, 1}},
(0, 0)
Row 0
(i – 1, j) r = 0.8
(i – 1, j – 1)
Column 0 (i, j – 1)
Column n –1
Obstacle Robot
Row n – 1
(m – 1, n – 1)
Figure 9.3
Practice for State Space Search ◾ 597
{{0, 0, 0}, {0, 0, 3}, {0, -1, 2}, {0, -2, 2}, {0, -3, 2}},
{{0, 0, 1}, {0, 0, 2}, {-1, 0, 3}, {-2, 0, 3}, {-3, 0, 3}},
};
The cost for the execution of one command is 1 second. BFS is done layer by
layer. If the destination point is reached, the number of executed commands is the
minimal number of seconds in which the robot reaches the destination point from
the starting point.
Program
#include <iostream>
#include <queue>
using namespace std;
typedef int Byte;
struct Node { //State
598 ◾ Algorithm Design Practice for Collegiate Programming
Input
The input file contains several villa descriptions. Each villa starts with a line con-
taining three integers r, d, and s. r is the number of rooms in the villa, which will be
at most 10. d is the number of doors/connections between the rooms, and s is the
number of light switches in the villa. The rooms are numbered from 1 to r; room
number 1 is the hallway, and room number r is the bedroom.
This line is followed by d lines containing two integers i and j each, specifying
that room i is connected to room j by a door. Then follow s lines containing two
integers k and l each, indicating that there is a light switch in room k that controls
the light in room l.
A blank line separates the villa description from the next one. The input file
ends with a villa having r=d=s=0, which should not be processed.
Output
For each villa, first output the number of the test case (‘Villa #1’, ‘Villa #2’, etc.) in
a line of its own.
If there is a solution to Mr. Black’s problem, output the shortest possible
sequence of steps that leads him to his bedroom and only leaves the bedroom light
switched on. (Output only one shortest sequence if you find more than one.) Adhere
to the output format shown in the sample below.
Practice for State Space Search ◾ 601
3 3 4 Villa #1
1 2 The problem can be solved in 6 steps:
1 3 – Switch on light in room 2.
3 2 – Switch on light in room 3.
1 2 – Move to room 2.
1 3 – Switch off light in room 1.
2 1 – Move to room 3.
3 2 – Switch off light in room 2.
2 1 2 Villa #2
2 1 The problem cannot be solved.
1 1
1 2
0 0 0
Source: ACM Southwestern European Regional Contest 1996
IDs for Online Judges: POJ 1137, ZOJ 1301, UVA 321
Analysis
Suppose the interval for the room numbers is [0, r−1].
State u: A state u is represented as a r+4-digit binary number, where the last
four digits for u (u%16) represents the current room number, and the r−digit prefix
for u (u/16) represents the current lights’ status for all rooms: one binary digit rep-
resents one room’s light: 1 represents that the light is on, and 0 represents that the
light is off; for the upper limit for the number of rooms is 10. The initial state u0 =24.
That is, the light in the hallway (room 0) is on, and lights in other rooms are off.
The goal state utarget =(1<<(r+4−1))+r−1. That is, the light in in the bedroom (room
r−1) is on, and lights in other rooms are off.
Successor Function (the rule generating a new state u_new): For state u,
there are three operations:
The generated state u_new is valid if the operation meets two following
conditions.
In order to avoid repeated searches, u_new hasn’t been visited before; In u_new,
the light in the current room must be on (((u_new/16)&(2u_new%16))==1).
State Space: From the initial state, new states are generated to construct a state
space tree.
Cost: In the state space tree, the cost for each edge is 1.
The problem requires you to calculate the shortest possible sequence of steps.
The upper limit for the number of states is 1024×10. For each state, the upper limit
of the number of operations is 30 (10 moving methods + 10 switching on lights + 10
switching off lights). Therefore, BFS is suitable to solve the problem.
Program
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <queue>
#include <algorithm>
using namespace std;
#define maxn 15 // The upper limit for the size of a matrix
#define maxs 20010 // The upper limit for states
#define MOVETO 20 // moving
#define SWITCHON 10 // switching on lights
#define SWITCHOFF 0 // switching off lights
int r; // the number of rooms
int control[maxs]; //state transformation: state u is
generated by control[u]
int op[maxs]; //op[i] stores control information for state i:
the number of room that Mr. Black will enter or control its light
Practice for State Space Search ◾ 603
{
u_new=u-j; //calculate state u_new
if (!visited[u_new] && checkstay(u_new) //u_new
hasn't been visited, and is valid
{
q.push(u_new); //u_new is added into q
step.push(k+1); //the number of steps is added into step
visited[u_new]=true; //set u_new visited mark
control[u_new]=u;
op[u_new]=SWITCHOFF+i; //state u_new turns the
light in room i off
}
}
else //turn on the light in room i
{
u_new=u+j; //new state u_new
if (!visited[u_new] && checkstay(u_new))
// u_new hasn't been visited, and is valid
{
q.push(u_new); // u_new is added into q
step.push(k+1); // the number of steps is added into step
visited[u_new]=true; // set u_new visited mark
control[u_new]=u;
op[u_new]=SWITCHON+i; // state u_new turns
the light in room i on
}
}
}
}
return -1; //return no solution
}
void dfsprint(int u) //from goal state u, output the
shortest possible sequence of steps
{
int u_new;
if (u==(1<<4)) return;
u_new=control[u];
dfsprint(u_new);
//Backtracking: if op[u]>=20, then Move to room op[u]−20+1; if
op[u] is in [19,10], then switch on light in room op[u]−10+1;
if op[u] is in [9,0], Switch off light in room op[u] +1
if (op[u]>=MOVETO) printf("- Move to room %d.\n",
op[u]-MOVETO+1);
else if (op[u]>=SWITCHON) printf("- Switch on light in
room %d.\n", op[u]-SWITCHON+1);
else if (op[u]>=SWITCHOFF) printf("- Switch off light in
room %d.\n", op[u]-SWITCHOFF+1);
}
void print(int cs, int steps) //calculate and output the
cs-th test case
606 ◾ Algorithm Design Practice for Collegiate Programming
{
printf("Villa #%d\n", cs); // the number of test cases
if (steps==-1) // no solution
printf("The problem cannot be solved.\n");
else
{
printf("The problem can be solved in %d steps:\n",
steps);
dfsprint((1<<(r+4-1))+r-1); // from goal state output
the shortest possible sequence of steps
}
printf("\n");
}
int main()
{
int steps; //the number of the shortest possible
sequence of steps
for (int cs=1; ;cs++) // deal with test cases
{
if (!init()) break; // Input a villa
steps=bfs(); //BFS is used to calculate the number
of the shortest possible sequence of steps
print(cs, steps); //calculate and output the cs-th
test case
}
return 0;
}
1. Branching;
2. Memorization;
3. Indexing;
4. Pruning;
5. Bounding;
6. A* algorithm;
Strategy 1: Branching
A state space can be very large. And there is no need to construct a state space
before the state space search begins. Branching means that a state space is
searched as its state space tree is constructed. For 9.1.1 Robot and 9.1.2
Practice for State Space Search ◾ 607
Input
Every case begins with N, the size of the grid (1≤N≤21), on a line. N lines with N
characters each follow, describing the garden: “.” indicates a plot without any roses,
“R” indicates the location of a rose, and “P” stands for the plinth in the center.
Input will end on a case where N=0. This case should not be processed.
608 ◾ Algorithm Design Practice for Collegiate Programming
Output
For each case, output a line containing the minimum guaranteed number of roses
you can step on while escaping.
Sample Input Sample Output
Analysis
According to the problem description, you are blindfolded; you have the layout of
your garden committed to memory; you are standing on a square marble plinth in
the exact center; and you are quite disoriented: you can orient yourself facing one
of North, East, South, or West, but you have no way to know which.
Your garden is an N×N collection of square plots (N is odd). Because of sym-
metry, the current square plot on which you are standing is a square plot (x, y), or
(n−1−y, x), or (y, n−1−x) or (n−1−x, n−1−y). And (x, y), (n−1−y, x), (y, n−1−x) and
(n−1−x, n−1−y) constitute a square whose center is the square marble plinth in the
exact center. Suppose you move into an adjacent square plot (x', y') from (x, y) in
direction 1, (x, y) and (x', y') are adjacent, either | x − x'|==1 or | y − y'==1. Also
because of symmetry, moves from three square plots in other three directions are
similar. In Figure 9.4, you move into (x', y') from (x, y), or move from (n−1−y, x),
(y, n−1−x) and (n−1−x, n−1−y) into (n−1−y', x'), (y', n−1−x') and (n−1−x', n−1−y')
respectively. Obviously, (n−1−y, x) and (n−1−y', x') are adjacent, (y, n−1−x) and (y',
n−1−x') are adjacent, and (n−1−x, n−1−y) and (n−1−x', n−1−y') are adjacent. And
(x', y'), (n−1−y', x'), (y', n−1−x') and (n−1−x', n−1−y') constitute a new square whose
center is the square marble plinth in the exact center. The four adjacent square plots
represent your four moving directions.
Based on the above information, the successor function is as follows:
Suppose you move into an adjacent square plot (x', y') from
(x, y) in direction 1. Because of symmetry, if
(x', y') contains a rose, then the number of roses you step
on in direction one into (x', y') = the number of roses
you step on when you move into (x, y) + 1;
Practice for State Space Search ◾ 609
(0, 0)
(n – 1 – y´, x´)
n – 1 – y, x (x, y)
(x´, y´)
(n – 1, n – 1)
Figure 9.4
Obviously, the maximum number of roses val you step on when you move into
(x', y') in four directions (up, left, down, right) is the upper limit of the number of
roses you step on when you move into (x', y').
Memorization BFS is used to calculate the minimum guaranteed number of
roses you step on while escaping. The greedy method is used. Each time, the state
with minimum val is removed from the priority queue. Therefore, the priority
queue is a min heap in which val is the priority.
Memorization is used in the search. In states there are the current position (x, y),
the number of roses you can step on in four directions (up, left, down, right) and
its maximum value val; and a Boolean array vis[x][y][d1][d2][d3][d4] is used to mark
whether the state that (x, y) is the position and the number of roses you step on are
d1, d2, d3, and d4 respectively has been searched before. If a generated state has been
searched before, the state is pruned.
Obviously, if ((x==0)||(x==n−1)||(y==0)||(y==n−1)), then you have escaped
from the garden, and f [x, y] is the minimum guaranteed number of roses you can
step on while escaping.
610 ◾ Algorithm Design Practice for Collegiate Programming
Program
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 21; //the upper limit of your garden size
const int d[4][2]={{1, 0}, {-1, 0}, {0, -1}, {0, 1}}; //four
directions: horiztontal and vertical
int n, vis[N][N][11][11][11][11]; //memorization list,
where vis[x][y][d1][d2][d3][d4] is the mark that when you move
into (x, y), the number of roses you step on are d1, d2, d3,
and d4 respectively in directions (up, left, down, right)
char g[N][N]; //the graph for the garden
struct State { // definition for State
int x, y, val; //the current square plot(x, y), the
maximum number of roses val you step on when you move into
(x', y') in four directions
int up, left, down, right; // the number of roses you
step on in 4 directions
State() {x= y=up=left=down=right=0;} //Initial state
(starting position (0, 0), numbers of roses you step on in
4 directions are 0)
State(int x, int y, int up, int left, int down, int right)
{ //current state
this->x = x;
this->y = y;
this->up = up;
this->left = left;
this->down = down;
this->right = right;
val = max(max(max(up,left), down), right);
}
bool operator<(const State& c)const { //priority for
states: val
return val > c.val;
}
} s; //state s
void init() { //Input the garden
for (int i = 0; i < n; i++) {
scanf("%s", g[i]);
for (int j = 0; j < n; j++) // the plinth in the
center
if (g[i][j] == 'P') s.x = i, s.y = j;
}
Practice for State Space Search ◾ 611
}
int bfs() { //memorization BFS: calculate the minimum
guaranteed number of roses you step on while escaping
memset(vis, 0, sizeof(vis)); //Initialization
priority_queue<State> Q; //priority queue Q storing
states: number of roses you step on val is priority
Q.push(s); //initial state is added into the queue
vis[s.x][s.y][0][0][0][0]=1; //initialize memorization
list
while (!Q.empty()) { // remove the front u from the
queue
State u = Q.top();
Q.pop();
if (u.x==0||u.x==n-1||u.y==0||u.y==n-1)return u.val;
//if escaping, return the minimum number of roses you step on
for (int i = 0; i < 4; i++) { //enumerating 4
directions
int xx = u.x + d[i][0]; //calculate the
adjacent square plot (xx, yy) in direction i
int yy = u.y + d[i][1];
int up = u.up; // the number of roses you step
on in the original 4 directions
int left = u.left;
int down = u.down;
int right = u.right;
if (g[xx][yy] == 'R') up++; //accumulation for
4 directions
if (g[n - 1 - yy][xx] == 'R') left++;
if (g[n - 1 - xx][n - 1 - yy] == 'R') down++;
if (g[yy][n - 1 - xx] == 'R') right++;
if (!vis[xx][yy][up][left][down][right]) { //if
the new state hasn't been visited, add it into the
memorization list and queue
vis[xx][yy][up][left][down][right] = 1;
Q.push(State(xx, yy, up, left, down, right));
}
}
}
}
int main() {
while (~scanf("%d", &n) && n) { //Input the size of
garden N
init(); // Input garden and the plinth in the
center
printf("At most %d rose(s) trampled.\n",bfs());
//Calculating and output the result
}
return 0;
}
612 ◾ Algorithm Design Practice for Collegiate Programming
Strategy 5: Bounding
Before enumerating the candidate solutions of a branch, the branch is checked
against upper and lower estimated bounds on the optimal solution, and it is
discarded if it cannot produce a better solution than the best one found so far
by the algorithm.
9.2.2 Fill
There are three jugs with a volume of a, b, and c liters. (a, b, and c are positive inte-
gers not greater than 200). The first and the second jug are initially empty, while the
third is completely filled with water. It is allowed to pour water from one jug into
another until either the first one is empty or the second one is full. This operation
can be performed zero, one, or more times.
You are to write a program that computes the least total amount of water that
needs to be poured; so that at least one of the jugs contains exactly d liters of water
(d is a positive integer not greater than 200). If it is not possible to measure d liters
this way, your program should find a smaller amount of water d '<d which is closest
to d and for which d ' liters could be produced. When d ' is found, your program
should compute the least total amount of poured water needed to produce d ' liters
in at least one of the jugs.
Input
The first line of input contains the number of test cases. In the next T lines, T test
cases follow. Each test case is given in one line of input containing four space-
separated integers—a, b, c, and d.
Output
The output consists of two integers separated by a single space. The first integer
equals the least total amount (the sum of all waters you pour from one jug to
another) of poured water. The second integer equals d, if d liters of water could be
produced by such transformations, or it equals the closest smaller value d ' that your
program has found.
2 2 2
2 3 4 2 9859 62
96 97 199 62
Source: Bulgarian National Olympiad in Informatics 2003
IDs for Online Judges: UVA 10603
Practice for State Space Search ◾ 613
Analysis
Suppose that volumes for three jugs are A, B, and C liters respectively. Finally, one
of the jugs contains exactly D liters of water.
State (a, b, c, tot): In the current three jugs, there are a, b, and c liters of water
respectively. And the current total amount of poured water is tot liters.
Successor function: There are six cases that you pour water from one jug into
another.
Case 1: If all water in jug 1 can be poured into jug 2 (a<B−b), then all water in
jug 1 is poured into jug 2, and a new state (0, b+a, c, tot+a) is generated; else
water in jug 1 is poured into jug 2 until jug 2 is full, and a new state (a−(B−b),
B, c, tot+(B−b)) is generated.
Case 2: If all water in jug 1 can be poured into jug 3 (a<C−c), then all water in
jug 1 is poured into jug 3, and a new state (0, b, c+a, tot+a) is generated; else
water in jug 1 is poured into jug 3 until jug 3 is full, and a new state (a−(C−c),
b, C, tot+(C−c)) is generated.
Case 3: If all water in jug 2 can be poured into jug 1 (b<A−a), then all water in jug
2 is poured into jug 1, and a new state (a+b, 0, c, tot+b) is generated; else water
in jug 2 is poured into jug 1 until jug 1 is full, and a new state (A, b−(A−a),
c, tot+(A−a)) is generated.
Case 4: If all water in jug 2 can be poured into jug 3 (b<C−c), then all water
in jug 2 is poured into jug 3, and a new state (a, 0, c+b, tot+b) is generated;
else water in jug 2 is poured into jug 3 until jug 3 is full, and a new state
(a, b−(C−c), C, tot+(C−c)) is generated.
Case 5: If all water in jug 3 can be poured into jug 1 (c<A−a), then all water in
jug 3 is poured into jug 1, and a new state (a+c, b, 0, tot+c) is generated; else
water in jug 3 is poured into jug 1 until jug 1 is full, and a new state (A, b,
c−(A−a), tot+(A−a)) is generated.
Case 6: If all water in jug 3 can be poured into jug 2 (c<B−b), then all water in
jug 3 is poured into jug 2, and a new state (a, b+c, 0, tot+c) is generated; else
water in jug 3 is poured into jug 2 until jug 2 is full, and a new state (a, B,
c−(B−b), tot+(B−b)) is generated.
closest to d and for which d' liters could be produced.) Obviously the problem is a
problem of finding a shortest path. BFS is suitable to solve the problem.
BFS is as follows:
When BFS ends, from D, the first res[D']≠∞ is searched in descending order.
That is, res[D'] is the least total amount of poured water.
Program
#include <stdio.h>
#include <queue>
using namespace std;
#define min(x, y) ((x) < (y) ? (x) : (y))
Practice for State Space Search ◾ 615
Input
The input file is divided into two parts. The first one describes the packages which are
listed in the catalogue. The second part describes individual customer requests. The four
sizes of light bulbs are identified in the input file by the characters “a”, “b”, “c”, and “d”.
The first part of the input file begins with an integer n (1≤n≤50) indicating the
number of packages described in the catalog. Each of the n lines that follows is a
single package description. A package description begins with a catalog number
(a positive integer) followed by a price (a real number), and then the sizes and cor-
responding numbers of the light bulbs in the package. Between one and four dif-
ferent sizes of light bulbs will be listed in each description. The listing format for
these size-number pairs is a blank, a character (“a”, “b”, “c”, or “d”) representing a
size, another blank, and then an integer representing the number of light bulbs of
that size in the package. These size-number pairs will not appear in any particular
order, and there will be no duplicate sizes listed in any package. The following line
describes a package with catalog number 210 and price $76.95 which contains
three size “a” bulbs, one size “c” bulb, and four size “d” bulbs.
210 76.95 a 3 c 1 d 4
The second part of the input file begins with a line containing a single positive
integer m representing the number of customer requests. Each of the remaining m
lines is a customer request. A listing of sizes and corresponding numbers of light
bulbs constitutes a request. Each list contains only the size-number pairs, formatted
the same way that the size-number pairs are formatted in the catalogue descrip-
tions. Unlike the catalogue descriptions, however, a customer request may contain
duplicate sizes. The following line represents a customer request for one size “a”
bulb, two size “b” bulbs, two size “c” bulbs, and five size “d” bulbs.
a1d5b1c2b1
Output
For each request, print the customer number (1 through m, 1 for the first customer
request, 2 for the second, ……, m for the m-th customer), a colon, the total price of
the packages which constitute the least expensive way to fill the request, and then
the combination of packages that the customer should order to fill that request.
Prices should be shown with exactly two significant digits to the right of the
decimal. The combination of packages must be written in ascending order of cata-
log numbers. If more than one of the same type package is to be ordered, then the
number ordered should follow the catalog number in parentheses. You may assume
that each customer request can be filled. In some cases, the least expensive way to
fill a customer request may contain more light bulbs of some sizes than necessary to
618 ◾ Algorithm Design Practice for Collegiate Programming
fill the actual request. This is acceptable. What matters is that the customers receive
at least what they request.
DFS is used to calculate the least expensive way to fill the request and the
combination of packages that the customer should order to fill that request. The
following strategies are used in the search.
For each size of light bulb, packages are sorted in ascending order of the
upper limits of its prices. Suppose rankby[i][j] stores the number of package stor-
ing the light bulb with size i whose price is ranked j; minave[i][j] stores the least
upper limit of prices for light bulb with size i from package j to package n. And
rankby[ ][ ] and minave[ ][ ] are calculated when a test case is input.
There are two boundings:
Bounding 1: If the current total price now is higher than the current
cheapest price ans, it backtracks directly;
Bounding 2: Four sizes of light bulbs are searched. If now+minave[i]
[st]×need[i] > ans (0≤i≤3) for four sizes of light bulbs, then it backtracks.
3. Optimized search strategy: A greedy algorithm is used. The size of bulb
which is demanded most is searched, that is, need [br ] = max {need [i ]}. In
0 ≤i ≤ 3
order to buy light bulbs with the cheapest price, based on the ascending order
for the upper limit of prices, in st the first package p which meets the cus-
tomer’s requirement is searched and is put into the current combination, that
is, (p=rankby[br][i])&&(p>st)&&(need[j]>0)&&(there exist light bulbs with
size j in package p), 0≤i≤n−1.
DFS is implemented by search(st, now):
Program
#include <cstdio>
#include <cstring>
#include <iostream>
620 ◾ Algorithm Design Practice for Collegiate Programming
#include <vector>
#include <algorithm>
#include <utility>
#include <sstream>
#include <map>
using namespace std;
struct pacnode //package struct
{
int q[4]; //number of bulbs q[i] with size i
double price; //price
int id; // catalog number
}pac[60]; //packages
int n, met[60], nowmet[60], need[4], rankby[4][60];
double ans, ave[4][60], minave[4][60];
void init(); // packages' information
void work(); //current customer's request
void search(int st, double now); //DFS is used to calculate
the result, the st-th package, the current price now
int main()
{
int testno = 0;
while (true) //number of packages n
{
if (scanf("%d", &n) == EOF) break;
if (n == 0) break;
init(); //n packages' information
++testno; //number of the test case
printf("Input set #%d:\n", testno);
int m;
scanf("%d\n", &m); //number of customers
for (int i = 0; i < m; ++i) //customers' requests
{
printf("%d:", i + 1); //number of the customer
work(); //deal with the request for customer i
}
}
return 0;
}
void init() // n packages' information
{
for (int i = 0; i < n; ++i) // n packages' information
{
scanf("%d%lf", &pac[i].id, &pac[i].price); // catalog
number and price for package i
memset(pac[i].q, 0, sizeof(pac[i].q));
char tmp[1000];
gets(tmp); // numbers and sizes for bulbs in package i
istringstream in(tmp);
while (true) //size kind and number x
Practice for State Space Search ◾ 621
{
char kind;
int x;
if (in >> kind >> x == NULL) break;
pac[i].q[kind - 97] += x; //the number of bulbs
with size kind in package i
}
}
for (int i = 0; i < 4; ++i) //calculate ave[ ][ ] by
enumerating sizes and packages
for (int j = 0; j < n; ++j)
if (pac[j].q[i] == 0) ave[i][j] = 1e100;
else ave[i][j] = pac[j].price / pac[j].q[i];
for (int i = 0; i < 4; ++i) //enumerate size i, sorting
packages x[ ], the upper limit for the price is as the first
key, number of packages is the second key
{
pair<double, int> x[60]; // x[ ]: a pair of elements
for (int j = 0; j < n; ++j)
{
x[j].first = ave[i][j]; x[j].second = j;
}
sort(x, x + n);
//calculate rankby[i][j] and minave[i][j]
for (int j = 0; j < n; ++j) rankby[i][j] = x[j].second;
minave[i][n - 1] = ave[i][n - 1];
for (int j = n - 2; j >= 0; --j) minave[i][j] =
min(minave[i][j + 1], ave[i][j]);
}
}
void work() // current customer's request
{
memset(need, 0, sizeof(need));
char tmp[1000];
gets(tmp);
istringstream in(tmp);
while (true) //size kind, number x
{
char kind;
int x;
if (in >> kind >> x == NULL) break;
if (kind == 'a') need[0] += x; //4 bulbs' numbers
else if (kind == 'b') need[1] += x;
else if (kind == 'c') need[2] += x;
else if (kind == 'd') need[3] += x;
}
memset(nowmet, 0, sizeof(nowmet)); ans = 1e100; //Initialize:
ans=∞
search(0, 0.0); // DFS is used to calculate the result,
the 0-th package, the current price 0
622 ◾ Algorithm Design Practice for Collegiate Programming
The reason why two lists are constructed is that we need to determine
whether the current state is unvisited, visited, or generated. Based on that, the
methods calculating f [v] are different: if state v is unvisited, f [v] is calculated
by f(v)=g(v)+h(v); else f [v] is adjusted. The process for A* search is as follows:.
The above process is repeated until the goal state is reached or OPEN is
empty.
If OPEN is empty, the search fails; else the best path is found.
Two aspects should be noted:
1. The selection for the estimated cost h(v) is the key to find the best path.
2. There is a balance between the computation of h(v) and the efficiency
solving a problem.
624 ◾ Algorithm Design Practice for Collegiate Programming
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 x
Figure 9.5
9.2.4 Eight
The 15-puzzle has been around for over 100 years; even if you don’t know it by that
name, you’ve seen it. It is constructed with 15 sliding tiles, each with a number
from 1 to 15 on it, and all packed into a 4×4 frame with one tile missing. Let’s call
the missing tile “x”; the object of the puzzle is to arrange the tiles so that they are
ordered as shown in Figure 9.5 where the only legal operation is to exchange “x”
with one of the tiles with which it shares an edge. As an example, the following
sequence of moves shown in Figure 9.6 solves a slightly scrambled puzzle.
The letters in the previous row indicate which neighbor of the “x” tile is swapped
with the “x” tile at each step; legal values are “r”, “l”, “u”, and “d”, for right, left, up,
and down, respectively.
Not all puzzles can be solved; in 1870, a man named Sam Loyd was famous for
distributing an unsolvable version of the puzzle, and frustrating many people. In
fact, all you have to do to make a regular puzzle into an unsolvable one is to swap
two tiles (not counting the missing “x” tile, of course).
In this problem, you will write a program for solving the less well-known 8-puzzle,
composed of tiles on a three by three arrangement.
Input
You will receive, in “eight.inp”, a description of a configuration of the 8-puzzle. The
description is just a list of the tiles in their initial positions, with the rows listed from
top to bottom, and the tiles listed from left to right within a row, where the tiles are
1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4
5 6 7 8 5 6 7 8 5 6 7 8 5 6 7 8
9 x 10 12 9 10 x 12 9 10 11 12 9 10 11 12
13 14 11 15 13 14 11 15 13 14 x 15 13 14 15 x
R D R
Figure 9.6
Practice for State Space Search ◾ 625
1 2 3
x 4 6
7 5 8
Figure 9.7
represented by numbers 1 to 8, plus “x”. For example, see the puzzle shown in Figure 9.7
is described by this list:
123×46758
Output
You will print to standard output either the word “unsolvable”, if the puzzle has
no solution, or a string consisting entirely of the letters “r”, “l”, “u”, and “d” that
describes a series of moves that produce a solution. The string should include no
spaces and start at the beginning of the line.
2 3 4 1 5 × 7 6 8 ullddrurdllurdruldr
Analysis
An 8-puzzle is a 3×3 matrix, where its elements are 1 to 9 respectively, and 9 repre-
sents “x”. An 8-puzzle can be represented as a permutation for 1…9, where the k-th
k
element in the permutation is the element whose position is , k %3 in the
3
matrix, 0≤k≤8.
States: A permutation for 1…9 can be regarded as a state. The number of states
is 9!=362880. In order to save memory, the alphabet order for permutations is used
as the index for states:
1,2,3.4,5,6,7,8,9: 0
……
9,8,7.6,5,4,3,2,1: 362879
626 ◾ Algorithm Design Practice for Collegiate Programming
A* algorithm is as follows:
Program
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
using namespace std;
int fac[] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 };
// fac[i]=i! ..
int order(const char *s, int n) { // the alphabet order for
permutations s
n −1
ks = ∑ (s[i] − 1)!* (the number of elements after s[i] and less than
i=0
s[i]),
0≤ks≤n!−1
int i, j, temp, num;
num = 0; // the alphabet order 0
for (i = 0; i < n-1; i++) { //from right to left,
enumeration
628 ◾ Algorithm Design Practice for Collegiate Programming
tmp.board[i] = 1;
break;
}
tmp.space = n - a[n-1] -1;
}
int goal_state[9][2] = {{0,0}, {0,1}, {0,2}, {1,0}, {1,1},
{1,2}, {2,0}, {2,1}, {2,2}}; //In the goal state, number i
is at (goal_state[i][0], goal_state[i][1])
int h(const char *board){ // calculate h(board): the
estimated cost from state board to the goal state
int k;
int hv = 0; //sum of distances
for(int i=0; i<3; ++i) //search each position (i, j)
for(int j=0; j<3; ++j){
k = i*3+j;
if(board[k]!=9){ //the number in position isn't 9
hv += abs(i - goal_state[board[k]-1][0]) +abs(j - goal_
state[board[k] -1][1]);
}
}
return hv; //return the sum of distances
}
int f[TABLE_SIZE], d[TABLE_SIZE]; // Heuristic Function
f[u]: the cost to the goal state, from the initial state and
through state u, d[u]: the minimal number of moves from the
initial state to state u, (u is the alphabet order for
permutations)
struct cmp{ //Comparison function for the priority queue:
Heuristic Function f[u] is the key, sorting in ascending
order
bool operator () (int u, int v){
return f[u] > f[v];
}
};
d[v] = d[u] + 1;
parent[v] = u;
open.push(v); //v is added into the
queue again
color[v] = 1; //v is in the queue
}
else if(color[v] == 0){ // v hasn't been
visited
move[v] = i; //direction i entering v
d[v] = d[u] + 1;
f[v]=d[v]+h(tmp.board);
parent[v] = u;
open.push(v); //v is added into the
queue
color[v] = 1; //v is in the queue
}
}
}
color[u] = 2; //4 directions for u have been searched
}
}
void print_path(){ // output a series of moves
int n, u;
char path[1000]; // a series of moves
n = 1; //number of moves
path[0] = move[0];
u = parent[0]; //the precursor for the goal state u
while(parent[u] != -1){ //from the goal state to the
initial state
path[n] = move[u]; //the direction entering state u
++n; //number of moves
u = parent[u]; //the precursor
}
for(int i=n-1; i>=0; --i){ //output a series of moves
from the initial state
if(path[i] == 0) printf("u");
else if(path[i] == 1) printf("d");
else if(path[i] == 2) printf("l");
else printf("r");
}
}
int main(){
//freopen("in", "r", stdin);
node start; //initial state
char c; //input character
for(int i=0; i<9; ++i){ //input 9 characters, the initial
state start is constructed
cin>>c;
if(c == 'x'){ //the i-th character “x” is 9, it's a
space
632 ◾ Algorithm Design Practice for Collegiate Programming
start.board[i] = 9;
start.space = i;
}
else start.board[i]=c-'0';
}
A_star(start); // A* algorithm is used to calculate a
series of moves
if(color[0]!= 0)print_path(); // if the goal state has
been visited, output a series of moves; else output "unsolvable—"
else printf("unsolvable");
return 0;
}
Input
The first line contains two integer numbers N and M (1≤N≤1000, 0≤M≤100000).
Stations are numbered from 1 to N. Each of the following M lines contains three
integer numbers A, B and T (1≤A, B≤N, 1≤T≤100). It shows that there is a directed
sideway from the A-th station to the B-th station with time T.
The last line consists of three integer numbers S, T, and K (1≤S, T≤N,
1≤K≤1000).
Practice for State Space Search ◾ 633
Output
A single line consisting of a single integer number: the length (time required) to
welcome Princess Uyuw using the K-th shortest path. If K-th shortest path does not
exist, you should output “−1” (without quotes) instead.
Analysis
The problem can be represented as a weighted directed graph G. Stations in UDF
are represented as vertices, muddy directed sideways connecting some of the sta-
tions are represented as arcs, and the time cost on a sideway is represented as the
weight for the corresponding arc.
The problem requires you to calculate the length of the K-th shortest path from
the starting point to the terminal point in G.
The naive algorithm solving the problem is using BFS from the starting point.
When the terminal point is searched K times, the length of the path is the time
required to welcome Princess Uyuw using the K-th shortest path. If K is larger
or the number of vertices is more, the solution will consume more memory than
permitted.
The method to solve the problem is using algorithm calculating the single-
source shortest paths and A* search.
Step 1: For G, its converse digraph G’ is constructed. Then the terminal point T
is as the single-source, and an SPFA algorithm is used to calculate the lengths
of the shortest paths from the terminal point T to other vertices. It is used for
the estimated cost.
Step 2: A* search is used to calculate the length of the K-th shortest path.
634 ◾ Algorithm Design Practice for Collegiate Programming
A* search can be used to calculate the shortest path. Therefore the K-th shortest
path can be calculated in the K-th times.
The key to A* search is to design the function for the estimated cost F[i]:
F[i]=G[i]+H[i], where G[i] is the length of the shortest path from the starting point
S to vertex i, and H[i] is the length of the shortest path from vertex i to the terminal
point T, calculated in Step 1. Therefore, the estimated cost F[i] is the length of the
shortest path from S to T, through vertex i.
Each time the minimal value is gotten out from F[ ]. Therefore F[ ] is stored as
a priority queue.
Initially the starting point S is added into the priority queue F[ ]. Then A*
search is used. Each time, the vertex with the minimal value is obtained from
F[ ]. For each adjacent vertex i, G[i] is calculated, F[i] is calculated based on
H[i], and the number of times that Prince Remmarguts goes through vertex i is
accumulated.
1. For each vertex, the number of paths that Prince Remmarguts goes through
it is at most K.
2. If T isn’t reachable from some vertices, in H[ ] the vertices’ values are ∞.
Program
#include<stdio.h>
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
#define inf 99999999
#define N 1100
typedef struct nnn //the struct for priority queue
{
int F,G,s; //vertex s, G: the length from the starting
point to s, F; the length of the path through s
friend bool operator<(nnn a,nnn b) //the priority for the
priority queue
{
return a.F>b.F;
}
}PATH;
typedef struct nn // adjacency list
{
int v,w; //adjacent vertex v, the length of the arc w
}node;
Practice for State Space Search ◾ 635
thus doesn’t go to the same depth everywhere in the search tree. Unlike A*, IDA*
doesn’t utilize dynamic programming and therefore often ends up exploring the
same nodes many times.
The keys to the IDA* algorithm are bounding and pruning.
If you can tell the king the minimum number of times the king has to jump to gain the
new formation, they could be generous and release you.
Input
The input file contains several sets of inputs. The total number of sets will be less
than 50. The description of each set is given below:
Each set starts with one integer N (4≤N≤40) which indicates the total number
of jaguar warriors. You can assume that N is a multiple of 4. The next line will
contain N numbers which indicates the final formation of the jaguars. Consecutive
numbers will be separated by a single space.
The input will be terminated by the set where N=0. And this set should not be
processed.
Output
For each set in the input, you should first print the set number starting from 1. And
the next line should be the minimum number of times the king has to jump to gain
the new formation.
Check the sample input-output for more details. Output should be formatted
like the sample output.
Hope you get out alive.
4 Set 1:
1 2 3 4 0
4 Set 2:
4 2 3 1 1
8 Set 3:
5 2 3 4 8 6 7 1 2
8 Set 4:
5 2 8 3 6 7 1 4 7
0
Source: Next Generation Contest III
ID for Online Judge: UVA 11163
Analysis
Initially N jaguars are placed at N positions in a queue, N%4==0. The king is placed
at position 1. Other jaguars are marked by a number from 2 to N. The jaguars are
Practice for State Space Search ◾ 639
placed according to their number. Only the king can exchange its position with
another jaguar. Suppose the king’s current position is i:
If (i % 4==1), then the king can jump to position (i+1), (i+3), (i+4), (i−4);
If (i % 4==2) , then the king can jump to position (i+1), (i−1), (i+4), (i−4);
If (i % 4==3), then the king can jump to position (i+1), (i−1), (i+4), (i−4);
If (i % 4 = 0), then the king can jump to position (i−3), (i−1), (i+4), (i−4).
Given the final formation of the jaguars, the minimum number of times the
king jumps to gain the final formation is required to calculate.
An array dx[i][j] is used to represent the above rule, where i is the remainder
that the king’s current position is divided by 4 (0≤i≤3), and each remainder is a
kind of the king’s jumping; and j is the sequence number for the kind of the king’s
jumping (0≤j≤3). That is, int dx[4][4] = {{−3, −1, +4, −4}, {+1, +3, +4, −4}, {+1, −1,
+4, −4}, {+1, −1, +4, −4}}. Therefore, if the king’s current position is k, the king can
jump to four positions, where the j-th position is k+dx[k %4][j], 0≤j≤3.
The estimated cost for the IDA* algorithm is F(v)=G(v)+H(v). F(v) is the esti-
mated number of times that the king jumps to gain the final formation through
the current state v. G(v) is the number of times that the king jumps to the cur-
rent state v from the initial formation. Initially, the king’s state is x, G(x)=0.
And H(v) is the estimated cost that the king jumps to gain the final formation
from the state v. H(v) is the sum of the numbers of times that n−1 jaguars (not
the king) jump to their current positions from their final positions using rule
dx[i %4][0..3], for n−1 jaguars (not the king) jump in the opposite directions for
the king’s jumping. A Floyd algorithm is used to calculate H(x) before the IDA*
algorithm is used.
In the IDA* algorithm, states are represented as (x, prev, dep, hv); where x is
the current position for the king; prev is the precursor position for the king, that
is, the king jumps to position x from position prev, and initially prev=−1; dep is
the number of times the king jumps to position x, that is, dep is G(x), and initially,
dep=0; and hv is the estimated number of times that the king jumps to gain the
final formation from the position x, that is, hv is H(v).
In the program, the function IDA(x, prev, dep, hv) is used to calculate the mini-
mum number of times mxdep the king jumps to gain the final formation. In order
to improve the efficiency, the following optimization strategies are used:
1. Bounding. The current minimum number of times mxdep that the king
jumps to gain the final formation is as the bounding. Based on the estimated
cost, if the king can jump to gain the final formation through the current
state, the estimated cost is dep+hv. Obviously, if dep+hv>mxdep, it can’t be a
solution.
2. The king can’t return to prev from x. That is, the endless loop needs to be
avoided.
640 ◾ Algorithm Design Practice for Collegiate Programming
3. There are at most four positions to which the king can jump. Therefore, there
are at most four generated states. The function IDA(x, prev, dep, hv) returns
the minimal value submxdep that is min {numbers of times for the king’s
jumping to gain the final formation in four directions}.
if (hv==0) return the number of times the king jumps dep and
the successful mark;
if (dep+hv> mxdep) it can't be a solution;
submxdep=∞;
Four positions that the king can jump are enumerated tx(tx =
x+dx[x%4][i], 0≤i≤3):
{
if (tx is in the bound)&&(tx≠prev)
{ the number of times the king jumps to gain the final
formation is calculated;
The generated state (tx, x, dep+1, shv) is recursively
calculated, and the number of times the king jumps is tmp;
submxdep= min(submxdep, tmp);
}
};
Return submxdep;
IDA (x, −1, 0, E(s)) is called to calculate the number of
times the king jumps mxdep until the final formation is gained.
Program
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
int g[45][45]; // g[i][j]: the length of the shortest path
between position i and position j
int dx[4][4] = {{-3,-1,+4,-4},{+1,+3,+4,-4},{+1,-1,+4,-4},
{+1,-1,+4,-4}}; // if the king's current position is k, the
king can jump to 4 positions, where the j-th position is
k+dx[k %4][j]
int A[45], n; // A[i] is the number of the jaguar at
position i in the final formation, the numder of jaguars n
void build() { //using Floyd algorithm to calculate g[ ][ ]
int i, j, k;
for(i = 1; i <= 40; i++) { //initialize g[ ][ ]
Practice for State Space Search ◾ 641
swap(A[x], A[tx]);
shv += singleH(x);
tmp = IDA(tx, x, dep+1, shv); //the king jumps from tx
if(solved)return solved; //gain the final formation
swap(A[x], A[tx]);
submxdep=min(submxdep,tmp); //adjust the current
minimal number of times
}
return submxdep; //return the current minimal number of
times
}
int main() {
int i, j, k, x;
int cases = 0; //the number of test cases
build(); // Floyd algorithm is used to calculate the
matrix for the length of shortest path g[ ][ ]
while(scanf("%d", &n) == 1 && n) { // the total number
of jaguar warriors
for(i=1; i<=n; i++) scanf("%d", &A[i]); // the
final formation of the jaguars
printf("Set %d:\n", ++cases); //output the number
of test cases
int initH = H(); // accumulate the minimal numbers
of times that n−1 jaguars (not the king) jump to initial
positions from final positions
if(initH == 0) puts("0"); //initial formation is
the final formation, the king needn't jump
else {
solved = 0; //initialize the minimal numbers
of times the king jumps
mxdep = initH; //initialize
for(i = 1; i <= n; i++) if(A[i] == 1) x=i;
while(solved==0) mxdep=IDA(x,-1,0,initH);
printf("%d\n", solved);
}
}
return 0;
}
The state space for a game can be represented as a game tree, where nodes rep-
resent states, and edges represent moves between states. The root for a game tree is
the initial state. For a node in a game tree, its children are states generated by next
possible moves. Leaves are goal states for a game.
For two players, “Minimax” means that one player makes a move to maxi-
mize his or her utility, and minimize the utility for his or her opponent. The
Minimax algorithm is to calculate the minimal or maximal value, that is, the
best move, based on the current state. If the size for the game tree isn’t large,
DFS can be used to get all possible moves, and to calculate the best move for
the current state. Otherwise, pruning should be used to eliminate some parts of
the tree.
Input
The input file contains one or more test cases, followed by a line beginning with a
dollar sign that signals the end of the file. Each test case begins with a line contain-
ing a question mark and is followed by four lines representing the board; format-
ting is exactly as shown in the example. The characters used in a board description
are the period (representing an empty space), lowercase x, and lowercase o.
Output
For each test case, output a line containing the (row, column) position of the first
forced win for x, or ‘#####’ if there is no forced win. Format the output exactly as
shown in the example.
644 ◾ Algorithm Design Practice for Collegiate Programming
For this problem, the first forced win is determined by board position, not
the number of moves required for victory. Search for a forced win by examining
positions (0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), ..., (3, 2), (3, 3), in that order,
and output the first forced win you find. In the second test case below, note that
x could win immediately by playing at (0, 3) or (2, 0), but playing at (0, 1) will
still ensure victory (although it unnecessarily delays it), and position (0, 1) comes
first.
? #####
.... (0,1)
.xo.
.ox.
....
?
o...
.ox.
.xxx
xooo
$
Source: University of Valladolid Local Contest
IDs for Online Judges: UVA 10111
Analysis
There are 16 squares in a 4×4 tic-tac-toe. There are three possibilities: empty, occu-
pied by x, and occupied by o. Therefore, state compression can be used to represent
states. A 16-digit ternary number state is used to represent a state for a 4×4 tic-tac-toe.
In state, the i×4+ j-th digit represents square (i, j):
If square (i, j) is “x”, then the i×4+ j-th digit for state is 1. That is, state
|= 1UL<<((i×4+ j)×2);
If square (i, j) is “o”, then the i×4+ j-th digit for state is 2. That is, state
|= 2UL<<((i×4+ j)×2);
If square is “.”, then the i×4+ j-th digit for state is 0.
For two players, x and o, there are 10 situations for winning a game, respec-
tively: four situations getting four pieces on the same row, four situations getting
four pieces on the same column, and two situations getting four pieces on the
Practice for State Space Search ◾ 645
same diagonal. For x, 10 situations winning a game are stored in xw[10]. For o,
10 situations winning a game are stored in ow[10].
In order to avoid repeated searches, for each state, a mark R[ ] is set. If turn will
win board node, then R[node]=1; else R[node]=0.
Because the size for the board is small, the search depth is limited. Assuming
that it is x’s turn to move, x is said to have a forced win if x can make a move such
that no matter what moves o makes for the rest of the game, x can win.
646 ◾ Algorithm Design Practice for Collegiate Programming
A recursive function dfs(node, rx, ry, turn) is used to calculate the result for turn;
where node represents the board, initially node is a test case; turn: 1 represents x, and
2 represents o. Obviously, after turn makes a move, 3-turn makes the next move; initially
turn is 1; (rx, ry) is a position of the forced win; initially (rx, ry) is (−1,−1). dfs(node, rx, ry,
turn) returns the result for turn. If the result is 0, then turn is defeated; and if the result
is 1, then turn must win, and the position of the forced win (rx, ry) is also returned.
Program
#include <stdio.h>
#include <string.h>
#include <map>
using namespace std;
map<unsigned int, int> R; // mark R[ ], where R[x] is for
board x
unsigned int ow[10] = {}, xw[10] = {}; //xw[10]: 10
situations that x wins the game, ow[10]: 10 situations that o wins
the game
int check(unsigned int node) { //the result for board node,
0 undetermined
check(node)= 1 x wins
2 o wins
int i;
for(i = 0; i < 10; i++) //x wins, return 1
Practice for State Space Search ◾ 647
A MAX nodes 9
B B B B MIN nodes –5 2 9 –2
Figure 9.8
There are some games whose search depths are larger. Therefore, we need to
restrict the search. For the current state, a score is evaluated. The method for evalu-
ating such scores is called an evaluation function. Suppose there are two players A
and B for a game. A makes the first move. In the game tree, nodes that specify A’s
moves are called “MAX nodes”, for A always moves to a state with the maximum
score. And nodes that specify B’s moves are called “MIN nodes”, for B always
moves to a state with the minimum score. That is to say, both A and B play opti-
mally (Figure 9.8).
In order to get the result more quickly, a kind of heuristic method, called α−β
(alpha-beta) pruning, is used in DFS in a game tree.
For a MAX node in the game tree, the value of the best choice (i.e., the maxi-
mum score) is obtained from leaves through DFS, called the value of α.
For a MIN node in the game tree, the value of the best choice (i.e., the mini-
mum score) is obtained from leaves through DFS, called the value of β.
The DFS updates values of α and value of β as it goes along and prunes remain-
ing branches at a node as soon as the value of the current node is known to be worse
than the current α or β value for MAX node or MIN node respectively.
α pruning: When DFS is used in a game tree, the score from leaves in the
leftmost branch to a MAX node A is denoted as α. And the score α is as the lower
bound for A’s score.
Then DFS is used for other children for A. If after a round (two moves), a score
is lower than α, the corresponding branch (the subtree whose root is the child
for A) is pruned [Figure 9.9(a)]. In Figure 9.9(b), scores are in an ascending order
from left to right, and no branch is pruned.
Pruning
MAX nodes 4 4 MAX nodes
Figure 9.9
650 ◾ Algorithm Design Practice for Collegiate Programming
Pruning
MIN nodes Best Pruning MIN nodes 4
7 Best
choice choice
MAX nodes 7 MAX nodes 8 4
Figure 9.10
β pruning: By the same reason, the score from leaves in the leftmost branch
to a MIN node B is denoted as β. Obviously, the score β is as the upper bound for
B’s score.
Then DFS is used for other children for B. If after a round (two moves), a score
is higher than β, the corresponding branch (the subtree whose root is the child
for B) is pruned. See Figure 9.10.
Input
The first line in the input contains the number of test cases (at most 50). Each
case contains four lines describing the chessboard, preceded by a blank line. The
first of the four lines will be the last rank of the chessboard (the starting point for
the black pawns). Black pawns will be denoted with a ‘p’, white pawns with a ‘P’,
and empty squares with a ‘.’. There will be between one and four pawns of each
color. The initial position will not be a final game position, and white will always
Practice for State Space Search ◾ 651
have at least one legal move. Note that the input position may not necessarily be
one that could have arisen from legal play from the games starting position.
Output
For each test case, output a line containing the text white (xx) if white will
win, or black (xx) if black will win. Replace xx with the number of moves
(which will always be an odd number if white wins and an even number if
black wins).
2 white (7)
.ppp black (2)
....
.PPP
....
...p
...p
pP.P
...P
Analysis
The problem requires you to calculate the winner and its number of moves. It
is a game problem. And α−β (alpha-beta) pruning is used to improve the search
efficiency.
DFS is used to construct a game tree, where nodes represent states for the 4×4
chessboard, and the root is the input test case. Goal states, that is, leaves, are states
that one player uses to get one of his pawns to the other end of the board (last rank
for the white player, first rank for the black player), or to stalemate his opponent.
Middle games are internal nodes.
The level number for the root of the game tree is depth=36. As it moves
down one level, −−depth. At even levels, it is white’s turn to move. And at
odd levels, it is black’s turn to move. The game tree is constructed top-down.
Based on game theory, at even levels, states of the maximum score should be
calculated; and at odd levels, states of the minimum score should be calculated.
Suppose
652 ◾ Algorithm Design Practice for Collegiate Programming
alpha(v) is the maximum number of moves for white from v to leaves. That
is, alpha(v)= max u ∈v ’s children {the number of moves from u to leafs}. The initial
value for alpha is −9999.
beta(v) is the minimum number of moves for black from v to leaves.
beta(v)=minu ∈v ’s children {the number of moves from u to leafs }. The initial value
for beta is 9999.
The value of alpha (or the value of beta) for each node is gotten from leaves.
Therefore, when it is white’s turn to move, return the value of alpha for the internal
nodes; and return −depth for leaves. And when it is black’s turn to move, return the
value of beta for internal nodes; and return depth for leaves.
During the process calculating alpha(v) and beta(v), if for a parent node v,
alpha(v) is calculated; for its children, the minimal beta is calculated. If u is a child
for v, beta(u) is p; and u' is another child for v; u'' is a child for u', and return q<p,
then the subtree whose root is u' can be pruned.
Repeat the process until a goal state is reached.
If the recursion result is a positive number, white wins, and the number of
moves is 36 - the recursion result. And if the recursion result is a negative number,
black wins, and the number of moves is 36 + the recursion result.
Program
#include <stdio.h>
#include <algorithm>
using namespace std;
struct state { // the chessboard
char g[4][5]; // the chessboard
int isEnd() { // if the chessboard is the final state,
return 1; else return 0
int b = 0, w = 0;
for (int i = 0; i < 4; i++) { //the number of white w
and the number of black b
for (int j = 0; j < 4; j++) {
if (g[i][j] == 'p') b++;
if (g[i][j] == 'P') w++;
}
}
if (b == 0 || w == 0) return 1; // having no pawns
left, return 1
for (int i = 0; i < 4; i++) { // get one of his pawns
to the other end of the board, return 1
if (g[0][i] == 'P') return 1;
Practice for State Space Search ◾ 653
9.4 Problems
9.4.1 The Most Distant State
The 8puzzle is a square tray in which eight square tiles are placed. The remain-
ing ninth square is uncovered. Each tile has a number on it. A tile that is
adjacent to the blank space can be slid into that space. A game consists of a
starting state and a specified goal state. The starting state can be transformed
into the goal state by sliding (moving) the tiles around. The 8puzzle problem
asks you to do the transformation in a minimum number of moves, as shown
in Figure 9.11.
However, our current problem is a bit different. In this problem, given an
initial state of the puzzle, you are asked to discover a goal state which is the most
distant (in terms of number of moves) of all the states reachable from the given
state.
Practice for State Space Search ◾ 655
2 8 3 1 2 3
1 6 4 8 4
7 5 7 6 5
Start Goal
Figure 9.11
Input
The first line of the input file contains an integer representing the number of test
cases to follow. A blank line follows this line.
Each test case consists of three lines of three integers each, representing the
initial state of the puzzle. The blank space is represented by a 0 (zero). A blank line
follows each test case.
Output
For each test case, first output the puzzle number. The next three lines will contain
three integers each representing one of the most distant states reachable from the
given state. The next line will contain the shortest sequence of moves that will trans-
form the given state to that state. The move is actually the movement of the blank
space represented by four directions : U (Up), L (Left), D (Down), and R (Right).
After each test case, output an empty line.
1 Puzzle #1
2 6 4 8 1 5
1 3 7 7 3 6
0 5 8 4 0 2
UURDDRULLURRDLLDRRULULDDRUULDDR
Hint
The problem is a special 8-puzzle. Normally the 8-puzzle requires you to calcu-
late the minimum number of moves from a starting state to a goal state. In this
problem, there is a starting state, but there isn’t a specified goal state. You need to
discover a goal state which is the most distant (in terms of number of moves) of all
the states reachable from the starting state.
656 ◾ Algorithm Design Practice for Collegiate Programming
Normally the 8-puzzle is solved by BFS. In this problem, a while repetition ends
when the queue is empty, to guarantee that the most distant of all the states reach-
able from the starting state can be calculated.
A queue q is used to store states. The type for a state is struct, including: a state
for the current nine squares ch[3][3], represented as a nine-digit novenary number;
the position for the square containing 0 (x, y); and the sequence of moves that trans-
forms from the starting state to the current state str;
Suppose m[] is used to show whether a state has been visited or not. That is,
1 state p has appeared before
m[ p ] = . It can be defined as map<long
0 state p hasn’t appeared before
long,int> m;
Function hash(p) is used to determine whether a state has visited or not.
int hash(p) {
long long cnt, k;
cnt=k=0;
for(int i=0; i<N; i++)) // calculate the value cnt for
state p
for(int j=0; j<N; j++) cnt+=p.ch[i][j]*pow(9, k++);
if (!m[cnt]) { //if cnt hasn't appeared
m[cnt]=1;
return 1;
}
return 0;
}
void bfs() {
initial state st is pushed into the queue q;
while (q isn't empty) {
the front st is poped from the queue;
Four directions are enumerated (0≤i≤3):
{
Calculate the position (x1, y1) which the blank space can
be slid into from (st.x, st.y) in direction i;
if ((x1, y1) is out of the puzzle) continue;
st1=st; //new state st1
st1.ch[st1.x][st1.y]=st1.ch[x1][y1]; st1.ch[x1][y1]=0;
st1.x=x1; st1.y=y1;
st1.str+= the character for direction i;
if (hash(st1)) q.push(st1); //if st1 hasn't been
visited, push st1 into the queue
}
}
}
Practice for State Space Search ◾ 657
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15
Figure 9.12
1. Initialization;
m.clear();
st.str is empty;
Set st visited mark (hash(st));
2. bfs(): search all reachable states;
3. For the last state st removed from the queue, output st.ch[3][3] and st.str.
2 12 11 14 2 12 11 14 2 12 11 14 2 12 11 14
6 15 10 5 6 15 10 5 6 15 5 6 15 5
3 9 13 3 9 13 3 9 10 13 3 9 10 13
8 7 1 4 8 7 1 4 8 7 1 4 8 7 1 4
A random puzzle position The missing Tile moves The missing Tile moves The missing Tile moves
to right. Denoted by R. upwards. Denoted by U. to the left. Denoted by L.
Figure 9.13
658 ◾ Algorithm Design Practice for Collegiate Programming
Input
The first line of the input contains one integer N, which indicates how many sets of
puzzles will be given as input. The next 4N lines contain N sets of inputs. It means
four lines make one set of input. Zero denotes the missing tile.
Output
For each set of input, you will have to give one line of output. If the input puzzle is
not solvable, then print the line “This puzzle is not solvable.” If the puzzle is solv-
able, then print the move sequence as described above to solve the puzzle.
2 LLLDRDRDR
2 3 4 0 This puzzle is not solvable.
1 5 7 8
9 6 10 12
13 14 11 15
13 1 2 4
5 0 3 7
9 6 10 12
15 8 11 14
Hint
The initial state is 16 sliding tiles, numbered from 0 to 15, are packed into a 4×4
frame. (The tile numbered 0 means there is no tile at the position). The goal state is
as shown in Figure 9.12. Only the tile numbered 0 can be exchanged with the tile
with which it shares an edge. It can be regarded as the tile moving horizontally or
vertically. The problem requires you to calculate the steps from the initial state to
the goal state.
Tiles’ positions are also numbered from 0 to 15. A position (x, y)=(p/4, p%4),
0≤p≤15.
Practice for State Space Search ◾ 659
13 10 11 6
5 7 4 8
1 12 14 9
3 15 2 0
Figure 9.14
660 ◾ Algorithm Design Practice for Collegiate Programming
If two states’ values are same, the two states are same. Hash technology is
used to determine whether two states are same or not.
For this problem, the DFS algorithm is as follows, where path[] is the
sequence for steps moving the tile whose number is 0.
When the number of steps is less than 15, BFS and DFS can get the solution
to the problem quickly. As the number of steps increases, the spent time and
memory for BFS and DFS will increase.
662 ◾ Algorithm Design Practice for Collegiate Programming
int h( )
{
int s = 0;
for (int i = 0; i < 16; ++i){ //each position is
enumerated
x is the number at position i;
if (x == 0) continue;
s+= abs(i/4 - the row number for x in the goal
state)+abs(i%4 - the column number for x in the goal state);
}
return s;
}
2. Determine whether the current puzzle is solvable or not under the limited
search depth.
There is no function to determine repetitions in the IDA* algorithm. In
IDA* algorithm, each search step can’t move in the opposite direction.
The Boolean function dfs( p, pre, g, maxd) is used to determine whether
the current puzzle is solvable or not under the limited search depth, where p
is the position for the title whose number is 0, pre: the last moving direction,
g is the current search depth, and maxd is the limit for the search depth.
a0 =1
am=n
a0<a1<a 2<...<am-1<am
For each k (1≤k≤m) there exist two (not necessarily different) integers i and
j (0≤i, j ≤k−1) with ak =ai+aj
You are given an integer n. Your job is to construct an addition chain for n with
minimal length. If there is more than one such sequence, any one is acceptable.
664 ◾ Algorithm Design Practice for Collegiate Programming
For example, <1,2,3,5> and <1,2,4,5> are both valid solutions when you are
asked for an addition chain for 5.
Input
The input file will contain one or more test cases. Each test case consists of one line
containing one integer n (1≤n≤100). Input is terminated by a value of zero (0) for n.
Output
For each test case, print one line containing the required integer sequence. Separate
the numbers by one blank.
Hint
The problem is a little time-critical, so use proper break conditions where necessary
to reduce the search space.
5 1 2 4 5
7 1 2 4 6 7
12 1 2 4 8 12
15 1 2 4 5 10 15
77 1 2 4 8 9 17 34 68 77
0
Hint
Given an integer n, the problem requires you to construct an addition chain for n
with minimal length.
Obviously, it is inefficient that only DFS is used. IDA* (DFS + pruning) is
used to solve the problem. Suppose best is the current length of the addition chain.
Initially best=∞. In array d[], d[i] is the maximal number of integers that can be
added into the addition chain after integer i.
The addition chain is constructed from a0 =1. In order to make the length of the
addition chain minimal, each time the maximum that can be added into is
Practice for State Space Search ◾ 665
considered first. That is, if the length of the addition chain is k+1, and the current
maximum in the addition chain is ak, then the possible maximum for ak+1 is
ak +ak =2ak. Therefore, the upper limit for the length of the addition chain after ak is
0 n ≤ i ≤ 2*n
extended is k+d[ak]. Therefore, d [i ] = .
1 + d [2 * i ] 1 ≤ i ≤ n − 1
The IDA* process solving the problem is as follows:
d[] is constructed;
best =∞; a[0] = 1;
DFS(0); // the addition chain is extended from a[0]
Output b[0]…b[best];
of time to travel one unit of distance. As you have only one chance, you’re planning
it thoroughly. The robots have left one of the fastest robots to guard you. You’d need
to program another robot which would carry you through the rugged terrain. A
crucial part of your plan requires you to find how much time the guard robot would
need to reach your destination. If you can beat him, you’re through. See Figure 9.15.
We must warn you that the IRQ2003 land is not a pleasant place to roam. The
R:US have dropped numerous bombs while they invaded the human land. Most
of the bombs have exploded. Still some of the bombs remain, acting as land mines.
We have managed to get a map that shows the unsafe regions of the IRQ2003 land;
unfortunately your guard has a copy of the map, too. We know that at most 40 percent
of the area can be unsafe. If you are to beat your guard, you’d have to find his fastest
route long before he finds it.
Input
Input consists of several test cases. Each test begins with two integers R (1≤R≤1000),
C (1≤C≤1000)—they give you the total number of rows and columns in the grid
map of the land. Then follow the grid locations of the bombs. It starts with the
number of rows, (0≤rows≤R) containing bombs. For each of the rows, you’d have
one line of input. These lines start with the row number, followed by the number
of bombs in that row. Then you’d have the column locations of that many bombs
in that row. The test case ends with the starting location (row, column) followed by
your destination (row, column). All the points in the region are in the range (0,0)
to (R−1, C−1). Input ends with a test case where R=0 and C=0, and you must not
process this test case.
D
Sample input scenario
S: source, D: destination
Figure 9.15
Practice for State Space Search ◾ 667
Output
For each test case, print the time the guard robot would take to go from the starting
location to the destination.
10 10 18
9
0 1 2
1 1 2
2 2 2 9
3 2 1 7
5 3 3 6 9
6 4 0 1 2 7
7 3 0 3 8
8 2 7 9
9 3 2 3 4
0 0
9 9
0 0
Hint
Given an R×C grid map of the land, a robot can only move in four directions:
Forward, Backward, Upward, and Downward. There are bombs in some grids and
the robot can’t move into the grids. The problem requires you to calculate the short-
est path from the starting location to the destination.
BFS is used to calculate the shortest path. A state is represented as (x, y, s), where
your current location is (x, y), and the distance from the starting location to (x, y)
is s; and the visited sequence is represented as Vist[][], where Vist[x][y] is the mark
that (x, y) is visited.
The process for BFS is as follows:
9.4.5 Jugs
In the movie “Die Hard 3”, Bruce Willis and Samuel L. Jackson were confronted
with the following puzzle. They were given a three-gallon jug and a five-gallon jug
and were asked to fill the five-gallon jug with exactly four gallons. This problem
generalizes that puzzle.
You have two jugs, A and B, and an infinite supply of water. There are three
types of actions that you can use: (1) you can fill a jug, (2) you can empty a jug,
and (3) you can pour from one jug to the other. Pouring from one jug to the other
stops when the first jug is empty or the second jug is full, whichever comes first. For
example, if A has five gallons and B has six gallons and a capacity of eight gallons,
then pouring from A to B leaves B full and three gallons in A.
A problem is given by a triple (Ca, Cb, N), where Ca and Cb are the capacities
of the jugs A and B, respectively, and N is the goal. A solution is a sequence of steps
that leaves exactly N gallons in jug B. The possible steps are
fill A
fill B
empty A
empty B
pour A B
pour B A
success
where “pour A B” means “pour the contents of jug A into jug B”, and “success”
means that the goal has been accomplished.
You may assume that the input you are given does have a solution.
Input
Input to your program consists of a series of input lines each defining one puzzle.
Input for each puzzle is a single line of three positive integers: Ca, Cb, and N.
Ca and Cb are the capacities of jugs A and B, and N is the goal. You can assume
0<Ca≤Cb and N≤Cb≤1000 and that A and B are relatively prime to one another.
Practice for State Space Search ◾ 669
Output
Output from your program will consist of a series of instructions from the list of the
potential output lines which will result in either of the jugs containing exactly N gallons
of water. The last line of output for each puzzle should be the line “success”. Output lines
start in column 1 and there should be no empty lines nor any trailing spaces.
3 5 4 fill B
5 7 3 pour B A
empty A
pour B A
fill B
pour B A
success
fill A
pour A B
fill A
pour A B
empty B
pour A B
success
Hint
There are two methods to solve the problem.
Solution 1. Mathematic method.
An equation ax−by=c is used to represent the problem, where a and b are the
capacities of the jugs A and B respectively; x and y are the numbers pouring
water to jugs A and B respectively; and finally c gallons of water is left in jug B.
Each time, first water is poured into the jug with small capacity. Then water
is poured into the jug with larger capacity. The solution with minimum integers
is the solution to the problem. The equation can be solved by simulation.
Solution 2. BFS
1. The struct for a vertex p includes:
A state (a, b, opr); where p.a and p.b are the current amount of water in
jug A and jug B respectively, and p.opr are six actions numbered 0∼5,
and represent “fill A”, “fill B”, “empty A”, “empty B”, “pour A B”, and
“pour B A” respectively;
A precursor pointer p.pre pointing to the state generating p. When the
goal state (a, n, opr) is reached, a series of instructions can be output
through p.pre:
void Outpath(p);
{
if (p.pre != NULL) Outpath(*(p.pre));
output the instruction whose index is p.opr;
}
➀ The visited mark vis[][], where vis[a][b] shows the state that there are a gal-
lons and b gallons water in jug A and jug B respectively has been visited;
2. States are added into the queue:
Push (&t, h, a, b, opr) is used to add the state (a, b, opr) into the queue,
where t is the pointer pointing to the rear, h is the pointer pointing to the
front, and vis[a][b]=1, t++.
3. BFS is used to calculate a series of instructions
Practice for State Space Search ◾ 671
Input
The first line contains an integer T (T<20) indicating the number of test cases.
672 ◾ Algorithm Design Practice for Collegiate Programming
Each test case begins with a line containing four integers: f x f y tx ty (−5000≤f x,
f y, tx, ty ≤5000). The knight is originally placed at (f x, f y) and (tx, ty) is its destination.
The following line contains an integer m (0<m≤10), indicating how many kinds
of moves the knight can make.
Each of the following m lines contains two integers mx my (−10≤mx, my≤10;
|mx|+|my|>0), which means that if a knight stands at (x, y), it can move to (x+mx, y+my).
Output
Output one line for each test case. It contains an integer indicating the least number
of moves needed for the knight to reach its destination. Output “IMPOSSIBLE” if
the knight may never gets to its target position.
2 3
0 0 6 6 IMPOSSIBLE
5
1 2
2 1
2 2
1 3
3 1
0 0 5 5
2
1 2
2 1
Source: ACM 2010 Asia Fuzhou Regional Contest
IDs for Online Judges: POJ 3985, UVA 5098
Hint
Given an infinite chess board, an initial position and a destination, and some kinds
of moves the knight can make, you are required to calculate the least number of
moves for the knight from the initial position to the destination.
The algorithm is achieved by combining BFS and pruning.
The structure for elements in the queue is struct, and contains the knight’s cur-
rent coordinate (x, y); and the distance s, from the knight’s initial coordinate to
knight’s current coordinate.
Practice for State Space Search ◾ 673
Each time the front of the queue is removed, and m kinds of moves are enumer-
ated. If the knight’s new coordinate (x, y) is legal and isn’t in the queue, then the
new element q(q.x=x', q.y=y', q.s=p.s+1) is added into the queue, else the branch is
pruned.
{(
Suppose the longest moving distance d = max mx2i + m 2yi
1≤i ≤ m
)}; the initial position
is (sx, sy) and the destination is (tx, ty); a=ty−sy; b=sx−tx; and c=sy×tx−sx×ty.
We analyze cases that the knight’s new coordinate (x, y) are legal or not as
follows:
Case 1: If the square of the Euclidean distance between (x, y) and the initial
position (sx, sy) ((x−sx)2+(y−sy)2) isn’t larger than d, then (x, y) is legal;
Case 2: If the square of the Euclidean distance between (x, y) and the destina-
tion (tx, ty) ((x−tx)2+(y−ty)2) isn’t larger than d, then (x, y) is legal;
Case 3: If (x, y) deviates from the initial position (sx, sy), that is, (tx−sx)×
(x−sx)+(ty−sy)×(y−sy)<0, then (x, y) isn’t legal;
Case 4: If (x, y) deviates from the destination (tx, ty), that is, (sx−tx)×(x−tx)+
(sy−ty)×(y−ty)<0, then (x, y) isn’t legal;
Case 5: If the distance between (x, y) and the line segment (sx, sy)→(tx, ty) isn’t
more than d, that is, (a×x+b×y+c)2/(a 2+b2)≤d, then (x, y) is legal; else (x, y)
isn’t legal.
8 0 5 6
5 6
2 3
0 1
7 8
8 9
2 4 9 0
3 4 5 6 0 1 1 2
Figure 9.16
in the clockwise direction and pressing the one marked with the right arrow rotates
it by one digit in the opposite direction.
The game starts with an initial configuration of the wheels. Suppose that in the
initial configuration the topmost digits form the integer S1S2S3S4. You will be given
some (say, n) forbidden configurations Fi1Fi2Fi3Fi4 (1≤i≤n) and a target configura-
tion T1T2T3T4. Your job will be to write a program that can calculate the minimum
number of button presses required to transform the initial configuration to the
target configuration by never passing through a forbidden one.
Input
The first line of the input contains an integer N giving the number of test cases to
follow.
The first line of each test case contains the initial configuration of the wheels
specified by four digits. Two consecutive digits are separated by a space. The next
line contains the target configuration. The third line contains an integer n giving
the number of forbidden configurations. Each of the following n lines contains a
forbidden configuration.
There is a blank line between two consecutive input sets.
Output
For each test case in the input, print a line containing the minimum number
of button presses required. If the target configuration is not reachable, then
print −1.
Practice for State Space Search ◾ 675
2 14
8 0 5 6 −1
6 5 0 8
5
8 0 5 7
8 0 4 7
5 5 0 8
7 5 0 8
6 4 0 8
0 0 0 0
5 3 1 7
8
0 0 0 1
0 0 0 9
0 0 1 0
0 0 9 0
0 1 0 0
0 9 0 0
1 0 0 0
9 0 0 0
Hint
The problem can be represented as a connected graph, where each four-digit integer
is represented as a vertex. Because each integer can become eight other integers
through pressing buttons, the degree for each vertex is 8. In the graph, the weight of
edges is 1. The initial configuration is as the initial state. And the target configura-
tion is the goal state.
If we press a button marked with a left arrow, the corresponding digit becomes
(the original digit +1)%10; and if we press a button marked with a right arrow, the
corresponding digit becomes (the original digit +9)%10.
Because there are many test cases, the offline method can be used. First, the
graph is constructed. Then, for each test case, vertices for forbidden configurations
and their edges are deleted from the graph. Finally, the shortest path from the ini-
tial configuration’s vertex to the target configuration’s vertex is calculated by BFS
or SPFA. If there is such a path, the length of the path is the minimum number of
button presses required; else the target configuration is not reachable.
Bibliography
677
Index
A ancestor, 408–411
anniversary party (dynamic programming),
ad hoc problems 281–284
connect the cable wires, 43–44 analysis, 282–283
cow doctor, 38–40 program, 283–284
decode the tape, 32–34 annoying painting tool (greedy algorithm),
defined, 1 249–250
factorials, 35–36 hint, 250
find the telephone, 27–28 ants (computational geometry),
fractions, 34–35 530–531
mechanism analysis, 1–6 hint, 531
Minesweeper, 17–19 ants (statistical analysis), 6–9
parity, 30–31 analysis, 7–8
perfection, 12–13 program, 8–9
power, 42–43 area, 450–453
prerequisites, 22–23 analysis, 451
Rock, Scissors, Paper, 20–22 program, 451–453
Save Hridoy, 23–27 area (computational geometry),
Soundex, 16–17 535–537
squares, 36–38 hint, 537
statistical analysis, 6–12 area for union of rectangles, 469–480
stock graph, 31–32 area of simple polygons (computational
Tic Tac Toe, 19–20 geometry), 581–582
2 the 9s, 28–29 hint, 582
uniform generator, 14–15 art gallery (polar angles), 491–495
WERTYU, 15–16 analysis, 492–493
wine trading, 40–42 program, 493–495
you can say 11, 29–30 articulation points, 408–420. See also graph
add all (greedy algorithm), 226–228 algorithms
analysis, 227 A-sequence (simulation problem), 86–87
program, 227–228 hint, 87
addition chains (state space search), 663–665 Atlantis (sweep line algorithm), 477–480
hint, 664–665 analysis, 478
IDA* algorithm for, 665 program, 478–480
always on the run (dynamic programming),
313–315
hint, 314–315 B
anagram, 202–204 back edge, 409
hint, 204 backward search, 592
679
680 ◾ Index
N program, 168–171
widths and heights for enclosing rectangles,
nails (computational geometry), 563–564 164–167
hint, 564 packing rectangles (simulation problem),
necklace (graph algorithm), 436–437 94–97
hint, 437 calculation of area by enumeration, 97
necklace of beads (Pólya counting formula), calculation of length and width, 97
191–194 hint, 95–97
analysis, 192 palindrome (dynamic programming), 302–303
program, 192–194 hint, 303
network (graph algorithm), 414–417 paper cutting (construction simulation), 75–77
analysis, 415 program, 77
program, 415–417 parallelogram, 445, 449, 457
new villa (state space search), 600–606 parity, 30–31
analysis, 601–602 hint, 31
program, 602–606 Pass-Muraille (greedy algorithm), 215–219
9-degree of N, 28–29 analysis, 217
NP-Complete Problems, 234 hint, 217
number theory, 12, 99–151 program, 218–219
indeterminate equations and congruence, pawn chess (game tree), 650–654
113–126 analysis, 651–652
multiplicative functions, 126–132 program, 652–654
prime numbers, 99–112 perfect numbers, 12–13
nuts for nuts (dynamic programming), perfect pth powers
284–287 hint, 144
analysis, 285–286 perfection (ad hoc problem), 12–13
program, 286–287 hint, 13
nuts for nuts (traveling salesman problem), permutation group, 186–188
396–399 permutations, 205–206. See also combinatorics
analysis, 396–397 hint, 206
program, 397–399 permutations, generating, 153–159
all permutations based on lexicographic
O order, 157–159
fast, sorted permutation, 157–159
obtuse angle, 444 next permutation based on lexicographic
open intervals, 428 order, 153–157
optimal solution, 75, 215, 217, 222, 250, 259–260 perpendicular bisector, 461, 496
optimal substructures, 215 phi-function formula, 127
optimization problems, 215, 259, 260, 432 pick up (line segment intersection), 453–457
origin, 443, 449–450, 529, 537, 564–567, 566 analysis, 455
orthocenter, 576–577 program, 455–457
picnic (computational geometry), 570–572
P hint, 572
picture (computational geometry), 577–579
package pricing (state space search), 616–623 hint, 578–579
program, 619–623 pieces of land (polyhedron), 466–469
packets (construction simulation), 72–74 analysis, 467
analysis, 73–74 program, 467–469
program, 74 pigeonhole principle, 178–180. See also
packing rectangles (combinatorics), 163–171 combinatorics
analysis, 164–168 pipe (computational geometry), 523–525
minimal enclosing rectangle, 167–168 hint, 525
Index ◾ 687
Q hint, 667
program, 596–599
QWERTY keyboard, 15–16 Rock, Scissors, Paper (ad hoc problem),
20–22
R hint, 21–22
rock-paper-scissors (simulation of direct
radar installation (greedy algorithm), 231–234 statement), 48–50
analysis, 232 analysis, 49
program, 233–234 program, 49–50
radius, 446–448, 463, 472, 484, 503, 516, 556 rocks (simulation problem), 84–86
rain collection (computational geometry), hint, 86
539–541 rotating caliper, 506, 509, 561, 574–575, 582
hint, 540–541 rotating scoreboard (computational geometry),
rank arrays, 335–339 549–550
rectangle, 525 hint, 550
area for union of, 469–480 round pet in a ground hole (computational
rectangles (simulation problem), 94–97 geometry), 527–529
calculation of area by enumeration, 97 hint, 528–529
calculation of length and width, 97
hint, 95–97 S
reduced residue system modulo n, 127
relatively prime integers, 113, 118, 120–121, Save Hridoy (ad hoc problem), 23–27
126–129, 668 hint, 27
relatives, 128–130 scrambled polygon (computational geometry),
analysis, 129 564–567
program, 129–130 hint, 567
remainder, 86, 179, 639 search space, 591
Remmarguts’ date (state space search), 632–637 segment trees, 357–381
analysis, 633–634 calculating the area for union of rectangles,
program, 634–636 470, 472, 477
Renju game (simulation by sieve method), calculating visible segments, 369–374
64–67 constructing, 372
analysis, 66 definition of, 357
program, 66–67 disjoint segments, 374–381
rivers (dynamic programming), 323–326 fundamental operations for, 358–359
hint, 325–326 subintervals, 364–381
road accident (computational geometry), updating and calculating disjoint segments,
541–542 374–381
constraints, 542 updating data uniformly and calculating
hint, 542 data dynamically in subinterval,
road construction (graph algorithm), 417–420 365–369
analysis, 418–419 updating single points in, 360–364
program, 419–420 updating subintervals in, 364–381
robbery (dynamic programming), 311–313 segments, 511–512
hint, 312–313 hint, 512
Robocode (simulation of direct statement), sequential search, 591
50–56 Seven Bridges of Konigsberg problem, 432
analysis, 53 shoemaker’s problem (greedy algorithm),
program, 54–56 223–226
robot (state space search), 594–599, 665–668 analysis, 224–225
analysis, 596–597 program, 225–226
BFS algorithm for, 667–668 sieve + trial division, 110
690 ◾ Index
who gets the most candies? (segment trees), wind trading (ad hoc problem), 40–42
425–426 hint, 41–42
hint, 425–426 winning move (game tree), 643–650
widget factory (number theory problem), analysis, 644–646
138–140 program, 646–650
hint, 140 wooden sticks (greedy algorithm), 228–231
Wild West (computational geometry), 542–545 analysis, 229–230
hint, 544–545 program, 230–231