1.连线游戏
【问题描述】
佳佳最近发明了一个游戏,来考验自命不凡的津津。游戏开始的时候,佳佳会给津津一块画着N (2 <= N <= 200)个不重合的点的木板,其中第i个点的横、纵坐标分别为Xi和Yi (-1,000 <= Xi <=1,000;-1,000 <= Yi <= 1,000)。
津津可以选两个点画一条过它们的直线,当且仅当平面上不存在与画出直线平行的直线。游戏结束时津津的得分,就是她画出直线的总条数。为了在游戏中胜出,津津找到了你,希望你帮她计算一下最大可能得分。
【文件输入】
文件输入的第一行为一个正整数N,表示木板上面点的个数,第二行到第n+1行每行两个整数Xi、Yi,表示每个点的坐标。
【文件输出】
文件输出只有一个整数,表示津津的最大得分,即她能画出互不平行直线的最多个数。
【样例输入】
4
-1 1
-2 0
0 0
1 1
【样例输出】
4
【输出说明】
津津能画出以下4种斜率的直线:-1,0,1/3以及1。
这是一道水题,可是因为我的数组开小了,所以悲剧WA40(交卷前我还专门检查了范围的),开大了后WA90,一组超时。
就是一个枚举,两两连线,最优方法是开hash表,但是我用的是一个线性表,每一次要从中查询有没有平行的线。
当时只是因为考虑到约分,平移懒得写所以这样办,结果事实证明用约分加平移写起来更方便。
这道题有一点需要注意。即约分要保证都为正,否则会导致(a/b)和(-a)/(-b)被判为不平行的情况!!
或者用-a+平移量这种方法也行。
//AC
//#include <iostream>
//using std::cout;
//using std::cin;
#include <cstdio>
#include <bitset>
const long oo = 0x7fff0000;
long n;
long x[202];
long y[202];
long h[4050][4050];
long gcd(long a,long b)
{
if (a<b){a^=b;b^=a;a^=b;}
while (b!=0)
{
long c = a%b;
if (a>=c){a=b;b=c;}
else{a=c;}
}
return a;
}
int main()
{
freopen("game.in","r",stdin);
freopen("game.out","w",stdout);
scanf("%ld",&n);
for (long i=1;i<n+1;i++)
{
scanf("%ld%ld",x+i,y+i);
}
long ans=0;
for (long i=1;i<n+1;i++)
{
for (long j=i+1;j<n+1;j++)
{
long yy = y[j]-y[i];
long xx = x[j]-x[i];
long g = gcd(yy,xx);
yy/=g;xx/=g;
if(!h[yy+2010][xx+2010]&&!h[2010-yy][2010-yy])
{
//printf("%ld %ld\n",i,j);
ans++;
h[yy+2010][xx+2010] = true;
}
}
}
printf("%ld",ans);
return 0;
}