热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[CERC2016]凸轮廓线ConvexContour

洛谷题目链接学习OI以来做的第一道几何题,写篇文章纪念一下。题目描述一些几何图形整齐地在一个网格图上从左往右排成一列。它们占据了连续的一段横行,每个位置恰好一个几何图形。每个图形是

洛谷题目链接

学习OI以来做的第一道几何题,写篇文章纪念一下。



题目描述

一些几何图形整齐地在一个网格图上从左往右排成一列。它们占据了连续的一段横行,每个位置恰好一个几何图形。每个图形是以下的三种之一:

1.一个恰好充满单个格子的正方形。

2.一个内切于单个格子的圆。

3.一个底边与格子重合的等边三角形。

已知每个格子的边长都为1,请求出这些几何图形的凸包的周长。


输入输出格式

输入格式:

第一行包含一个正整数n(1<=n<=20),表示几何图形的个数。

第二行包含n个字符,从左往右依次表示每个图形,“S”表示正方形,“C”表示圆形,“T”表示等边三角形。

输出格式:

输出一行一个实数,即凸包的周长。与答案的绝对或相对误差不超过10^-6时被认为是正确的。


输入输出样例

输入样例#1: 

4 TSTC

输出样例#1: 

9.088434417



解决步骤:

     我将计算分为了三个部分:底边、侧边和顶边,分别对应下图中的红色、橙色和绿色部分。

    ①计算凸包底边长度

        我们定义凸包和网格底边的重合部分为凸包的底边,那么对于凸包的左右两端只有三种情况:圆在最左/右边,正方形在最左/右边和圆在最左/右边。



    根据凸包的定义,对于这3种情况,凸包的底边显然会是下图中的红色部分:


     如果这几种图形凸包的右端,那也是同样道理。观察发现,对于若干个题中所说的图形组合,底边长可以分成下图中的橙色、紫色两段。其中橙色部分的长度V_{i}

所以计算底边的代码:


//shape[i]为第i个位置上的图案,0=三角形,1=正方形,2=圆形
double btmspec[]={0.5,0.5,0};//对应三角形、正方形、圆形
double bottom=(n-1)+btmspec[shape[0]]+btmspec[shape[n-1]];

 

    ②计算侧边长

        如图,左右两端的图形的橙色部分长度加起来就是凸包的侧边长了。

        


//shape的意义同上
double lrspec[]={1,1.5,PI/2.0}
double side=lrspec[shape[0]]+lrspec[shape[n-1]];

    ③计算顶边

        这算是最难的一部分了。如果图形两端是正三角形,由于它的高度是\frac{\sqrt{3}}{2}

找最左边的不为三角形的图形位置:


int findLT(){
for(int i=0;i if(shape[i]!=TRIANGLE)
return i;
}

    找右端的同理。现在重点来了:假设最左端的不为三角形的位置为l

    对于绿色部分的长度,我们分两种情况讨论:

        1.如果是三角形和正方形组合,中间夹着若干三角形,那么我们直接可以根据勾股定理得到斜边长H_y=\sqrt{(\Delta x)^2+H^2}



        2.如果是三角形和圆组合,中间夹着若干三角形,那么总长就是下图中橙色的斜边+一小段红色圆弧的长度。



    对于这种情况,我们如下计算:



由切线、圆和直角三角形的几何性质可知:
\left\{\begin{matrix} r=0.5\\ h_y=\sqrt{(\Delta x)^2+(\frac{\sqrt{3}-1}{2})^2}\\ \theta =\arcsin{\frac{\Delta x}{h_y}}=\arccos{\frac{\sqrt{3}-1}{2*h_y}}\\ \alpha =\arccos{\frac{r}{h_y}}\\ \beta =\theta -\alpha \\ d=h_y \sin \alpha\\ a=r \beta \end{matrix}\right.

 

这就是计算凸包周长的步骤了,完整代码如下:


#include
using namespace std;
const int TRI=1,SQR=2,CIR=3;
int n,tcount=0,shape[21];//tcount为三角形数量,用于特判全是三角形的情况
double PI=3.14159265358979,SQ1_3=0.13397459621556,HS3_1=0.36602540378443;
double btmspec[]={0,0.5,0.5,0},lrspec[]={0,1,1.5,PI/2.0};
//SQ1_3=1-√3/2 HS3_1=(√3-1)/2
int findLT(){for(int i=0;iint findRT(){for(int i=n-1;i>=0;i--)if(shape[i]!=TRI)return i;}
double procHy(int slot1,int slot2){//处理顶边的长度
if(slot1==slot2)return 0;//最左/最右并没有三角形,直接跳过
int sh2=shape[slot2];//由之前讲的可以知道,这时shape[slot1]只能是三角形
double deltaX=abs(slot1-slot2);
if(sh2==SQR){//正方形和三角形组合
deltaX-=0.5;
return sqrt(SQ1_3*SQ1_3+deltaX*deltaX)+0.5;
}else{//sh2一定为CIRCLE
double hyd=sqrt(deltaX*deltaX+HS3_1*HS3_1);
double alpha=acos(0.5/hyd),theta=acos(HS3_1/hyd);
return hyd*sin(alpha)+(theta-alpha)*0.5;
}
}
int main(){
cin>>n;
for(int i=0,x=0;i do{x=getchar();}while(x<'A'||x>'Z');
if(x=='C')shape[i]=CIR;
if(x=='S')shape[i]=SQR;
if(x=='T')shape[i]=TRI,tcount++;
}
double ans=0;
ans+=(n-1)+btmspec[shape[0]]+btmspec[shape[n-1]];//bottom
ans+=lrspec[shape[0]]+lrspec[shape[n-1]];//left&right
//top
if(tcount==n)ans+=n-1;//特判全是三角形的情况
else{
int lt=findLT(),rt=findRT();//找最左和最右不是三角形的位置
ans+=(rt-lt)+procHy(0,lt)+procHy(n-1,rt);
}
printf("%.8lf",ans);
return 0;
}

 



推荐阅读
  • LeetCode 540:有序数组中的唯一元素
    来源:力扣(LeetCode),链接:https://leetcode-cn.com/problems/single-element-in-a-sorted-array。题目要求在仅包含整数的有序数组中,找到唯一出现一次的元素,并确保算法的时间复杂度为 O(log n) 和空间复杂度为 O(1)。 ... [详细]
  • 如何在Faceu激萌中设置和使用妆容切换特效?
    本文将详细介绍如何在Faceu激萌应用中设置和使用妆容切换特效,帮助用户轻松实现创意拍摄。无论是新手还是有经验的用户,都能从中受益。 ... [详细]
  • 本文介绍如何解决在 IIS 环境下 PHP 页面无法找到的问题。主要步骤包括配置 Internet 信息服务管理器中的 ISAPI 扩展和 Active Server Pages 设置,确保 PHP 脚本能够正常运行。 ... [详细]
  • Python 异步编程:深入理解 asyncio 库(上)
    本文介绍了 Python 3.4 版本引入的标准库 asyncio,该库为异步 IO 提供了强大的支持。我们将探讨为什么需要 asyncio,以及它如何简化并发编程的复杂性,并详细介绍其核心概念和使用方法。 ... [详细]
  • 探讨一个老旧 PHP MySQL 系统中,时间戳字段不定期出现异常值的问题及其可能原因。 ... [详细]
  • 国内BI工具迎战国际巨头Tableau,稳步崛起
    尽管商业智能(BI)工具在中国的普及程度尚不及国际市场,但近年来,随着本土企业的持续创新和市场推广,国内主流BI工具正逐渐崭露头角。面对国际品牌如Tableau的强大竞争,国内BI工具通过不断优化产品和技术,赢得了越来越多用户的认可。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 郑州大学在211高校中的地位与排名解析
    本文将详细解读郑州大学作为一所位于河南省的211和双一流B类高校,在全国211高校中的地位与排名,帮助高三学生更好地了解这所知名学府的实力与发展前景。 ... [详细]
  • 深入理解 Oracle 存储函数:计算员工年收入
    本文介绍如何使用 Oracle 存储函数查询特定员工的年收入。我们将详细解释存储函数的创建过程,并提供完整的代码示例。 ... [详细]
  • 优化ASM字节码操作:简化类转换与移除冗余指令
    本文探讨如何利用ASM框架进行字节码操作,以优化现有类的转换过程,简化复杂的转换逻辑,并移除不必要的加0操作。通过这些技术手段,可以显著提升代码性能和可维护性。 ... [详细]
  • 本文总结了2018年的关键成就,包括职业变动、购车、考取驾照等重要事件,并分享了读书、工作、家庭和朋友方面的感悟。同时,展望2019年,制定了健康、软实力提升和技术学习的具体目标。 ... [详细]
  • 电子元件封装库:三极管、MOS管及部分LDO(含3D模型)
    本资源汇集了常用的插件和贴片三极管、MOS管以及部分LDO的封装,涵盖TO和SOT系列。所有封装均配有高质量的3D模型,共计96种,满足日常设计需求。 ... [详细]
  • 在计算机技术的学习道路上,51CTO学院以其专业性和专注度给我留下了深刻印象。从2012年接触计算机到2014年开始系统学习网络技术和安全领域,51CTO学院始终是我信赖的学习平台。 ... [详细]
  • CSS 布局:液态三栏混合宽度布局
    本文介绍了如何使用 CSS 实现液态的三栏布局,其中各栏具有不同的宽度设置。通过调整容器和内容区域的属性,可以实现灵活且响应式的网页设计。 ... [详细]
  • 本文详细介绍了如何使用PHP检测AJAX请求,通过分析预定义服务器变量来判断请求是否来自XMLHttpRequest。此方法简单实用,适用于各种Web开发场景。 ... [详细]
author-avatar
fhuwiop
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有