poj 2780 Linearity 最多共线点经典问题

题意:

给n个点,其中最多有多少点共线(n<1000)。

分析:

这是一个经典问题,朴素n^3解法:枚举n^2条直线,判断每条直线与多少点相交,复杂度n^3。明显会超时。这是n^2logn的解法:枚举每个点,对某个点与其他点连的n条直线按斜率排序,设这些直线中斜率相同的直线有k条,则k更新答案。这里想着重说一下斜率的问题,网上很多代码都是直接算斜率的,但计算几何的题目不推荐用斜率,最好用叉积代替有关斜率的一切计算,因为1)斜率的取值范围非常大,如果有中间计算有乘法很容易爆数据表示范围,对于要求精度的题会捉急。2)如果你定义INF=100000000代表无穷大的斜率,那么如果题目中有条直线的斜率为INF+1怎么办?3)计算斜率涉及除法,处处要特判分母,导致程序不简洁还容易出错4)叉积和点积是对点线关系比斜率深刻得多的描述,能表示点线之间的前后关系,顺逆关系等,有时候将点线平移还能在叉积点积运算上构成偏序集(这道题代码中对线段的逆向就是为了构成偏序集),而偏序集又可以多出很多手段来处理了。所以建议计算几何中少考虑斜率,多从点积叉积开始入手。

代码:

//poj 2780
//sep9
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxN=1024;
const int maxM=500024;
struct POINT
{
	int x,y;
}p[maxN];
struct LINE
{
	int x,y;
}l[maxM];

int cmp(LINE a,LINE b)
{
	 return a.x*b.y-a.y*b.x>=0;
}

int main()
{
	int n;
	while(scanf("%d",&n)==1){
		int num_line,ans=-1;
		for(int i=0;i<n;++i)
			scanf("%d%d",&p[i].x,&p[i].y);
		for(int i=0;i<n;++i){
			num_line=0;
			for(int j=i+1;j<n;++j){
				int dx=p[i].x-p[j].x,dy=p[i].y-p[j].y;
				if(dy<0) dy=-dy,dx=-dx;
				else if(dy==0&&dx<0)
					dx=-dx;
				l[num_line].x=dx,l[num_line].y=dy;
				++num_line;
			}
			sort(l,l+num_line,cmp);
			int cnt=0;
			for(int k=0;k<num_line;++k)
				if(k==0||l[k-1].x*l[k].y==l[k-1].y*l[k].x)
					++cnt;
				else{
					ans=max(ans,cnt);
					cnt=1;
				}
			ans=max(ans,cnt);
		}
		printf("%d\n",ans+1);
	}
	return 0;
} 

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-09 07:41:21

poj 2780 Linearity 最多共线点经典问题的相关文章

POJ 1118 最多共线点

Lining Up Time Limit: 2000MS   Memory Limit: 32768K Total Submissions: 22516   Accepted: 7091 Description "How am I ever going to solve this problem?" said the pilot. Indeed, the pilot was not facing an easy task. She had to drop packages at spe

HDU 1102 &amp;&amp; POJ 2421 Constructing Roads (经典MST~Prim)

链接:http://poj.org/problem?id=2421  或   http://acm.hdu.edu.cn/showproblem.php?pid=1102 Problem Description There are N villages, which are numbered from 1 to N, and you should build some roads such that every two villages can connect to each other. We

[ACM] poj 1700 Crossing River (经典过河问题)

Crossing River Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 10212   Accepted: 3855 Description A group of N people wishes to go across a river with only one boat, which can at most carry two persons. Therefore some sort of shuttle arr

POJ 1328 Radar Installation(经典贪婪)

Radar Installation Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 54143   Accepted: 12178 Description Assume the coasting is an infinite straight line. Land is in one side of coasting, sea in the other. Each small island is a point loca

POJ 1163 The Triangle(经典问题教你彻底理解动归思想)

The Triangle Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 38195   Accepted: 22946 Description 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 (Figure 1) Figure 1 shows a number triangle. Write a program that calculates the highest sum of numbers passed

POJ 1239 Increasing Sequences(经典的两次dp)

http://poj.org/problem?id=1239 题意:给出一串序列,现在要添加逗号作为分隔符,使得序列是递增序列,然后让最后一个数尽量小,第一个数尽量大. 思路:先从头到尾进行一次dp,d[i]表示分析到第i位时往前的最小长度,这样一来,d[n]就表示最后一位的最小长度. 在满足了最后一位尽量小的情况下,我们再从尾到头进行一次dp,此时d[i]表示分析到第i位时往后的最大长度.思路和第一次dp是差不多的. 1 #include<iostream> 2 #include<al

POJ 1328 Radar Installation(经典贪心)

Radar Installation Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 54143   Accepted: 12178 Description Assume the coasting is an infinite straight line. Land is in one side of coasting, sea in the other. Each small island is a point loca

POJ 1984 Navigation Nightmare 【经典带权并查集】

任意门:http://poj.org/problem?id=1984 Navigation Nightmare Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 7783   Accepted: 2801 Case Time Limit: 1000MS Description Farmer John's pastoral neighborhood has N farms (2 <= N <= 40,000), usuall

poj 1837 Balance 动态规划 (经典好题,很锻炼思维)

题目大意:给你一个天平,并给出m个刻度,n个砝码,刻度的绝对值代表距离平衡点的位置,并给出每个砝码的重量.达到平衡状态的方法有几种. 题目思路:首先我们先要明确dp数组的作用,dp[i][j]中,i为放置的砝码数量,j为平衡状态,0为平衡,j<0左倾,j>0右倾,由于j作为下标不能是负数,所以我们要找一个新的平衡点,因为15*20*20 = 7500,所以平衡点设置为7500, 然后我们可以得出动态方程 dp[i][j+w[i]*c[k])+=dp[i-1][j]; #include<c