链接 : http://codeforces.com/contest/849/problem/B
题意 : 给出 n 个在直角坐标系上的点,每个点的横坐标的值对应给出的顺序序数,比如 1 2 4 3 则相当于给出了(1,1)、(2,2)、(3,4)、(4,3)这四个点,现在问你能不能找出两条不重叠的平行直线将所有点都覆盖掉
分析 : 假设存在满足题目条件的两条平行直线,那么肯定有一条是落在了1-2(第一和第二个点间连线)或1-3或者2-3上,我们分别考虑这三条直线以及其他点就能够知道是否满足题意了,比如现在考虑1-2这条直线,将不在这条直线上的所有点都暂存起来,最后判断暂存起来的点是否能够连成一条直线,并且斜率与1-2这条直线一样。用同样的方法考虑1-3以及2-3即可。
#include<bits/stdc++.h> using namespace std; const int maxn = 1e3 + 10; int n; struct point { int x, y; }; point arr[maxn], tmp[maxn]; double Slope(point fir, point sec) { ///计算两点间连线斜率 return (double)((double)sec.y-(double)fir.y) / (double)((double)sec.x-(double)fir.x); } bool Case1() { double k = Slope(arr[1], arr[2]);///1 - 2的情况 int cnt = 0;///不在 1 - 2这条直线上的点的个数 for(int i=3; i<=n; i++){ if(Slope(arr[1], arr[i]) != k){ ///挑出不在 1 - 2 这条直线上的点 tmp[cnt++] = arr[i]; } } if(!cnt) return false;///如果cnt==0那么也就是所有点都在1 - 2上,不满足题意 if(cnt == 1) return true;///如果挑出来是一个点的情况,那么1 - 2这条线以及这个点是满足题意的 double kk = Slope(tmp[0], tmp[1]);///计算斜率 if(kk != k) return false;///如果与 1 - 2的斜率不一致,不满足题意 for(int i=2; i<cnt; i++){///一个个点去试 if(Slope(tmp[0], tmp[i]) != kk) return false; } return true; } bool Case2() { double k = Slope(arr[1],arr[3]); int cnt = 0; for(int i=2; i<=n; i++){ if(i!=3){ if(Slope(arr[1], arr[i]) != k){ tmp[cnt++] = arr[i]; } } } if(!cnt) return false; if(cnt == 1) return true; double kk = Slope(tmp[0], tmp[1]); if(kk != k)return false; for(int i=2; i<cnt; i++){ if(Slope(tmp[0], tmp[i]) != kk) return false; } return true; } bool Case3() { double k = Slope(arr[2], arr[3]); int cnt = 0; for(int i=1; i<=n; i++){ if(i!=2 && i!=3){ if(Slope(arr[2], arr[i]) != k){ tmp[cnt++] = arr[i]; } } } if(!cnt) return false; if(cnt == 1) return true; double kk = Slope(tmp[0], tmp[1]); if(kk != k) return false; for(int i=2; i<cnt; i++){ if(Slope(tmp[0], tmp[i]) != kk) return false; } return true; } int main(void) { scanf("%d", &n); for(int i=1; i<=n; i++){ arr[i].x = i; scanf("%d", &arr[i].y); } if(Case1() || Case2() || Case3()) puts("Yes"); else puts("No"); return 0; }