[NOIP模擬賽]多邊形

題目描述
輸入整數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; 
}

發佈了101 篇原創文章 · 獲贊 7 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章