ACM 计算几何模板 点在三角形内 加强版 HDU4380

来源:互联网 发布:bbc news软件下载 编辑:程序博客网 时间:2024/05/18 04:48

计算几何模板

统计有多少个点在三角形内(HDU4380)


先预处理,统计每条线段(直线)上方的点,然后利用类似容斥的方法

技巧是先对点按照横坐标排序大小,就避免了对三角形类型的讨论


注意1:直线ij,要统计[i,j)半开半闭区间的点个数,不能是闭区间,否则会重复计算(比如刚好横坐标相等的点)

注意2:在注意1的做法下,就会出现bug——不能有直角三角形,因为那个直角边在开区间那就没有统计在内了(本题HDU4380不能三点共线,就没有这个问题);补丁是另外保存横坐标刚好等于端点的点个数


如图:


判断某个点在三角形内的方法:

http://blog.csdn.net/nickwong_/article/details/47346695

提炼出模板

//预处理线段代码int st=1;//指针加速    for (int i=1; i<=n; i++)        for (int j=i+1; j<=n; j++)            for (int l=st; l<=m; l++)            {                if (b[l]<a[i]) st++; else //因为a数组递增,所以下一次直接跳过b[l]了                    if (b[l].x>=a[j].x) break; else //注意是大于等于,不能少了等于                        //统计的是半开半闭区间的数目,闭区间的话,会导致重复计算点                        if (check(i,j,l)) up[i][j]++;            }

//三角形内点的个数for (int i=1; i<=n; i++)        for (int j=i+1; j<=n; j++)            for (int k=j+1; k<=n; k++)            {                //if (cross(a[j]-a[i],a[k]-a[i])==0) continue; //题目说不会共线                int sum=abs(up[i][j]+up[j][k]-up[i][k]);                if (sum&1) ans++;            }


另外

完整代码:

/* * Author: NICK WONG * Created Time:  2015/8/7 13:09:53 * File Name:  */#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>#include<iomanip>using namespace std;#define out(x) cout<<#x<<": "<<x<<endlconst double eps(1e-8);const int maxn=1010;const long long maxint=-1u>>1;const long long maxlong=maxint*maxint;typedef long long lint;struct Point{    lint x,y;    Point(lint x=0, lint y=0):x(x),y(y){}    friend bool operator < (Point a, Point b)    {        //if (a.x==b.x) return a.y<b.y; else         return a.x<b.x;    }/*        friend bool operator == (Point a, Point b)        {        return a.x==b.x;        }*/};Point a[maxn],b[maxn];typedef Point Vector;inline Vector operator - (Point a, Point b) { return Vector(a.x-b.x,a.y-b.y); }int dcmp(double x){    if (fabs(x)<eps) return 0; else return x<0?-1:1;}inline lint cross(Vector a, Vector b) { return a.x*b.y-a.y*b.x; }int n,m,ans,cases;int c[maxn];int up[maxn][maxn];bool check(int i, int j, int k){    //if (b[k]<a[i] || b[k].x>=a[j].x) return false;    if (cross(a[j]-a[i],b[k]-a[i])>0) return true;    return false;}void init(){    for (int i=1; i<=n; i++)        cin>>a[i].x>>a[i].y;    for (int i=1; i<=m; i++)        cin>>b[i].x>>b[i].y;}void work(){    memset(up,0,sizeof(up));    ans=0;    sort(a+1,a+1+n);    sort(b+1,b+1+m);    //for (int i=1; i<=n; i++)    //cout<<a[i].x<<endl;    int st=1;//指针加速    for (int i=1; i<=n; i++)        for (int j=i+1; j<=n; j++)            for (int l=st; l<=m; l++)            {                if (b[l]<a[i]) st++; else //因为a数组递增,所以下一次直接跳过b[l]了                    if (b[l].x>=a[j].x) break; else //注意是大于等于,不能少了等于                        //统计的是半开半闭区间的数目,闭区间的话,会导致重复计算点                        if (check(i,j,l)) up[i][j]++;            }    for (int i=1; i<=n; i++)        for (int j=i+1; j<=n; j++)            for (int k=j+1; k<=n; k++)            {                //if (cross(a[j]-a[i],a[k]-a[i])==0) continue; //题目说不会共线                int sum=abs(up[i][j]+up[j][k]-up[i][k]);                if (sum&1) ans++;            }    printf("Case %d: %d\n",++cases,ans);}int main(){    while(cin>>n>>m)    {          init();        work();    }    return 0;}

F - Farmer Greedy
Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u
Submit Status Practice HDU 4380

Description

  Farmer Greedy is going to buy some houses for his farm. He has money only to buy three houses. The three houses can from a triangle area, which he can own as his farm. 
  There are many houses he can choose to buy, and there are many goldstones. They are points in a 2-dimentional plane. No three points are collinear. Farmer Greedy likes odd numbers. Now Farmer Greedy wonders how many farms he can choose to have odd goldstones in it.
 

Input

  There are multiple test cases. In each case, the first line gives two integers N, M. In the next N lines, each line gives two integers (X, Y) indicating the coordinates of one house. In the next M lines, each line gives two integers (X, Y) indicating the coordinates of one goldstone. 
Technical Specification 
  3 <= N <= 100 
  0 <= M <= 1000 
  |X|, |Y| <= 100000 
 

Output

  For each case, print in one line containing the case number (starting with 1) and the number of farms Farmer Greedy can choose to have odd goldstones in it.
 

Sample Input

4 4-10 010 00 100 -101 11 2-1 1-1 -1
 

Sample Output

Case 1: 2

0 0
原创粉丝点击