5.4.3 果园里的树
果园里的树排列成矩阵。他们的x和y的坐标均是1~99的整数。输入若干个三角形,依次统计每个三角形内部和边界上共有多少棵树。
输入:
1.5 1.5 1.5 6.8 6.8 1.5
10.7 6.9 8.5 1.5 14.5 1.5
此题用三角形有向面积来解,求有向面积2倍的函数为:
double area(double x0,double y0,double x1,double y1,double x2,double,y2) { return x0*y1+x2*y0+x1*y2-x0*y2-x1*y0-x2*y1; }
若求其面积,即没有方向的:则为fabs(S)/2;
可以用行列式来记住这个式子:
|x0 y0 1|
2S=|x1 y1 1|=x0*y1+x2*y0+x1*y2-x2*y1-x0*y2-x1*y0;
|x2 y2 1|
若三角形三个点按逆时针排列,则有向面积为正,否则为负。
对一个三角形ABC和平面上任意一点O:都有 Sabc=Soab+Sobc+Soca;
判断点p是否在三角形内部或者是边界上的方法是:O点分出的三个三角形按oab,obc,oca的顺序得到的结果与原来的大三角形Sabc的同号或为0。
简单代码如下:
1 #include <stdio.h> 2 #include <math.h> 3 #include <string.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #include <iostream> 7 #include <algorithm> 8 using namespace std; 9 10 const double eps = 1e-9; 11 double area2(double x0, double y0, double x1, double y1, double x2, double y2){ 12 return fabs(x0 * y1 + x2 * y0 + x1 * y2 - x2* y1 - x0 * y2 - x1 * y0); 13 } 14 int main(){ 15 int i, j, t, n, m; 16 int ans; 17 double x0, x1, x2, y0, y1, y2; 18 while(EOF != scanf("%lf%lf%lf%lf%lf%lf",&x0, &y0, &x1, &y1, &x2, &y2)){ 19 ans = 0; 20 double area = area2(x0, y0, x1, y1, x2, y2); 21 for(i = 1; i < 100; ++i){ 22 for(j = 1; j < 100; ++j){ 23 double area0 = area2(i, j, x0, y0, x1, y1) + area2(i, j, x1, y1, x2, y2) + area2(i, j, x2, y2, x0, y0); 24 if(fabs(area0 - area) < eps) ++ans; 25 } 26 } 27 printf("%d\n",ans); 28 } 29 return 0; 30 }
注意,如果area2函数写成
double area2(double x0, double y0, double x1, double y1, double x2, double y2){ return x0 * y1 + x2 * y0 + x1 * y2 - x2* y1 - x0 * y2 - x1 * y0; }
则会WA。