【连线游戏】解题报告

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;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值