hdu4380Farmer Greedy(多校九)

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 }

 

你可能感兴趣的:(HDU)