1. 程式人生 > >51nod 1100 斜率最大

51nod 1100 斜率最大

平面上有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 3
Output示例
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排序,所以只要和後一個比較

如果早知道這個規律根本不用那麼多行,還是太年輕