鱼C论坛

 找回密码
 立即注册
查看: 3081|回复: 2

[技术交流] 046:Texas Trip(最小正方形覆盖)

[复制链接]
发表于 2018-2-18 20:49:13 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
Description

After a day trip with his friend Dick, Harry noticed a strange pattern of tiny holes in the door of his SUV. The local American Tire store sells fiberglass patching material only in square sheets. What is the smallest patch that Harry needs to fix his door?

Assume that the holes are points on the integer lattice in the plane. Your job is to find the area of the smallest square that will cover all the holes.

Input

The first line of input contains a single integer T expressed in decimal with no leading zeroes, denoting the number of test cases to follow. The subsequent lines of input describe the test cases.

Each test case begins with a single line, containing a single integer n expressed in decimal with no leading zeroes, the number of points to follow; each of the following n lines contains two integers x and y, both expressed in decimal with no leading zeroes, giving the coordinates of one of your points.

You are guaranteed that T ≤ 30 and that no data set contains more than 30 points. All points in each data set will be no more than 500 units away from (0,0).

Output

Print, on a single line with two decimal places of precision, the area of the smallest square containing all of your points.

Sample Input

2
4
-1 -1
1 -1
1 1
-1 1
4
10 1
10 -1
-10 1
-10 -1
Sample Output

4.00
242.00

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2018-2-18 20:53:49 | 显示全部楼层
题目描述

在与Dick一天的旅行之后,Harry在自己SUV的车门上发现了几个奇怪的小孔。而当地的维修店只出售正方形的玻璃纤维修补材料。现在,我们把车门上的小孔当做位于平面上整数坐标的点,问: 至少要一块多大面积的正方形修补材料才能覆盖住所有的小孔?

输入

第一行包含一个整数T (T ≤ 30),表示有T组测试数据。

对于每一组数据,第一行包含一个整数n (n ≤ 30),表示有n个小孔。接下来有N行,每行两个整数X和Y,分别表示一个小孔的横坐标和纵坐标。输入数据保证每一个小孔距离原点(0,0)不超过500个单位距离。

输出

对于每一组数据,输出一个两位小数,表示正方形材料的最小面积。


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-2-18 20:55:25 | 显示全部楼层
本题应用了三分算法,参考文章http://blog.csdn.net/littlewhite520/article/details/70144763


给出平面上一些点(坐标),让我们在平面上选择一个正方形能够覆盖这些所有的点,求这个正方形的最小面积。



我们很容易找到一个符合要求的正方形,也就是所有边都平行于坐标轴的正方形,那么我们就只找平行于坐标轴的正方形,我们将每个点都旋转一定的角度,他们的相对位置不变,而正方形却相对于点在旋转,面积在改变,那么就可以找到最小的正方形.

我们只需要考虑最优的旋转角度.

假设旋转的角度为f,初始点的坐标为(x,y)与x轴的夹角为a,距离坐标原点的长度为len,那么x = cos(a)*len,y = sin(a)*len,nx = cos(a+f)*len,ny = sin(a+f)*len

拆开nx = cos(a)*cos(f)*len-sin(a)*sin(f)*len,ny = sin(a)*cos(f)*len+cos(a)*sin(f)*len

也就是说 nx = cos(f)*x-sin(f)*y,ny = sin(f)*x+cos(f)*y;

正方形的边长等于max(rightx-leftx,upy-downy) = max(cos(f)*(x1-x2)-sin(f)*(y1-y2),sin(f)*(x1-x2)+cos(f)*(y1-y2))(x1>x2 &&  y1>y2)

等于 max(sqrt((x1-x2)^2+(y1-y2)^2)sin(f+p1),sqrt((x1-x2)^2+(y1-y2)^2)sin(f+p2))

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<algorithm>
  4. #include<cmath>
  5. #define maxn 31
  6. #define pi acos(-1.0)
  7. #define eps 1e-12
  8. #define inf 0xfffffff

  9. using namespace std;

  10. struct E
  11. {
  12.         double x,y;
  13.         E toa(double a)
  14.         {
  15.                 E ans;
  16.                 ans.x=x*cos(a)-y*sin(a);
  17.                 ans.y=x*sin(a)+y*cos(a);
  18.                 return ans;
  19.         }
  20.        
  21. }a[maxn];
  22. int T,n;
  23. double cal(double x)
  24. {
  25.         double minx=inf,miny=inf;
  26.         double maxx=-inf,maxy=-inf;
  27.         for(int i=1;i<=n;i++)
  28.         {
  29.                 E ans;
  30.                 ans=a[i].toa(x);
  31.                 minx=min(minx,ans.x),miny = min(miny,ans.y);
  32.         maxx = max(maxx,ans.x),maxy = max(maxy,ans.y);       
  33.         }
  34.         return max(maxx-minx,maxy-miny);
  35. }
  36. int main()
  37. {
  38.         scanf("%d",&T);
  39.         while(T--)
  40.         {
  41.                 scanf("%d",&n);
  42.                 for(int i=1;i<=n;i++)
  43.                         scanf("%lf%lf",&a[i].x,&a[i].y);
  44.                 double l=0,r=pi,mid,mmid;
  45.                 while(l+eps<r)
  46.                 {
  47.                         mid=(l+r)/2;
  48.                         mmid=(mid+r)/2;
  49.                         if(cal(mid)>cal(mmid))
  50.                                 l=mid;
  51.                         else
  52.                                 r=mmid;
  53.                 }
  54.                 double len=cal(l);
  55.                 printf("%.2lf\n",len*len);
  56.         }
  57.         return 0;
  58. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-3-29 21:01

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表