UVa Problem 10065 Useless Tile Packers (没用的瓷砖打包公司)

来源:互联网 发布:api接口 聚合数据 编辑:程序博客网 时间:2024/04/30 16:50
// Useless Tile Packers (没用的瓷砖打包公司)// PC/UVa IDs: 111405/10065, Popularity: C, Success rate: average Level: 3// Verdict: Accepted// Submission Date: 2011-11-06// UVa Run Time: 0.020s//// 版权所有(C)2011,邱秋。metaphysis # yeah dot net//// [解题方法]// 简单的求凸包和面积问题,思考后解决应该不难。#include <iostream>#include <algorithm>#include <iomanip>#include <cmath>using namespace std;#define MAXPOLY 105struct point{int x;int y;};struct polygon{int vertexNumber;point vertex[MAXPOLY];};// 利用有向面积计算多边形的面积,注意最后结果取绝对值,因为顶点顺序可能并不是按逆时针方向给出。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);}// 叉积,判断点 first,second,third 组成的两条线段的转折方向。当叉积大于 0,则形成一个右拐,// 否则共线(cp = 0)或左拐(cp > 0)。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);}// Andrew 凸包扫描算法的预排序,先按 x 坐标排序,若 x 坐标相同,则按 y 坐标排序。bool left_lower(point first, point second){if (first.x == second.x)return first.y < second.y;elsereturn first.x < second.x;}// Andrew 凸包扫描算法。void convex_hull(point vertex[], int vertexNumber, polygon &container){// 点个数小于等于三个,构成凸包。if (vertexNumber <= 3){for (int i = 0; i < vertexNumber; i++)container.vertex[i] = vertex[i];container.vertexNumber = vertexNumber;return;}// 排序。sort(vertex, vertex + vertexNumber, left_lower);point upper[MAXPOLY], lower[MAXPOLY];int top;// 求上凸包。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];// 求下凸包。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++;}// 合并下凸包。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;}


原创粉丝点击