2016.08.07计算几何总结测试day2

T1 bzoj: [Usaco2010 OPen]Triangle Counting 数三角形

看到这个题n那么大, 于是想到极角排序搞一搞,然而排完序后立马懵逼,完全不知道接下来应该怎么写。。。。

盯了好久题目给的图后全无思路于是手绘图,然后我就发现了秘密。。。。

极角排序后,如果两个点能与另外的某一个点构成黄金三角形,那么那个点必然在这两个点与原点连线的延长线所夹的区间内。

又因为有极角排序,点a[1],a[2]能构成的三角形,换成点a[1],a[3]肯定也可以构成,因为它们的区间一定是包含关系。

于是我们搞出所有a[i],a[i-1]区间内的答案,计算对答案的贡献即可。

正着有i-1个区间包含它,反着有n-i个区间包含它,然后搞一搞就好了。。。

细节什么的参见代码,反正感觉我代码是写丑了,我还算出了j搞了两遍for循环,看他们代码一个个巨短。。。。理应一遍就应该可以了吧。。。。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 #define maxn 100100
 8 #define pi (acos(-1.0))
 9
10 int n,j,tmp,sum;
11 long long ans;
12
13 struct point{
14     double x,y,ang;
15 }p[maxn];
16
17 double operator *(point a,point b){return a.x*b.y-a.y*b.x;}
18
19 bool cmp(point a,point b){
20     return a.ang<b.ang;
21 }
22
23 int main(){
24 //  freopen("input.txt","r",stdin);
25 //  freopen("output.txt","w",stdout);
26     scanf("%d",&n);
27     for (int i=1;i<=n;i++)
28         scanf("%lf%lf",&p[i].x,&p[i].y),p[i].ang=atan2(p[i].y,p[i].x);
29     sort(p+1,p+n+1,cmp);
30     for (int i=1;i<=n;i++) if (p[i].ang-p[1].ang>pi){j=tmp=i;break;}
31     for (int i=2;i<j;i++){
32         int sum=0;
33         while (p[tmp].ang-p[i].ang<pi && tmp<=n) tmp++,sum++;
34         ans+=(long long)sum*(i-1)*(j-i);
35     }
36     for (int i=1;i<j;i++) if (p[j].ang-p[i].ang<pi){tmp=i;break;}
37     for (int i=j+1;i<=n;i++){
38         int sum=0;
39         while (p[i].ang-p[tmp].ang>pi && tmp<j) tmp++,sum++;
40         ans+=(long long)sum*(i-j)*(n-i+1);
41     }
42     printf("%lld\n",ans);
43     return 0;
44 }

T1

T2 poj 3608 Bridge Across Islands

两个多边形间的旋转卡壳,网上给了一大堆代码,一大堆题解,感觉都大同小异,几乎都是国外某大牛的论文翻译过来的。。。。。什么搞出一个ymin,ymax,特别是哪个叉乘while,根本看不懂。。。。。线段之间的距离真的可以用叉乘吗。。。。。(蒟蒻求解。。。)

于是我有一种想法,首先在多边形P上随便找到一条边,然后找到多边形Q上距离最近的点,然后将多边形P上的该边跳到它的邻边,同时直接移动多边形Q上找到的点,和两边的点比较,之后移动,直到移动到下一个点的距离比该点距离大就停止。然后在多边形Q上也做一次类似的即可。然后每次移动更新答案,就完了。。。。。

感觉这样做正确性也十分显然,因为对于任意一条边,另一个多边形的所有点距离它都是单峰的。于是对于当前点,它一定能找到距离最近的点。注意这里并不用两个指针扫,只需要将当前点与左右两边比较就行了。因为不可能出现左右两边的点都比当前点更优的情况,因为当前点一定是左右两边的某个点转移过来的,而对于当前的边,它一定会比至少一条边优。(这个性质稍微分情况讨论一下也可以得出),同时因为边每次只是跳到邻边,因此绝对不会出现每次移动n/2的情况,因为这个过程类似于旋转卡壳实现过程,时间复杂度也是可以保证的,常数好像大了一些。。。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 #define maxn 100010
 8 #define inf 1e9
 9
10 int n,m;
11 double ans;
12
13 struct point{
14     double x,y;
15 }p[maxn],q[maxn];
16
17 struct line{
18     point from,to;
19 }lp[maxn],lq[maxn];
20
21 point operator -(point a,point b){return (point){a.x-b.x,a.y-b.y};}
22 double operator *(point a,point b){return a.x*b.y-a.y*b.x;}
23
24 double sqr(double x){return x*x;}
25 double dis(point a,point b){return sqr(a.x-b.x)+sqr(a.y-b.y);}
26
27 double point_line_dis(point a,line b){
28     if (dis(b.to,b.from)+min(dis(a,b.to),dis(a,b.from))<max(dis(a,b.to),dis(a,b.from)))
29     return sqrt(min(dis(a,b.to),dis(a,b.from)));
30     else return fabs((b.to-a)*(b.from-a))/sqrt(dis(b.to,b.from));
31 }
32
33 void solvep(){
34     double dist=inf;int pos;
35     for (int i=1;i<=m;i++){
36         double tmp=point_line_dis(q[i],lp[1]);
37         if (tmp<dist)
38             dist=tmp,pos=i;
39     }
40     ans=min(ans,dist);
41     for (int i=2;i<=n;i++){
42         while (point_line_dis(q[pos],lp[i])>point_line_dis(q[pos+1],lp[i])) pos==m?pos=1:pos++;
43         while (point_line_dis(q[pos],lp[i])>point_line_dis(q[pos-1],lp[i])) pos==1?pos=m:pos--;
44         ans=min(ans,point_line_dis(q[pos],lp[i]));
45     }
46 }
47
48 void solveq(){
49     double dist=inf;int pos;
50     for (int i=1;i<=n;i++){
51         double tmp=point_line_dis(p[i],lq[1]);
52         if (tmp<dist)
53             dist=tmp,pos=i;
54     }
55     ans=min(ans,dist);
56     for (int i=2;i<=m;i++){
57         while (point_line_dis(p[pos],lq[i])>point_line_dis(p[pos+1],lq[i])) pos==n?pos=1:pos++;
58         while (point_line_dis(p[pos],lq[i])>point_line_dis(p[pos-1],lq[i])) pos==1?pos=n:pos--;
59         ans=min(ans,point_line_dis(p[pos],lq[i]));
60     }
61 }
62
63 int main(){
64     while (scanf("%d%d",&n,&m)!=EOF){
65         ans=inf;
66         if (n==0 && m==0) break;
67         for (int i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
68         for (int i=1;i<=m;i++) scanf("%lf%lf",&q[i].x,&q[i].y);
69         p[n+1]=p[1],q[m+1]=q[1];
70         for (int i=1;i<=n;i++) lp[i].from=p[i],lp[i].to=p[i+1];
71         for (int i=1;i<=m;i++) lq[i].from=q[i],lq[i].to=q[i+1];
72         solvep();
73         solveq();
74         printf("%.6f\n",ans);
75     }
76     return 0;
77 }

时间: 2024-10-05 08:44:30

2016.08.07计算几何总结测试day2的相关文章

2016.08.06计算几何总结测试day1

T1 bzoj1132[POI2008]TRO 还是太弱了....测试时看到这题直接懵逼,极角排序什么的根本想不起来,只会n^3暴力怎么破......不过竟然有84.....QAQ 正解是n^2logn的,首先为了避免算重,以点的x坐标为第一关键字和y坐标为第二关键字排好序,然后O(n)枚举当前点计算以当前点为三角形的一个顶点的三角形面积之和. 显然不能n^2枚举,于是想到nlogn极角排序,以当前点为原点建一个平面直角坐标系,加一个前缀和将计算优化到O(n),于是就是n^2logn的了 至于怎

分布式技术一周技术动态 2016.08.07

searcher 分布式纵向方向主要涵盖的范围包括分布式系统理论和设计实践, 资源管理和虚拟化技术, 大规模服务稳定性技术, DevOps和自动运维技术等方面, “分布式方向一周技术动态"是我每周总结和整理的关于分布式方向的精选技术文章, 希望以此让大家能够跟踪业界相关的技术动态, 培养大家对分布式系统的兴趣, 学习分布式系统理论和设计思路, 辅助大家的日常工作. 每周的技术动态会在hi群和邮件组里同步发布, 欢迎大家阅读. 对于后续 分布式技术动态 有任何意见或者建议, 大家可以随时联系我.

大集合Cadence Encounter Test 15.12+SystemVue 2016.08+SewerCAD StormCAD CONNECT Edition 10.00.00.4

Cadence Encounter Test 15.12.000全球电子设计创新领先者 Cadence Design Systems公司,全球电子设计创新的领先者,已经发布了Cadence Encounter Test15.12.000版,是Cadence Encounter的一个关键技术的数字IC设计平台. Cadence Encounter Test3D-IC 设计测试和自动化测试样式生成为提供了一个全面的技术方法,其中包 括从芯片 I/Os 中控制和观察的一个单个芯片,不同的测试模式来控制

AryaLinux 2016.08 发布,Linux 内核更新至 4.7

AryaLinux 2016.08 发布了. 在 AryaLinux 2016.04 的基础上做出一系列改进. 主要更新内容: 1. AryaLinux 2016.08 新发布功能 MATE1.15 . 2. 构建 AryaLinux 的方法更标准化,并提供额外的 -KDE 和 LXQt 桌面环境支持. 3. Qt4 更新为 Qt5 . 4. Linux 内核更新至 4.7 版.这个内核版本支持很多新的硬件. 4. GCC 已被更新到版本 GCC 6. 5. VLC 媒体播放器升级到 3.x .

2016年07月MVP开始申请了~[截止时间:4月12日]

51CTO与微软中国合作长期为用户提供申请"微软最有价值专家"的平台希望有兴趣.资历的朋友以及正在朝这个方向努力的朋友能够积极参与只要您想参与我们将为您向微软推荐 微软最有价值专家MVP一年评选4次分别为每年的1月.4月.7月.10月.2016年7月的MVP申请截止时间是2016年4月12日. 申请MVP的午饭请下载2016年4月MVP申请表填好后发送到[email protected].我们会在每次MVP申请开始时把用户提交的申请表格推荐到微软中国相关部门 [注意事项]1.51CTO

Bootstrap 3.2.0 源码试读 2014/08/07

第一部分 normalize.css 70至72行 small {   font-size: 80%; } 设置small标签的字体大小为父容器字体的80%. 73至79行 sub, sup {   position: relative;   font-size: 75%;   line-height: 0;   vertical-align: baseline; } sup {   top: -.5em; } sub {   bottom: -.25em; } 先设置上标sup及下标sub,位

Python array,list,dataframe索引切片操作 2016年07月19日——智浪文档

array,list,dataframe索引切片操作 2016年07月19日——智浪文档 list,一维,二维array,datafrme,loc.iloc.ix的简单探讨 Numpy数组的索引和切片介绍: 从最基础的list索引开始讲起,我们先上一段代码和结果: a = [0,1,2,3,4,5,6,7,8,9] a[:5:-1] #step < 0,所以start = 9 a[0:5:-1] #指定了start = 0 a[1::-1] #step < 0,所以stop = 0 输出: [

2019.08.07学习整理

2019.08.07学习整理 字符编码 1.什么是字符编码 字符编码是将人类的字符编码成计算机能识别的数字,这种转换必须遵循一套固定的标准,该标准无非是人类字符与数字的对应关系,称之为字符编码表. 2.字符编码发展史与分类 计算机由美国人发明,最早的字符编码为ASCII,只规定了英文字母数字和一些特殊字符与数字的对应关系.最多只能用 8 位来表示(一个字节),即:2**8 = 256,所以,ASCII码最多只能表示 256 个符号. 当然我们编程语言都用英文没问题,ASCII够用,但是在处理数据

国双前端笔试题2016年07月08日

 简直就是虐人呢! 1.  输出什么 for (i = 0, j = 0; i < 10, j < 6; i++, j++) { value = i + j; } alert(value) 2. 输出什么 var handle = function (a) { var b = 3; var tmp = function (a) { b = a + b; return tmp; } tmp.toString= function () { return b; } return tmp; } ale