热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

HDU5784(计算几何)

ProblemHowManyTriangles(HDU5784)题目大意给定平面上的n个点(n《2000),询问可以组成多少个锐角三角形。解题分析直接统计锐角三角形较

Problem How Many Triangles (HDU 5784)

题目大意

  给定平面上的n个点(n《2000),询问可以组成多少个锐角三角形。

解题分析

  直接统计锐角三角形较困难,考虑问题的反面,统计直角三角形、钝角三角形、平角三角形(暂时这么叫吧QAQ)。

  首先枚举三角形的一个端点A,对其他点进行象限为第一关键字,极角为第二关键字排序。

  然后使用三个指针,进行O(n)的扫描。

  具体做法为用 i 指针指向三角形的第二个端点B。我们可以假想通过平移和旋转,把A点置于平面直角坐标系的原点,把B点置于x轴的正方向。那么可以与AB组成钝角或直角的点就在三四象限或者y轴。

  将 j 指针指向第一象限内可以组成锐角的最靠后的点,将k指针从j + 1 开始扫描至最后一个可以组成钝角的点,然后统计对答案的贡献。

  之后将 i 指针 +1,继续扫描。

  注意一些特殊的情况,可以写个暴力对拍,造点小数据debug。

参考程序

 1 #include 
 2 #include 
 3 #include 
 4 #include 
 5 using namespace std;
 6 #define eps 1e-8
 7 
 8 struct P{
 9     long long x,y;
10     int f;
11     friend P operator -(P a,P b){
12         return (P){a.x-b.x,a.y-b.y};
13     }
14 }a[20008],b[20008],S;
15 
16 int n,m;
17 
18 inline long long cross(P a,P b,P c){  //ab X ac
19     return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
20 }
21 
22 inline int calc(P a){
23     if (a.x>0 && a.y==0) return 1;
24     if (a.x>0 && a.y>0) return 1;
25     if (a.x==0 && a.y>0) return 2;
26     if (a.x<0 && a.y>0) return 2;
27     if (a.x<0 && a.y==0) return 3;
28     if (a.x<0 && a.y<0) return 3;
29     if (a.x==0 && a.y<0) return 4;
30     if (a.x>0 && a.y<0) return 4;
31 }
32 
33 inline bool cmp(const P a,const P b) {
34     if (a.freturn true;
35     if (a.f>b.f) return false;
36     long long tmp=cross(S,a,b);
37     if (tmp>0) return true;
38     return false; 
39 }
40 
41 inline bool ok(P a,P b,P c){
42     long long tmp=(b.x-a.x)*(c.x-a.x)+(b.y-a.y)*(c.y-a.y);
43     if (tmp>0) return true;
44     return false;
45 }
46 
47 int main(){
48     while (~scanf("%d",&n)){
49         for (int i=1;i<=n;i++) scanf("%I64d %I64d",&a[i].x,&a[i].y);
50         long long sum=0;
51         for (int ii=1;ii<=n;ii++){
52             S=a[ii]; m=0; 
53             for (int j=1;j<=n;j++)
54                 if (j!=ii) b[++m]=a[j];
55             for (int i=1;i<=m;i++) b[i].f=calc(b[i]-S);
56             sort(b+1,b+m+1,cmp);
57             int i=1,j=1,k=1;
58             while (ok(S,b[i],b[j]) && cross(S,b[i],b[j])>=0 && j<=m) j++;
59             if (j==m+1) continue;
60             j--; k=j+1;
61             while (i<=m)
62             {
63                 if (!ok(S,b[i],b[k])){        
64                     while (!ok(S,b[i],b[k+1]) && k;
65                     sum+=k-j;
66                 }
67                 i++;
68                 if (ji; 
69                 while (ok(S,b[i],b[j+1]) && cross(S,b[i],b[j+1])>0 && j;
70                 if (k<=j) k=j+1;
71                 if (k>m) break;
72             }        
73         }
74         long long p=1ll*n*(n-1)*(n-2)/6;
75         printf("%I64d\n",p-sum);
76     }
77 }
View Code

 


推荐阅读
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文讨论了一个数列求和问题,该数列按照一定规律生成。通过观察数列的规律,我们可以得出求解该问题的算法。具体算法为计算前n项i*f[i]的和,其中f[i]表示数列中有i个数字。根据参考的思路,我们可以将算法的时间复杂度控制在O(n),即计算到5e5即可满足1e9的要求。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • IhaveconfiguredanactionforaremotenotificationwhenitarrivestomyiOsapp.Iwanttwodiff ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 3.223.28周学习总结中的贪心作业收获及困惑
    本文是对3.223.28周学习总结中的贪心作业进行总结,作者在解题过程中参考了他人的代码,但前提是要先理解题目并有解题思路。作者分享了自己在贪心作业中的收获,同时提到了一道让他困惑的题目,即input details部分引发的疑惑。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • Go语言实现堆排序的详细教程
    本文主要介绍了Go语言实现堆排序的详细教程,包括大根堆的定义和完全二叉树的概念。通过图解和算法描述,详细介绍了堆排序的实现过程。堆排序是一种效率很高的排序算法,时间复杂度为O(nlgn)。阅读本文大约需要15分钟。 ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
author-avatar
毛云龙hei
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有