解题报告 轰炸德累斯顿
1. 题目
轰炸德累斯顿(Bomb.pas/c/cpp)
题目描述
1944年,随着诺曼底登陆的成功,同盟国的军队登上了欧洲西海岸,开辟了第二战场,胜利之日不远了。
为了彻底打击德国的军工制造,你与美国空军一起执行轰炸德国工业重镇——德累斯顿的计划。正当你驾驶“空中堡垒”轰炸机准备投弹时,德军防空火炮击中了你的飞机,现在飞机已经无法转向了,只能沿直线飞行。
地面上的德军目标处在同一平面内,用二维坐标描述。现在你想一次轰炸最多的目标,请完成任务。
输入数据
输入数据由n对整数组成(1<n<700),每对整数表示一个点的坐标。没有一个点会出现两次。
输出数据
一个整数,表示能轰炸到的最多的目标数。
样例输入
1 1
2 2
3 3
9 10
10 11
样例输出
3
2. 题目实质
找出一条直线,使其经过给定的点的数量最多。
3. 算法
简单枚举。
首先,储存坐标时开两个坐标系,一个存横坐标,一个存纵坐标,不要开二维数组。
然后枚举一个点(分别枚举),并且枚举他与其他的点所组成的直线的斜率,,跑一遍快排,然后找出斜率相同的最多的点,统计。最后找出枚举的最大值。
4. 注意事项
不要用二维数组存。
判断斜率时如果用除,要判断 0 ,如果用乘,要小心它会乘出来一个特别大的数。
理解题意时要理解对,这个飞机不是从原点出发,而是从给定的飞机中的任意一个出发。
5. 时空复杂度
(O(n*(n+n)*logn))
6. 程序代码
Leve (Pascal)
var
n,i,j,ans,now,k:longint;
x,y:array[1..700] of longint;
procedure qs(r,l:longint);
var
i,j,xx,yy,temp:longint;
begin
i:=r; j:=l;
xx:=x[(i+j)>>1];
yy:=y[(i+j)>>1];
repeat
while (x[i]<xx) or ((x[i]=xx) and (y[i]<yy)) do inc(i);
while (x[j]>xx) or ((x[j]=xx) and (y[j]>yy)) do dec(j);
if i<=j then
begin
temp:=x[i]; x[i]:=x[j]; x[j]:=temp;
temp:=y[i];y[i]:=y[j]; y[j]:=temp;
inc(i);
dec(j);
end;
until i>j;
if i<l then qs(i,l);
if j>r then qs(r,j);
end;
begin
assign(input,'bomb.in');
assign(output,'bomb.out');
reset(input);
rewrite(output);
n:=0;
while not eof do
begin
inc(n);
readln(x[n],y[n]);
end;
qs(1,n);
for i:=1 to n do
for j:=i+1 to n do
begin
now:=2;
for k:=j+1 to n do
if (y[j]-y[i])*(x[k]-x[i])=(x[j]-x[i])*(y[k]-y[i]) then
inc(now);
if now>ans then ans:=now;
end;
writeln(ans);
close(input);
close(output);
end.