一、算法分析
本题上来先想到的就是爆搜一下,结果tle两个点。后仔细看题,原来只要求出所有斜率的可能,每种斜率各一条直线,就可以得到答案。注意对斜率的计算一定要对分母为0的情况进行特判。
二、暴搜代码(tle两个点)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#define ll long long
using namespace std;
const int maxn=1005;
int n;
struct point{
int x;
int y;
point(int u,int v):x(u),y(v){}
};
vector<point> a;
map<double,bool> mp; //判断斜率是否重复(即判断新连接的线与已有直线是否平行)
ll ans=0;
void dfs(int cur){
if(cur==n) return;
for(int i=0;i<n;i++){ //尝试连接其它点
if(cur==i) continue;
double k;
if(a[cur].x!=a[i].x) //注意要特判一下直线与x轴垂直的情况
k=(double)(a[cur].y-a[i].y)/(double)(a[cur].x-a[i].x);
else k=1000000000;
if(!mp[k]){
mp[k]=true;
ans++;
dfs(cur+1);
}
}
}
int main(){
int xx,yy;
cin>>n;
for(int i=0;i<n;i++){
cin>>xx>>yy;
a.push_back(point(xx,yy));
}
dfs(0);
cout<<ans;
return 0;
}
三、AC代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<set>
#include<cmath>
#define ll long long
using namespace std;
const int maxn=1005;
int n;
struct point{
int x;
int y;
point(int u,int v):x(u),y(v){}
};
vector<point> a;
double xielv(point p1,point p2){
double k;
if(p1.x!=p2.x) //注意要特判一下直线与x轴垂直的情况
k=(double)(p1.y-p2.y)/(double)(p1.x-p2.x);
else k=1000000000;
return k;
}
int ans=0;
set<double> setti;
int main(){
int xx,yy;
cin>>n;
for(int i=0;i<n;i++){
cin>>xx>>yy;
a.push_back(point(xx,yy));
}
for(int i=0;i<n-1;i++)
for(int j=i+1;j<n;j++){
setti.insert(xielv(a[i],a[j]));
}
ans=setti.size();
cout<<ans;
return 0;
}