题目描述:
1118:飞行员一次性沿直线想飞跃尽可能多的点,输入n为位置个数(最大700),n为0时退出,后面两个一组为坐标
2606:猎人一次击杀尽可能多的兔子,首次输入个数(最大200),随后两个一组为位置坐标
(两题一样,只是1118要求多次输入n,2606没有)
算法分析:
暴力搜索,确立一条直线,其余点代入实验。确立方法是三点式 (yi-yk)*(xj-xk)=(yj-yk)*(xi-xk)(i、j、k共线)
程序代码:
#include <stdio.h>
#define MAX 700
int main(int argc, char *argv[])
{
int n, i, j, k, count = 0, temp = 0;
int x[MAX], y[MAX];
while (1)
{
scanf("%d", &n);
if (n == 0)
break;
for ( i = 0; i < n; i++)
scanf("%d%d", &x[i], &y[i]);
count = 0;
for ( i = 0; i < n; i++)
for ( j = i+1; j < n; j++)
{
temp = 2;
for ( k = j+1; k < n; k++)
if ((y[i]-y[k])*(x[j]-x[k]) == (y[j]-y[k])*(x[i]-x[k]))
temp++;
if (temp > count)
count = temp;
}
printf("%d\n", count);
}
return 0;
}
(这个是1118,2606去掉while循环,并将MAX值改为200,去掉if(n == 0)即可)
错误版本及分析:
这两道是水题,但开始竟然WA了好几次,后来反思,原因如下:
开始直接反应用斜截式y = kx + b,如果斜率不存在用x = ky + b;
但是首先k可能是分数,用int存,不精确,必然错,若用double存,在比较点是否满足条件时又会都变成double,浮点数原则上不能比较精确大小,比较也是确定1e-10之类的范围内比,所以此法否了,换思路,用三点式可以完全避免这些问题.
错误代码如下:
#include <stdio.h>
#define MAX 700
int main(int argc, char *argv[])
{
int n, i, j, k, b, l, count = 0, temp = 0;
int x[MAX], y[MAX];
while (1)
{
scanf("%d", &n);
if (n == 0)
break;
for ( i = 0; i < n; i++)
scanf("%d%d", &x[i], &y[i]);
count = 0;
for ( i = 0; i < n; i++)
for ( j = i+1; j < n-i; j++)
{
temp = 0;
if (x[i]-x[j] != 0)
{
k = (y[i] - y[j]) / (x[i] - x[j]);
b = k*y[i] - x[i];
for ( l = 0; l < n; l++)
{
if (x[l] == y[l]*k + b)
temp++;
}
}
else if (y[i]-y[j] != 0)
{
k = (x[i] - x[j]) / (y[i] - y[j]);
b = k*x[i] -y[i];
for ( l = 0; l < n; l++)
{
if (y[l] == x[l]*k + b)
temp++;
}
}
else
break;
if (temp > count)
count = temp;
}
printf("%d\n", count);
}
return 0;
}