提供两种思路,这里只给思路不给代码,因为百度知道现在似乎贴代码格式会乱,而且自己写代码更容易进步。
第一种暴力的方法:遍历所有格点,用勾股定理算出三条边长度,用海伦公式算出面积。
勾股定理这个大家都会。海伦公式可以通过三边长度算出三角形面积。
海伦公式大致内容:令 p = ( a + b + c ) / 2 ,则 S = sqrt [ p ( p - a ) ( p -b ) ( p - c ) ] 。
(之前题目看错了。。重新写一遍这个方法
暴力的方法在 9×9 的范围内当然跑得快,但是如果题目加强,让你在 10^7×10^7 的方格内找好点,你怎么找?
第二种方法:根据面积相等和底边长度关系,可以求出高的比值,然后设出其中一条高的长度,就能得到另一条高的长度。然后写出两个直线方程并联立,可以得到一个新的方程。这个方程的图象上的整点就是好点。
听起来有点绕,拿这道题做例子就好理解了。
设 △PAB 的高为 a (为了方便记作条件①),则 △PAC 的高为 2a (条件②)。
以方格左下角为原点建系,可以写出满足条件①的直线解析式 y = x + √2 a 。
同理满足条件②的直线解析式为 y = 12 - x - 2√2 a 。(这里 a 的系数可正可负,篇幅原因只算一种,另一种后面代入一遍就好了)
联立可得 P 坐标为 ( 6 - 3√2/2 a, 6 - √2/2 a )。
根据坐标式子和题目性质可得 P 图象必定过 A( 6, 6 ),并且图象是一条直线。
设 P : y = k ( x - 6 ) + 6 ,代入坐标解得 k = 1/3 。
所以 P 在直线 y = 1/3 x + 4 上。
同理,P 也在直线 y = 3 x - 12 上。
然后把所有横坐标代入就好啦,复杂度直接少了一阶。(事实上还可以继续优化,不过这样已经很优了)
不知道对不对。。
#include
#include
int main(void) {
double XA = 6, YA = 6, XB = 2, YB = 2, XC = 8, YC = 4;
double Aab = YB - YA, Aac = YC - YA;
double Bab = XA - XB, Bac = XA - XC;
double Cab = XB * YA - XA * YB, Cac = XC * YA - XA * YC;
double AB = sqrt(pow(YB - YA, 2) + pow(XB - XA, 2));
double AC = sqrt(pow(YC - YA, 2) + pow(XC - XA, 2));
int C = 0;
for(int x = 1; x <= 9; x++)
for(int y = 1; y <= 9; y++) {
if(Aab * x + Bab * y + Cab == 0 || Aac * x + Bac * y + Cac == 0)
continue;
double Pab = fabs(Aab * x + Bab * y + Cab) / sqrt(Aab * Aab + Bab * Bab);
double Pac = fabs(Aac * x + Bac * y + Cac) / sqrt(Aac * Aac + Bac * Bac);
if(AB * Pab == AC * Pac)
C++;
}
printf("共有%d个好点\n", C);
return 0;
}