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 }

 

posted @ 2012-08-24 08:53  _雨  阅读(191)  评论(0编辑  收藏  举报