http://acm.hdu.edu.cn/showproblem.php?pid=4380
求三角形内的点的个数为奇数的三角形数 官方解题报告提供的是O(n2+m)的算法 先算两点与原地围成的三角形 最后总的有向三角形面积等于三者之和
实在不知道有向面积怎么转换成无向的 交了十几次依旧WA 在网上看到另一种做法 感觉很好
利用叉乘算出每个线段下面的点 三角形是由三条线段所围成 所以用一条减去两条(钝角)或者两条减一条(锐角)就能得到三角形区域 所以它包围的点数也就出来 了
View Code
1 #include <iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<string.h> 6 using namespace std; 7 #define N 1000000 8 struct node 9 { 10 double x,y; 11 }; 12 node q[101]; 13 node p[1011]; 14 int s[101][101]; 15 int ft(double x1,double y1,double x2,double y2, double x3,double y3) 16 { 17 if(x3<x1||x3>=x2)//在线段端点外的点不要 18 return 0; 19 if(((x1-x3)*(y2-y3)-(x2-x3)*(y1-y3))<0)//叉乘判断点在线段下方 20 return 1; 21 else 22 return 0; 23 } 24 bool cmp(node a,node b) 25 { 26 if(a.x==b.x)//按x排序 27 return a.y<b.y; 28 return a.x<b.x; 29 } 30 int main() 31 { 32 int i,j,k,n,m,num,g,mm = 0; 33 while(scanf("%d%d",&n,&m)!=EOF) 34 { 35 int tnum = 0; 36 mm++; 37 memset(s,0,sizeof(s)); 38 for(i = 1; i <= n ;i++) 39 scanf("%lf%lf",&q[i].x,&q[i].y); 40 for(j = 1; j <= m ; j++) 41 scanf("%lf%lf",&p[j].x,&p[j].y); 42 sort(q+1,q+n+1,cmp); 43 for(i = 1; i <= n-1 ; i++) 44 { 45 for(j = i+1 ; j <= n ; j++) 46 { 47 for(g = 1 ;g <= m ; g++) 48 { 49 if(ft(q[i].x,q[i].y,q[j].x,q[j].y,p[g].x,p[g].y)) 50 s[i][j]++,s[j][i]++; 51 } 52 } 53 } 54 for(i = 1; i <= n-2 ; i++)//线段包围的点 互相减掉 减成一个三角形区域包围的点 55 for(j = i+1; j <= n-1; j++) 56 for(k = j+1; k <= n ; k++) 57 if(abs(s[i][j]-s[j][k]-s[i][k])%2!=0)//锐角三角形 是两个减一个 钝角是一个减两个 直接用一个减会有负值 加上绝对值 58 tnum++; 59 printf("Case %d: ",mm); 60 printf("%d\n",tnum); 61 } 62 return 0; 63 }