news 2026/3/22 13:16:01

UVa 149 Forests

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
UVa 149 Forests

题目分析

这道题来源于一个常见的观察现象:在森林中,当你站在某个位置观察时,远处的树木可能会被近处的树木遮挡,导致你无法看清远处的树木。题目中给出了一个数学模型:树木被抽象为直径相同的圆柱体,它们的中心位于一个单位间距的无限矩形网格上。观察者站在某个坐标点( x , y ) (x, y)(x,y)上,用一只眼睛观察。只有当一棵树在观察者眼中所张的视角大于0.01 0.010.01度,并且它的树干没有被更近的树木遮挡时,这棵树才是可见的。

关键点:

  • 树木直径d dd满足0.1 ≤ d ≤ x , y ≤ 1 − d 0.1 \le d \le x, y \le 1-d0.1dx,y1d
  • 网格是无限的,但题目通过坐标缩放保证了输入坐标在[ 0 , 1 ] [0,1][0,1]之间。
  • 需要计算从给定观察点可以看到的树木数量。

解题思路

由于网格是无限的,直接枚举所有树木是不可能的。我们需要找到一种有效的方法来判断哪些树是可见的。

1. 几何模型

每棵树是一个直径为d dd的圆柱体。观察者位于O ( x , y ) O(x, y)O(x,y),树木中心位于网格点T ( i , j ) T(i, j)T(i,j)。要判断T TT是否可见,需要考虑:

  • 视角大小:树木在观察者眼中的张角必须大于0.01 0.010.01度。
  • 遮挡关系:如果存在另一棵树N NNT TT更接近观察者,并且从O OOT TT的视线被N NN的树干遮挡,那么T TT不可见。

2. 遮挡判定

对于两棵树N NN(近)和F FF(远),我们需要判断N NN是否遮挡了F FF。这可以通过计算角度来判断:
设:

  • a = ∣ O N ∣ 2 a = |ON|^2a=ON2
  • b = ∣ O F ∣ 2 b = |OF|^2b=OF2
  • c = ∣ N F ∣ 2 c = |NF|^2c=NF2
  • A = arcsin ⁡ ( d / ( 2 a ) ) A = \arcsin(d / (2\sqrt{a}))A=arcsin(d/(2a))N NN树干的半张角)
  • B = arcsin ⁡ ( d / ( 2 b ) ) B = \arcsin(d / (2\sqrt{b}))B=arcsin(d/(2b))F FF树干的半张角)
  • cos ⁡ C = ( a + b − c ) / ( 2 a b ) \cos C = (a + b - c) / (2\sqrt{a}\sqrt{b})cosC=(a+bc)/(2ab)C = arccos ⁡ ( cos ⁡ C ) C = \arccos(\cos C)C=arccos(cosC)O OO到两棵树中心的夹角)

如果C − A − B ≤ 0.01 C - A - B \le 0.01CAB0.01度(转换为弧度比较),则N NN遮挡了F FF

3. 枚举范围

由于网格无限,但树木大小固定,观察点位置有限,实际上只需要检查一定范围内的树木即可:

  • 将坐标乘以100 100100转换为整数网格,便于计算。
  • 将平面分为四个象限,每个象限内按“深度”(距离观察点的网格层数)逐步向外检查。
  • 对于每一层,检查该层的角点和边上的树木是否可见。
  • 设置最大深度为10 1010,这足以覆盖所有可能可见的树木。

4. 实现细节

  • 使用isObscured函数判断两棵树之间的遮挡关系。
  • 使用isVisible函数判断一棵树是否被当前层内的任何更近的树遮挡。
  • 主函数循环读取输入,对每个测试用例调用visibleTrees计算可见树木数量并输出。

代码实现

// Forests// UVa ID: 149// Verdict: Accepted// Submission Date: 2016-02-01// UVa Run Time: 0.000s//// 版权所有(C)2016,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;constdoublePI=3.14159265358;structpoint{doublex,y;};doublediameter,x,y;point base[4]={{100,100},{0,100},{0,0},{100,0}};intsteps[4][2]={{100,100},{-100,100},{-100,-100},{100,-100}};intsubSteps[8][2]={{-100,0},{0,-100},{100,0},{0,-100},{100,0},{0,100},{-100,0},{0,100}};doublemaxCos=cos(0.01/180*PI);boolisObscured(point near,point far){doublea=pow(x-near.x,2)+pow(y-near.y,2);doubleb=pow(x-far.x,2)+pow(y-far.y,2);doublec=pow(near.x-far.x,2)+pow(near.y-far.y,2);doubleA=asin(diameter/2/sqrt(a));doubleB=asin(diameter/2/sqrt(b));doublecosC=(a+b-c)/(2*sqrt(a)*sqrt(b));// 因为余弦的值域为[-1, 1],故绝对值大于 1 的值取反余弦会得到一个非数值(NAN),// 而且题目中提到当角度大于 0.01 度时人眼才能区分,因此需要设定一个阈值。// 此处是关键,否则很可能 Wrong Answer。if(cosC>=maxCos)returntrue;doubleC=acos(cosC);return((C-A-B)*180/PI)<=0.01f;}boolisVisible(point tree,intdepth,intquadrant){for(intsubDepth=0;subDepth<depth;subDepth++){point corner={base[quadrant].x+subDepth*steps[quadrant][0],base[quadrant].y+subDepth*steps[quadrant][1]};if(isObscured(corner,tree))returnfalse;for(intj=2*quadrant;j<2*(quadrant+1);j++)for(intk=0;k<subDepth;k++){point vertex={corner.x+subSteps[j][0]*(k+1),corner.y+subSteps[j][1]*(k+1)};if(isObscured(vertex,tree))returnfalse;}}returntrue;}intvisibleTrees(){intcount=0;for(intdepth=0;depth<=10;depth++)for(inti=0;i<4;i++){point corner={base[i].x+depth*steps[i][0],base[i].y+depth*steps[i][1]};if(isVisible(corner,depth,i))count++;for(intj=2*i;j<2*(i+1);j++)for(intk=0;k<depth;k++){point tree={corner.x+subSteps[j][0]*(k+1),corner.y+subSteps[j][1]*(k+1)};if(isVisible(tree,depth,i))count++;}}returncount;}intmain(){while(cin>>diameter>>x>>y){diameter=(int)(diameter*100);x=(int)(x*100),y=(int)(y*100);if(diameter==0&&x==0&&y==0)break;cout<<visibleTrees()<<endl;}return0;}

总结

本题的关键在于将无限网格问题转化为有限范围内的几何遮挡判断。通过合理的枚举顺序和角度计算,可以在有限时间内得到正确结果。代码中使用了整数运算以提高精度和效率,同时注意处理了角度比较的边界情况,避免了因浮点误差导致的错误。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/20 0:08:45

Qwen-Image-Layered部署实录:Docker方式一键启动服务

Qwen-Image-Layered部署实录&#xff1a;Docker方式一键启动服务 Qwen-Image-Layered 不是传统意义上的图像生成模型&#xff0c;而是一个专为图像可编辑性重构而生的智能分层引擎。它不生成新内容&#xff0c;而是把一张普通图片“解构”成多个语义清晰、边界准确、彼此独立的…

作者头像 李华
网站建设 2026/3/14 4:05:45

医疗级分子可视化:在Maya中构建生物分子3D模型的专业指南

医疗级分子可视化&#xff1a;在Maya中构建生物分子3D模型的专业指南 【免费下载链接】blender-chemicals Draws chemicals in Blender using common input formats (smiles, molfiles, cif files, etc.) 项目地址: https://gitcode.com/gh_mirrors/bl/blender-chemicals …

作者头像 李华
网站建设 2026/3/9 17:38:34

3大颠覆性功能让AI代码审查效率提升50%

3大颠覆性功能让AI代码审查效率提升50% 【免费下载链接】claude-code Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git w…

作者头像 李华
网站建设 2026/3/20 6:01:35

GLM-4V-9B企业部署方案:Nginx反向代理+HTTPS+用户权限控制

GLM-4V-9B企业部署方案&#xff1a;Nginx反向代理HTTPS用户权限控制 1. 为什么需要企业级部署&#xff1a;从本地Demo到生产环境的跨越 你可能已经试过GLM-4V-9B的Streamlit本地版本——上传一张图&#xff0c;输入几个问题&#xff0c;模型秒级响应&#xff0c;效果惊艳。但…

作者头像 李华
网站建设 2026/3/14 19:15:54

Figma-to-JSON高效转换工具:设计开发协作必备指南

Figma-to-JSON高效转换工具&#xff1a;设计开发协作必备指南 【免费下载链接】figma-to-json 项目地址: https://gitcode.com/gh_mirrors/fi/figma-to-json 在数字化协作流程中&#xff0c;设计文件与开发资源的格式转换常成为效率瓶颈。设计师使用Figma创建的视觉资产…

作者头像 李华