題目描述輸入整數L,在平面直角座標系中找出一個多邊形,滿足:頂點均在整點上周長恰爲L(1≤L≤5000)邊數儘量少在滿足以上條件的前提下,最長邊與最短邊長度之差儘量小輸出其最長邊與最短邊長度之差。無解輸出-1.000000。
輸入格式第1行:1個整數
輸出格式第1行:1個浮點數,表示答案。精確到小數點後6位。
輸入樣例12
輸出樣例2.000000
樣例說明存在邊長是3,4,5
題解首先明確幾點條件:①每條邊都是整數。因爲多邊形的頂點均在整點上,每條邊的長度都是√x。L=√x1+√x2+√x3+...+√xn,若√xi爲無理數,則L也不可能爲無理數。
②L<3時無解。
③若L≥4且L爲奇數,一定存在奇數條邊的長度爲奇數。對於一條邊,設它的兩個端點分別爲(x0, y0), (x1, y1)。根據勾股定理,邊長c滿足c^2 =(x1 − x0)^2 + (y1 − y0)^2。若c爲奇數,則|x1 − x0|與|y1 − y0|中恰有一個爲奇數。即從點(x0, y0)走到點(x1, y1),所在點的縱橫座標之和x+y的奇偶性發生變化;若c爲偶數,則|x1 − x0|, |y1 − y0|的奇偶性相同,因此走一條長度爲偶數的邊,所在點的縱橫座標之和x+y的奇偶性不發生變化;從多邊形的一個頂點出發,沿着所有邊走一遍走回這個頂點。若經過了奇數條長度爲奇數的邊,x+y的奇偶性應當發生變化。但是實際上,由於回到了同一個點,x+y的奇偶性不變。於是,L爲奇數時不存在滿足條件的多邊形。
④若L≥4且L爲偶數時,一定可以找到滿足條件的矩形,最後只需判斷L是否能圍成正方形,可以輸出0,不能輸出1。即所求多邊形的邊數要麼爲3要麼爲4。
無論三角形的形狀如何,都可以通過平移令它的一個頂點與原點重合,剩下兩個頂點位於第一象限內(或x軸正半軸上或y軸正半軸上)。然後枚舉剩下兩個頂點的位置。
#include<cstdio> #include<cmath> #include <algorithm> using namespace std; const int INF=0x3f3f3f3f; const int N=10000; int L, l, maxl, minl, ans, pcnt, w, t; struct node{ int x, y, l; }p[N<<1]; bool Can( int i, int j ) { if( t*t==w && t<=l && p[i].l+p[j].l+t==L ) if( p[i].x*p[j].y-p[i].y*p[j].x ) return 1; return 0; } int Dis( node a, node b ) { w=(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y); return sqrt(w); } void Pre() { ans=INF; l=L>>1; for( int i=1; i<=L; i++ ) for( int j=0; i*i+j*j<=l*l; j++ ) { t=sqrt( i*i+j*j ); if( t*t==i*i+j*j ) { p[++pcnt].l=t; p[pcnt].x=i; p[pcnt].y=j; } } } int main() { scanf( "%d", &L ); if( L&1 || L<4 ){ printf( "-1.000000\n" ); return 0; } Pre(); for( int i=1; i<=pcnt; i++ ) for( int j=i+1; j<=pcnt && p[i].l+p[j].l < L; j++ ) { t=Dis( p[i], p[j] ); if( Can( i, j ) ) { maxl=max( t, max( p[i].l, p[j].l ) ); minl=min( t, min( p[i].l, p[j].l ) ); ans=min( ans, maxl-minl ); } } if( ans>=INF ) { if( L%4 ) ans=1; else ans=0; } printf( "%.6lf\n", (double)ans ); return 0; }
[NOIP模擬賽]多邊形
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.