// Useless tile packers (useless tile packaging company) // PC/Ultraviolet IDs: 111405/10065, popularity: C, success rate: average level: 3 // verdict: accepted // submission date: 2011-11-06 // UV Run Time: 0.020 S // All Rights Reserved (c) 2011, Qiu. Metaphysis # Yeah dot net /// [solution] // simply solve the problem of convex hull and area. It is not difficult to solve the problem after thinking about it. # Include <iostream> # include <algorithm> # include <iomanip> # include <cmath> using namespace STD; # define maxpoly 105 struct point {int X; int y ;}; struct polygon {int vertexnumber; point vertex [maxpoly] ;}; // calculate the area of the polygon using the directed area. Pay attention to the absolute value of the final result, because the vertex order may not be given in the clockwise direction. Double area (point vertex [], int vertexnumber) {double Total = 0.0; For (INT I = 0; I <vertexnumber; I ++) {Int J = (I + 1) % vertexnumber; Total + = (vertex [I]. x * vertex [J]. y-vertex [J]. x * vertex [I]. y);} return FABS (total/2.0);} // cross product, judge the turning direction of the two line segments composed of the first, second, and third. When the cross area is greater than 0, a right turn is formed. // otherwise, the cross Line (Cp = 0) or left turn (CP> 0) is formed ). Int crossproduct (point first, point second, point third) {return (second. x-first. x) * (third. y-first. y)-(second. y-first. y) * (third. x-first. x);} // pre-sorting of the Andrew convex packet scanning algorithm. The algorithm is first sorted by X coordinates. If X coordinates are the same, the algorithm is sorted by Y coordinates. Bool left_lower (point first, point second) {If (first. X = second. x) return first. Y <second. y; elsereturn first. x <second. x;} // Andrew convex packet scanning algorithm. Void convex_hull (point vertex [], int vertexnumber, polygon & container) {// The number of points is less than or equal to three, forming a convex hull. If (vertexnumber <= 3) {for (INT I = 0; I <vertexnumber; I ++) container. vertex [I] = vertex [I]; container. vertexnumber = vertexnumber; return;} // sort. Sort (vertex, vertex + vertexnumber, left_lower); point upper [maxpoly], lower [maxpoly]; int top; // top convex hull. Upper [0] = vertex [0]; upper [1] = vertex [1]; Top = 2; for (INT I = 2; I <vertexnumber; I ++) {upper [Top] = vertex [I]; while (top> = 2 & crossproduct (upper [Top-2], upper [Top-1], upper [Top])> = 0) {upper [Top-1] = upper [Top]; top --;} top ++;} container. vertexnumber = 0; For (INT I = 0; I <top; I ++) container. vertex [container. vertexnumber ++] = upper [I]; // calculate the lower convex hull. Lower [0] = vertex [vertexnumber-1]; lower [1] = vertex [vertexnumber-2]; Top = 2; for (INT I = vertexnumber-3; i> = 0; I --) {lower [Top] = vertex [I]; while (top> = 2 & crossproduct (lower [Top-2], lower [Top-1], lower [Top])> = 0) {lower [Top-1] = lower [Top]; top --;} top ++ ;} // merge the lower convex hull. For (INT I = 1; I <top-1; I ++) container. vertex [container. vertexnumber ++] = lower [I];} int main (INT AC, char * AV []) {point tile [maxpoly]; polygon container; int vertexnumber, currentcase = 1; cout. precision (2); cout. SETF (IOs: Fixed | IOs: showpoint); While (CIN> vertexnumber, vertexnumber) {for (INT I = 0; I <vertexnumber; I ++) {CIN> tile [I]. x; CIN> tile [I]. y;} double used = Area (tile, vertexnumber); convex_hull (tile, vertexnumber, container); cout <"tile #" <currentcase ++ <Endl; double all = Area (container. vertex, container. vertexnumber); double rate = (1.0-used/All) * 100.0; cout <"wasted space =" <rate <"%" <Endl; cout <Endl;} return 0 ;}