以后,如果不是A+B问题,我尽量每题都写,聚沙成塔
1610: [Usaco2008 Feb]Line连线游戏
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 2080 Solved: 928
[ Submit][ Status][ Discuss]
Description
Farmer John最近发明了一个游戏,来考验自命不凡的贝茜。游戏开始的时 候,FJ会给贝茜一块画着N (2 <= N <= 200)个不重合的点的木板,其中第i个点 的横、纵坐标分别为X_i和Y_i (-1,000 <= X_i <=1,000; -1,000 <= Y_i <= 1,000)。 贝茜可以选两个点画一条过它们的直线,当且仅当平面上不存在与画出直线 平行的直线。游戏结束时贝茜的得分,就是她画出的直线的总条数。为了在游戏 中胜出,贝茜找到了你,希望你帮她计算一下最大可能得分。
Input
* 第1行: 输入1个正整数:N
* 第2..N+1行: 第i+1行用2个用空格隔开的整数X_i、Y_i,描述了点i的坐标
Output
第1行: 输出1个整数,表示贝茜的最大得分,即她能画出的互不平行的直线数
Sample Input
4
-1 1
-2 0
0 0
1 1
-1 1
-2 0
0 0
1 1
Sample Output
* 第1行: 输出1个整数,表示贝茜的最大得分,即她能画出的互不平行的直线数
HINT
4 输出说明: 贝茜能画出以下4种斜率的直线:-1,0,1/3以及1。
var
n,i,j,y,x,ans,tot:longint;
flag,bl:boolean;
k:array[-1..20001]of double;
a,b:array[-1..201]of longint;
procedure qsort(l,r:longint);
var i,j:longint; mid,x:double;
begin
i:=l;
j:=r;
mid:=k[(i+j)shr 1];
repeat
while k[i]<mid do inc(i);
while k[j]>mid do dec(j);
if i<=j then
begin
x:=k[i];
k[i]:=k[j];
k[j]:=x;
inc(i);
dec(j);
end;
until i>j;
if i<r then qsort(i,r);
if j>l then qsort(l,j);
end;
begin
readln(n);
for i:=1 to n do
begin
readln(a[i],b[i]);
end;
for i:=1 to n do
for j:=i+1 to n do
begin
if a[i]=a[j] then//横坐标相同,即x轴平行,这点要判断一下,否则除数将为0
begin
flag:=true;
end
else if b[i]=b[j] then//纵坐标相同,这个可要可不要
begin
bl:=true;
end
else
begin
inc(tot);
x:=a[i]-a[j];
y:=b[i]-b[j];
k[tot]:=y/x;
end;
end;
qsort(1,tot);//判断种类问题,一般用到快排
ans:=1;//因为n条斜率,最多有n条不同,最少有1条不同,又只能判断n-1次,因此将ans的初值定为1
for i:=2 to tot do
begin
if k[i]-k[i-1]<>0 then
begin
//writeln(k[i]:0:2);
inc(ans);
end;
end;
if flag then inc(ans);
if bl then inc(ans);
writeln(ans);
end.
总结:
1、斜率等坐标问题,必须考虑除数为0的情况。
2、判断是否重复(种类问题)可用类似桶排序的方法,但对于此题,会使桶排序的数组下标为实数,因此选用快排