Apple
Time Limit : 10000/5000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Problem Description
小H是一个程序员,但他的生活不局限在写程序。
有一天,他走到公园散步。他见到公园的一棵苹果树上结满了苹果。他于是拿起石头,想砸几个苹果下来当第二天的早餐。突然他思考到了一个问题:怎样才能一次砸到最多苹果?
我们考虑该局面是这样一个模型:所有东西位于二维笛卡尔坐标系,其中小H位于原点,苹果们分别在坐标系的整点上。石头飞出的轨迹是一条经过原点的抛物线,确切的说,经过的是 y=ax^2+bx 的抛物线(a<0)。石头砸到一个苹果后,该苹果会落下,且石头不会改变运动轨迹。
现在小H希望求扔一个石头最多砸到的苹果数。
Input
第一行为一个整数T(1 <= T<= 10),表示有T组测试数据;
每组数据第一行一个正整数N(1<=N<=2000),表示苹果数。下面N行每行两个整数给出每个苹果的坐标xi, yi(1<=xi<=1000, 1<=yi<=1000000)。
Output
对于每组数据,输出最多可能砸到的苹果数。
解法:
根据题目的描述,题目的意思即是给定一个坐标点集合S,我们需要求出一条形式为y = aX2+ bX的抛物线,使得集合S中的点能够尽可能多的落在这条抛物线上。那么换一个角度思考,对于集合S中的每一个点p = (x, y),我们根据(x, y)求出一个关于a和b的等式,表示为 a = kb + c。这其实可以看作一条以a,b为坐标系的直线。所有以这条直线上的a和b的值作为参数的抛物线都经过点p。假设集合S中总共有n个点,则我们便可以得到n条关于a和b的直线。这样一来,问题便转换为:我们拥有n条直线,要求一个点,使得n条直线中经过这个点的直线条数最多,那么由这个点(a,b)作为系数的抛物线经过集合S的点数最多,具体点数即为通过这个点(a, b)的直线条数。
分析至此,则写出相应的代码便不是难事。下面给出我的参考代码(仅供参考,望多多指教):
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
#define EPS 0.001
struct Line
{
double k;
double c;
};
struct Point
{
double x;
double y;
bool operator==(const Point& rhs)
{
if(x - rhs.x < EPS && y - rhs.y < EPS) return true;
return false;
}
};
struct node
{
Point p;
int count;
};
int main()
{
int t;
int n;
cin >> t;
while(t--)
{
vector<node> inter;
vector<Line> lines;
cin >> n;
bool flag = true;
for(int i = 0; i < n; i++)
{
int x, y;
cin >> x >> y;
Line l;
l.k = -x;
l.c = y/x;
Point p;
for(vector<Line>::iterator iter = lines.begin(); iter != lines.end(); iter++)
{
if(l.k != iter->k || l.c != iter->c)
flag = false;
p.x = (l.c - iter->c) / (iter->k - l.k);
p.y = (iter->k * l.c - l.k * iter->c) / (iter->k - l.k);
vector<node>::iterator i;
for(i = inter.begin(); i != inter.end(); i++)
{
if(i->p == p)
{
i->count++;
break;
}
}
if(i == inter.end())
{
node newN;
newN.p = p;
newN.count = 1;
inter.push_back(newN);
}
}
lines.push_back(l);
}
int max = 0;
if(!flag)
{
for(vector<node>::iterator iter = inter.begin(); iter != inter.end(); iter++)
{
if(iter->count > max ) max = iter->count;
}
}
else
max = n;
cout << max << endl;
}
}