51nod 1100 斜率最大
阿新 • • 發佈:2019-01-26
平面上有N個點,任意2個點確定一條直線,求出所有這些直線中,斜率最大的那條直線所通過的兩個點。
(點的編號為1-N,如果有多條直線斜率相等,則輸出所有結果,按照點的X軸座標排序,正序輸出。資料中所有點的X軸座標均不相等,且點座標為隨機。)
Input
第1行,一個數N,N為點的數量。(2 <= N <= 10000) 第2 - N + 1行:具體N個點的座標,X Y均為整數(-10^9 <= X,Y <= 10^9)Output
每行2個數,中間用空格分隔。分別是起點編號和終點編號(起點的X軸座標 < 終點的X軸座標)Input示例
5 1 2 6 8 4 4 5 4 2 3Output示例
4 2
學校老司機建議寫下自己當時思路,有利於以後複習,一開始還沒怎麼在意,今天看兩週前的題目居然忘了怎麼做,嚇得我馬上開了個部落格,主要是學習過程,非大神,看官們輕噴
首先看了這道題第一感覺是暴力(菜雞隻能暴力), 最暴力的方法就是兩個for迴圈,比較斜率,估計會爆所以跳過
1 :將點首先按x座標排序,有利於儲存答案和優化
2 :計算過程儲存一個最高y點,在x增大的情況下y如果一樣大,肯定斜率更低。
3 :儲存的話用陣列儲存兩個點的x值,因為題目x都不相同,題目要求輸出原來的陣列的順序點,所以開個陣列儲存原順序,然後算出答案從中匹配
附上程式碼:
#include<iostream> #include <algorithm> #include <string.h> #include <string> #include <stack> #include<cstdio> using namespace std; long long int n,i,j,ansnum=0,ymax=0,temp,shunxu[10005],ax=0,ay=0; double xielv=0,txielv; struct dian { long long int x,y; }d[10005],ans[10005]; int cmp(dian a,dian b) { if(a.x<b.x) return 1; return 0; } int main() { scanf("%lld",&n); for(i=0;i<n;i++) { scanf("%lld%lld",&d[i].x,&d[i].y); shunxu[i]=d[i].x; } sort(d,d+n,cmp); temp=n-1; for(i=0;i<temp;i++) { ymax=d[i].y; for(j=i+1;j<=temp;j++) { if(d[j].y<=ymax) continue; if(d[j].y<=d[i].y) continue; txielv=(double(d[j].y-d[i].y))/(double(d[j].x-d[i].x)); if(txielv>xielv) { ymax=d[j].y; xielv=txielv; ans[0].x=d[i].x; ans[0].y=d[j].x; ansnum=1; } else if(txielv==xielv) { ans[ansnum].x=d[i].x; ans[ansnum].y=d[j].x; } } } for(i=0;i<ansnum;i++) { for(j=0;j<n;j++) { if(shunxu[j]==ans[i].x) ax=j+1; else if(shunxu[j]==ans[i].y) ay=j+1; } printf("%lld %lld\n",ax,ay); } return 0; }
然後發現別人的程式碼都是20ms以內
發現有個數學規律,排序後斜率最大的兩個點肯定是相鄰的,用反證法更容易驗證,那我寫那麼多幹嗎唉
附上程式碼:
#include<iostream> #include <algorithm> #include <string.h> #include <string> #include <stack> #include<cstdio> #include <set> #include<queue> using namespace std; long long int n,i,j,ansnum=0,ymax=0,temp,shunxu[10005],ax=0,ay=0; double xielv=0,txielv; struct dian { long long int x,y; }d[10005],ans[10005]; int cmp(dian a,dian b) { if(a.x<b.x) return 1; return 0; } int main() { scanf("%lld",&n); for(i=0;i<n;i++) { scanf("%lld%lld",&d[i].x,&d[i].y); shunxu[i]=d[i].x; } sort(d,d+n,cmp); temp=n-1; for(i=0;i<temp;i++) { j=i+1; if(d[j].y<=d[i].y) continue; txielv=(double(d[j].y-d[i].y))/(double(d[j].x-d[i].x)); if(txielv>xielv) { xielv=txielv; ans[0].x=d[i].x; ans[0].y=d[j].x; ansnum=1; } else if(txielv==xielv) { ans[ansnum].x=d[i].x; ans[ansnum].y=d[j].x; } } for(i=0;i<ansnum;i++) { for(j=0;j<n;j++) { if(shunxu[j]==ans[i].x) ax=j+1; else if(shunxu[j]==ans[i].y) ay=j+1; } printf("%lld %lld\n",ax,ay); } return 0; }
只是把一個迴圈改成了i+1;因為按x排序,所以只要和後一個比較
如果早知道這個規律根本不用那麼多行,還是太年輕