New Year Table

今天做了codeforces上的operation weak win训练营题目。很不幸, 第一题就被卡了。
下面给出原题。
A. New Year Table
time limit per test 2 seconds memory limit per test 256 megabytes

input
standard input
output
standard output

Gerald is setting the New Year table. The table has the form of a circle; its radius equals R. Gerald invited many guests and is concerned whether the table has enough space for plates for all those guests. Consider all plates to be round and have the same radii that equal r. Each plate must be completely inside the table and must touch the edge of the table. Of course, the plates must not intersect, but they can touch each other. Help Gerald determine whether the table is large enough for n plates.
Input

The first line contains three integers n, R and r (1 ≤ n ≤ 100, 1 ≤ r, R ≤ 1000) — the number of plates, the radius of the table and the plates’ radius.
Output

Print “YES” (without the quotes) if it is possible to place n plates on the table by the rules given above. If it is impossible, print “NO”.

Remember, that each plate must touch the edge of the table.
Examples
Input
4 10 4
Output
YES

Input
5 10 4
Output
NO

Input
1 10 10
Output
YES

题意给出n-小球的个数,R-大球的半径,r-小球的半径。问在大球里能放下n个小球吗?
注:本题目规定了小球必须紧贴着大球,这样难度其实有所减小,至少小球最多只能围成一圈,不会出现以下的情况,这里写图片描述如果是这样的情况,那么根据小球半径,还要再加上几个循环。实际上里圈就是外圈的缩影,那么里圈大球半径实为(R-n*2*r),小球半径照旧,然后while(R-n*2*r>0)即可求出最大球数。

不过本题目我们只需要考虑最外圈一层就够了。
本题是一道几何体,很简单,无非是通过作图然后正余弦公式得到。
先从大圆圆心作一条切线到小圆边,然后两个圆心一连,一个直角三角形就出来了。三边分别为斜边(R-r),直角边r,还有另一个直角边我们可以通过圆心角正弦公式得到。
我们可以判断理论圆心角和实际圆心角的大小,这里代码比较的是理论半径和实际半径r的大小。
理论半径—–>(R-r) * sin(x),x为弧度,大小为(角度2π/360),角度大小为(360/n),化简得到x为(2π/n)。然后正弦定理就可以得到理论半径。如果实际半径大于理论半径,那么输出NO,反之输出YES。

本题目是几何题,最麻烦的是精度问题,一开始我用的是余弦定理,但是在算式中浮点数计算越复杂,可能丢的低位数就越多。一般处理精度问题通常有以下几种办法:
1.首先π我们用 const int PI = acos(-1.0)来表示,当然我这么写是错的,应该是const double PI = acos(-1.0),我int写顺手了,然后就精度差得很大,也不知道余弦定理是不是这个原因错的。
2.使用eps,eps一般为1e-8,如果误差在eps之内,那么直接当作相等。本题用的1e-9,其实也可以。如果不是判断大小,而是判断是否相等,还要加上fabs()。

代码如下:

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <complex>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <cassert>
using namespace std;
const int MAXN = 10000;
const double PI = acos(-1.0);
const double eps=1e-9;
double n,R,r;
int main()
{
    scanf("%lf%lf%lf",&n,&R,&r);
    if(R<r) {printf("NO\n");return 0;}
    if(R>=r) {
        if(n==1) {printf("YES\n");return 0;}
    }
    double r1=R*sin(PI/n)/(1+sin(PI/n));
    //cout<<r1<<' '<<r<<endl;
    if(r1+eps>=r) printf("YES\n");
    else puts("NO");
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值