Problem Description
给你n个点,分别给出它们的坐标。问你能否连接n条边,使的其成为连通图。最多四条河流在任何一个码头相遇,河流除了在码头外,不能相碰。输出n条你所建立的河流
例:
5
-1 0
2 3
3 2
5 4
6 1
输出:
3 2
3 4
5 3
1 5
2 4
思路:
就是一个思维题,看你如何建立河流,能满足要求。
其中一种方法就是,我AC的方法。把点按从小到大排序,从最左边的点,开始往右边的点连接,可以做到连接n-1条边,不会有交叉,这时候最后一条边是最左边的点到距离该点斜率最高或者最低的点。这样就连接出n条边了
只要是斜率问题,就得想到乘法,又白白wa了好几发。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e3+100;
const double inf = 1.0*0x3f3f3f3f;
struct node
{
ll x, y;
int id;
bool operator < (const node &b) const {//重载小于号,按x从小到大排序
if(x == b.x) return y < b.y;
else return x < b.x;
}
}a[N];
bool judge_k(ll *ky, ll *kx, int u, int v)//判断斜率是否相等
{
ll y = a[u].y - a[v].y;
ll x = a[u].x - a[v].x;
if(*ky == inf) {
*ky = y, *kx = x;
return 1;
}
if(y**kx == *ky*x) return 1;
else return 0;
}
double get_k(int u, int v)//获取斜率
{
double y = a[u].y - a[v].y;
double x = a[u].x - a[v].x;
if(a[u].x == a[v].x) return inf;
return 1.0*y/x;
}
int main()
{
int n, i;
scanf("%d", &n);
for(i = 1; i <= n; i++) {
cin >> a[i].x >> a[i].y;
a[i].id = i;//记录一下下标
}
sort(a+1, a+1+n);//按x从小到大排序
double Max = -inf, Min = inf;//记录最大斜率,最小斜率
ll Maxy, Maxx, Miny, Minx;//记录最大斜率点,最小斜率点(都是到最左边的点)
ll ky = inf, kx;
int flag = 0;
for(i = 2; i <= n; i++)
{
if(!judge_k(&ky, &kx, i, i-1)) {
flag = 1;
}
double t = get_k(1, i);//求最大,最小斜率的点。
if(Max < t)
Max = t, Maxy = a[i].y, Maxx = a[i].x;
if(Min > t)
Min = t, Miny = a[i].y, Minx = a[i].x;
}
if(!flag) printf("-1\n");//如果斜率全一样,那么就是一条线
else {
for(i = 2; i <= n; i++)//输出n-1条边
printf("%d %d\n", a[i].id, a[i-1].id);
for(i = 3; i <= n; i++)//输出最大斜率边,或者最小斜率边 i从3开始,因为2已经连接过了。
{
if((a[i].x == Maxx && a[i].y == Maxy) || (a[i].x == Minx && a[i].y == Miny))
{
printf("%d %d\n", a[1].id, a[i].id);
break;
}
}
}
return 0;
}