[NOIP模拟赛]多边形

17 篇文章 0 订阅
9 篇文章 0 订阅
题目描述
输入整数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; 
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值