uva 10065 (凸包+求面积)

本文提供UVA在线评测系统中编号10065的问题——Useless Tile Packers的解题思路及代码实现。该问题要求计算特定形状瓷砖放入定制容器后浪费的空间百分比。

链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=&problem=1006

Problem A

Useless Tile Packers

Input: standard input

Output: standard output

 

Yes, as you have apprehended the Useless Tile Packers (UTP) pack tiles. The tiles are of uniform thickness and have simple polygonal shape. For each tile a container is custom-built. 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. But this strategy leads to wasted space inside the container.

 

                             

 

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 (xy) co-ordinates 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 co-linear.

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.

 

 

Sample Input

5
0 0
2 0
2 2
1 1
0 2
5
0 0
0 2
1 3
2 2
2 0
0

 

Sample Output

Tile #1
Wasted Space = 25.00 %

Tile #2
Wasted Space = 0.00 %

________________________________________________________________________________
Rezaul Alam Chowdhury

 

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

让求空闲的面积,简单转化一下,就是求建造凸包之前的面积,以及建造凸包之后的面积,相减,再相除即可

犯了个好傻的毛病,把求叉乘积的函数,以及距离的函数类型定义为bool,搞的一直出不来结果,最后调试两遍才发现,汗!!!

 

 1 #include <stdio.h>
 2 #include <math.h>
 3 #include <string.h>
 4 #include <stdlib.h>
 5 #include <iostream>
 6 #include <algorithm>
 7 
 8 using namespace std;
 9 #define MAXX 105
10 #define eps 1e-8
11 
12 typedef struct point
13 {
14     double x;
15     double y;
16 }point;
17 
18 bool xy(double x,double y){ return x<y-eps; }
19 bool dy(double x,double y){ return x>y+eps; }
20 bool xyd(double x,double y){ return x<y+eps; }
21 bool dyd(double x,double y){ return x>y-eps; }
22 bool dd(double x,double y){ return fabs(x-y)<eps; }
23 
24 double crossProduct(point a,point b,point c)
25 {
26     return (c.x-a.x)*(b.y-a.y)-(c.y-a.y)*(b.x-a.x);
27 }
28 double dist(point a,point b)
29 {
30     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
31 }
32 
33 point p[MAXX];
34 point stk[MAXX];
35 int top;
36 
37 bool cmp(point a,point b)
38 {
39     double len=crossProduct(p[0],a,b);
40     if(dd(len,0.0))
41     {
42         return xy(dist(p[0],a),dist(p[0],b));
43     }
44     return xy(len,0.0);
45 }
46 
47 void Graham(int n)
48 {
49     int tmp=0;
50     for(int i=1; i<n; i++)
51     {
52         if(xy(p[i].x,p[tmp].x) || dd(p[i].x,p[tmp].x) && xy(p[i].y,p[tmp].y))
53         {
54             tmp=i;
55         }
56     }
57     swap(p[0],p[tmp]);
58     sort(p+1,p+n, cmp);
59 
60     stk[0]=p[0];
61     stk[1]=p[1];
62     top=1;
63     for(int i=2; i<n; i++)
64     {
65         while(top && xyd(crossProduct(stk[top],stk[top-1],p[i]),0.0))
66             top--;
67         stk[++top]=p[i];
68     }
69 }
70 
71 double Area(int n,point ss[])
72 {
73     double ans=0.0;
74     for(int i=2; i<n; i++)
75     {
76         ans+=crossProduct(ss[0],ss[i-1],ss[i]);//printf("%lf^^\n",ans);
77     }
78     return fabs(ans)/2.0;
79 }
80 
81 int main()
82 {
83     int n,m,i,j;
84     int cas=1;
85     while(scanf("%d",&n)!=EOF &&n)
86     {
87         for(i=0; i<n; i++)
88             scanf("%lf%lf",&p[i].x,&p[i].y);
89         double ans_min=Area(n,p);
90         Graham(n);//printf("%d--",top);
91         double ans_max=Area(top+1,stk);
92         printf("Tile #%d\n",cas++);
93         printf("Wasted Space = %.2lf %%\n\n",(ans_max-ans_min)/ans_max*100);
94     }
95     return 0;
96 }
View Code

 

第一道uva的题,做个纪念、uva 的邮件

××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

Hi,

This is an automated response from UVa Online Judge.

Your submission with number  14050702 for the problem  10065 - Useless Tile Packers has succeeded with verdict  Accepted.

Congratulations! Now it is time to try a new problem.

Best regards,

The UVa Online Judge team
×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

 

转载于:https://www.cnblogs.com/ccccnzb/p/3916975.html

<think>好的,用户想用C#实现计算凸包面积,我需要先理解凸包面积的计算方法。首先,凸包是一个凸多边形,面积计算通常使用多边形面积公式。根据引用[2],Jarvis算法可以用来找到凸包的顶点集合,但用户现在需要的是如何根据这些顶点计算面积。 我记得多边形面积的公式是,对于按顺序排列的顶点,可以用Shoelace公式。也就是将顶点坐标按顺序相乘再相减,最后取绝对值的一半。比如顶点为$(x_1,y_1), (x_2,y_2), ..., (x_n,y_n)$,面积等于$\frac{1}{2} | \sum_{i=1}^{n}(x_i y_{i+1} - x_{i+1} y_i) |$,其中$x_{n+1}=x_1$,$y_{n+1}=y_1$。 那如何在C#中实现呢?首先需要确保凸包的顶点是按顺时针或逆时针顺序排列的。根据引用[4],cv::convexHull生成的凸包顶点是按顺时针排列的,但不确定C#中的实现是否也是如此。不过Shoelace公式无论顺序如何,只要顶点是闭合的循环,就能正确计算,只需要取绝对值。 所以步骤应该是:1. 获取凸包的顶点集合,按顺序排列。2. 应用Shoelace公式计算面积。 现在需要编写C#代码。首先,需要Point类,可能用System.Drawing中的PointF或者自定义。然后,计算面积的函数接受点的列表,遍历每个点,累加$x_i * y_{i+1} - x_{i+1} * y_i$,最后取绝对值的一半。 需要注意顶点是否闭合,比如最后一个点是否和第一个点相连。比如,顶点列表是否包含起始点的重复,或者在计算时是否需要将最后一个点连接到第一个点。在代码中,循环到n-1,然后单独处理最后一个点和第一个点的乘积。 例如,假设points是凸包的顶点列表,按顺序排列。循环i从0到points.Count-1,计算points[i].X * points[i+1].Y - points[i+1].X * points[i].Y,当i是最后一个时,i+1是0。或者,将points复制一份,加上第一个点到末尾,这样可以统一处理。 此外,还需要确保凸包至少有三个点,否则面积为0。同时处理可能的空集合或无效输入。 结合引用[2]中的ConvexHull类,假设已经通过GetConvexHull方法获得了顶点集合,那么可以在这个基础上添加计算面积的方法。或者单独写一个计算面积的静态方法,接受点集合参数。 现在将代码部分整理出来,确保使用正确的C#语法,例如使用List<PointF>,处理浮点坐标。然后,在示例中展示如何调用该方法,并输出结果。 用户可能需要完整的示例,包括如何生成凸包然后计算面积。所以可能需要先给出生成凸包的代码(基于引用[2]的步骤),再添加面积计算的部分。 但用户的问题主要是计算面积,所以重点放在面积算法上。因此,示例代码可以假设已经获得了凸包的顶点,然后应用Shoelace公式。 综上,步骤是:实现一个计算凸包面积的静态方法,使用Shoelace公式,处理顶点列表的顺序,返回面积值。</think>以下是使用C#实现计算凸包面积的详细步骤及代码示例: ### 1. 计算凸包面积的数学原理 凸包是一个凸多边形,面积计算采用**鞋带定理(Shoelace Formula)**。对于按顺序排列的顶点$(x_1,y_1),(x_2,y_2),...,(x_n,y_n)$,面积公式为: $$S = \frac{1}{2} \left| \sum_{i=1}^{n}(x_i y_{i+1} - x_{i+1} y_i) \right|$$ 其中$x_{n+1}=x_1$, $y_{n+1}=y_1$[^4]。 ### 2. C#实现步骤 1. **定义点结构体**:存储坐标信息 2. **实现面积计算函数**:输入凸包顶点集合,返回面积值 3. **处理顶点顺序**:确保顶点按顺时针/逆时针顺序排列 ### 3. 完整代码实现 ```csharp using System; using System.Collections.Generic; public struct Point { public double X { get; } public double Y { get; } public Point(double x, double y) { X = x; Y = y; } } public class ConvexHullCalculator { // 使用鞋带定理计算凸包面积 public static double CalculateConvexHullArea(List<Point> hullPoints) { if (hullPoints == null || hullPoints.Count < 3) return 0; double area = 0; int n = hullPoints.Count; for (int i = 0; i < n; i++) { int j = (i + 1) % n; area += hullPoints[i].X * hullPoints[j].Y; area -= hullPoints[i].Y * hullPoints[j].X; } return Math.Abs(area) / 2.0; } } // 使用示例 public class Program { public static void Main() { // 示例凸包顶点(需按顺序排列) var convexHull = new List<Point> { new Point(0, 0), new Point(4, 0), new Point(4, 3), new Point(0, 3) }; double area = ConvexHullCalculator.CalculateConvexHullArea(convexHull); Console.WriteLine($"凸包面积: {area}"); // 输出:12 } } ``` ### 4. 关键点说明 1. **顶点顺序要**:算法不依赖具体排列方向(顺时针/逆时针),但必须保证顶点连续闭合 2. **复杂度**:时间复杂度为$O(n)$,适用于任意凸多边形 3. **精度处理**:使用double类型保证计算精度 4. **异常处理**:当顶点数小于3时直接返回0 ### 5. 结合凸包生成的完整流程 若需要从原始点集生成凸包后计算面积,可结合Jarvis算法(礼物包装算法)[^2]: ```csharp // 补充凸包生成代码(基于引用[2]的实现) public class ConvexHull { public List<Point> GetConvexHull(List<Point> points) { // 实现Jarvis算法获取凸包顶点 // (具体实现参考引用[2]的步骤) } } // 完整使用流程: var rawPoints = new List<Point> { /* 原始点数据 */ }; var hullPoints = new ConvexHull().GetConvexHull(rawPoints); double area = ConvexHullCalculator.CalculateConvexHullArea(hullPoints); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值