p1959 遺址[NOI導刊2009普及(6)]
阿新 • • 發佈:2018-09-09
int amp 如何判斷 lin fine reg () getch lol
題目描述--> P1959 遺址_NOI導刊2009普及(6)
普通方法分析:
因為題目要求是找最大正方形(如果是長方形更麻煩.
講真,題目不難,耗時間!
根據題目要求,我們要找的是正方形.
我們可以根據已知兩點去判斷其他兩點是否存在
然後就到了畫圖課講解法的時候.
下面所有的dely代表縱坐標差值,delx代表橫坐標差值.
(記得在輸入的時候,標記圓柱坐標.
當我們枚舉的兩個點所在直線平行於x軸或y軸的時候↓.
直線兩側均可能有正方形
(即橫坐標差值為0或縱坐標差值為0的時候.)
縱坐標相同的話,加減橫坐標差值即可.
這時只需要判斷其他位置點是否存在即可.
我們的難點在於如何判斷兩個點是傾斜的情況.
容易發現一個將一個傾斜正方形圍起來之後,四個三角形是相等的. 像這樣↓
很明顯全等吧!證明過程略
然後我們需要考慮的是兩個點所在直線斜率是正還是負的問題
(親測只考慮一種情況,不能AC此題.)
求斜率的公式: k=Δy/Δx
分母不能為0!
然後我們又開始畫圖 emmm
斜率為負有兩種情況.我們可以畫圖如下↓
斜率為正.同樣有兩種情況如下↓
按照圖片去寫代碼即可.
--------------------代碼---------------------
#include<bits/stdc++.h> #define IL inline #define RI register int IL void in(int &x) { int f=1;x=0;char s=getchar(); while(s>‘9‘ or s<‘0‘){if(s==‘-‘)f=-1;s=getchar();} while(s<=‘9‘ and s>=‘0‘){x=x*10+s-‘0‘;s=getchar();} x*=f; } int n,x[30008],y[30008]; bool res[6008][6008]; int ans; IL int dis(int a,int b){return abs(a-b);} IL bool ok(int x,int y) { if(x<0 || y<0 || x>5000 || y>5000 || !res[x][y])return false; return true; } IL void search(int px,int py,int nx,int ny) { int delx=dis(px,nx),dely=dis(py,ny); if(delx==0) { if(ok(px+dely,py) && ok(nx+dely,ny)) ans=std::max(ans,dely*dely); else if(ok(px-dely,py) && ok(nx-dely,ny)) ans=std::max(ans,dely*dely); } else if(dely==0) { if(ok(px,py+delx) && ok(nx,ny+delx)) ans=std::max(ans,delx*delx); else if(ok(px,py-delx) && ok(nx,ny-delx)) ans=std::max(ans,delx*delx); } else if(((ny-py)/(nx-px))<0 && nx-px!=0) { if(ok(px+dely,py-delx) && ok(nx-dely,ny-delx)) ans=std::max(delx*delx+dely*dely,ans); else if(ok(px+dely,py+delx) && ok(nx+dely,ny+delx)) ans=std::max(delx*delx+dely*dely,ans); } else if(((ny-py)/(nx-px))>0 && nx-px!=0) { if(ok(px+dely,py-delx) && ok(nx+dely,ny-delx)) ans=std::max(delx*delx+dely*dely,ans); else if(ok(px-dely,py+delx) && ok(nx-dely,ny+delx)) ans=std::max(delx*delx+dely*dely,ans); } } int main(void) { in(n); for(RI i=1;i<=n;i++) in(x[i]),in(y[i]),res[x[i]][y[i]]=true; for(RI i=1;i<=n;i++) for(RI j=1;j<=n;j++) if(i!=j)search(x[i],y[i],x[j],y[j]); printf("%d",ans); }
如果RE的話記得判邊界,還要判斷是否有標記.
可能會有些麻煩,但個人感覺較好理解.
更簡單的方法
通過我們的畫圖.(如果你不知道請向上看圖 qwq
我們很容易發現
新點的橫坐標,只與dely有關.
新點的縱坐標,只與delx有關.
無論直線如何擺放都是如此.
且對應坐標為一個加一個減.
因此我們可以精簡代碼成下面這樣:
--------------------代碼--------------------
#include<bits/stdc++.h> #define IL inline #define RI register int IL void in(int &x) { int f=1;x=0;char s=getchar(); while(s>‘9‘ or s<‘0‘){if(s==‘-‘)f=-1;s=getchar();} while(s<=‘9‘ and s>=‘0‘){x=x*10+s-‘0‘;s=getchar();} x*=f; } int n,x[30008],y[30008]; bool res[6008][6008]; int ans; IL int dis(int a,int b){return abs(a-b);} IL bool ok(int x,int y) { if(x<0 || y<0 || x>5000 || y>5000 || !res[x][y])return false; return true; } IL void search(int px,int py,int nx,int ny) { int delx=dis(px,nx),dely=dis(py,ny); if(ok(px+dely,py-delx) &&ok(nx+dely,ny-delx)) ans=std::max(ans,delx*delx+dely*dely); else if(ok(px-dely,py+delx) && ok(nx-dely,ny+delx)) ans=std::max(ans,delx*delx+dely*dely); //感覺少考慮了斜率為負的那一種情況,但的確是可以AC的. /* 我們也可以加上判斷斜率為負的情況. else if(ok(px+dely,py+delx) && ok(nx+dely,ny+delx)) ans=std::max(ans,delx*delx+dely*dely); else if(ok(px-dely,py-delx) && ok(nx-dely,ny-delx)) ans=std::max(ans,delx*delx+dely*dely); 難道數據水? */ } int main(void) { in(n); for(RI i=1;i<=n;i++) in(x[i]),in(y[i]),res[x[i]][y[i]]=true; for(RI i=1;i<=n;i++) for(RI j=1;j<=n;j++) if(i!=j)search(x[i],y[i],x[j],y[j]); printf("%d",ans); }
裏面的delx*delx+dely*dely
是勾股定理的內容,就不用我多說了吧.
(逃
p1959 遺址[NOI導刊2009普及(6)]