1.
/**
* FWP, Ausgewählte Probleme aus dem ACM Programming Contest
* Problem: 11612 - Sultan and Khairun
Shundori
* Link:
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=78&problem=2659
*
*
* Method : Geometry (ad hoc)
* Status : Accepted
* Runtime: 0.964
*
* @author Evgeni Pavlidis
* @version 1.0, 30/10/2010
*/
import java.io.*;
import java.util.*;
class Point implements Comparable<Point>
{
int x,y,number;
double crossProduct;
Point(int number, int x, int y)
{
this.x = x;
this.y = y;
this.number = number;
}
public int compareTo(Point o)
{
if(o.y > y)
return -1;
if(o.y == y)
return 0;
return 1;
}
public String toString()
{
return
String.format("{%d}_(%d,%d)", number, x, y);
}
public int hashCode()
{
return (x << 16) &
y;
}
}
class Main
{
static StreamTokenizer st = new StreamTokenizer(new
BufferedReader(new InputStreamReader(System.in)));
static int nextInt() throws IOException
{
st.nextToken();
return (int)st.nval;
}
static double crossProduct(Point m, Point a, Point b)
{ return (a.x - m.x)*(b.y - m.y) -
(b.x - m.x)*(a.y - m.y); }
static final double EPSILON = 1e-20;
public static void main(String...args) throws
Exception
{
StringBuffer output = new
StringBuffer();
int n, startPos = 0;
// lower left and upper
right points
Point left, right;
Point home, p;
// indicate if we have
points upward/below the separation line
boolean up, down;
// container for the points
Set<Point> set = new
HashSet<Point>();
// set of points that lie
above the line between lower-left most
// and upper-right most
points - the key is the x coordinate
Map<Integer,
Set<Point>> upper = new HashMap<Integer,
Set<Point>>();
// set of points that lie
below and on the line
Map<Integer,
Set<Point>> lower = new HashMap<Integer,
Set<Point>>();
// save the x coordinates to
inspect
TreeSet<Integer> sweep
= new TreeSet<Integer>();
// save the loop series
(from left to right)
Point[] series = new
Point[1000];
while(true)
{
set.clear();
lower.clear();
upper.clear();
sweep.clear();
up =
down = false;
n =
nextInt();
if(n
== 0)
break;
left
= right = home = new Point(0, nextInt(), nextInt());
set.add(home);
sweep.add(home.x);
upper.put(home.x, new TreeSet<Point>());
lower.put(home.x, new TreeSet<Point>());
//
init all structures and find lower-left and uppper-right points
for(int i = 1; i < n; i++)
{
p
= new Point(i, nextInt(), nextInt());
if(p.x
< left.x || (p.x == left.x && p.y < left.y))
left
= p;
if(p.x
> right.x || (p.x == right.x && p.y > right.y))
right
= p;
if(!upper.containsKey(p.x))
upper.put(p.x,
new TreeSet<Point>());
if(!lower.containsKey(p.x))
lower.put(p.x,
new TreeSet<Point>());
sweep.add(p.x);
set.add(p);
}
//
check where each point lies
double test;
for(Point point: set)
{
point.crossProduct
= crossProduct(left, right, point);
if(point.crossProduct
- EPSILON > 0)
up
= true;
if(point.crossProduct
+ EPSILON < 0)
down
= true;
}
if(!up && !down) // all points lie on a line
{
output.append("no
solution\n");
continue;
}
//
divide set of point into two groups: above and below the line
for(Point point: set)
if(Math.abs(point.crossProduct)
< EPSILON)
{
if(!up)
// build two groups to be able to make a loop
upper.get(point.x).add(point);
else
lower.get(point.x).add(point);
}
else
if(point.crossProduct - EPSILON > 0)
upper.get(point.x).add(point);
else
lower.get(point.x).add(point);
//System.out.println(upper);
//System.out.println(lower);
//
build loop series
int
pos = 0;
for(int x: sweep)
for(Point
point: upper.get(x))
{
if(point
== home)
startPos
= pos;
series[pos++]
= point;
}
for(int x: sweep.descendingSet())
for(Point
point: ((TreeSet<Point>)lower.get(x)).descendingSet())
{
if(point
== home)
startPos
= pos;
series[pos++]
= point;
}
if(series[startPos].number != 0 || n != pos)
throw
new RuntimeException();
pos
= startPos;
for(int i = 0; i < n; i++, pos = ((pos+1) % n) )
output.append(series[pos].number
+ " ");
output.append("0\n");
}
System.out.print(output);
}
}