2020 ICPC Shanghai Site I 简单计算几何

题目链接

文章目录

题意:

n个同心圆,第i个圆的半径为i,m条直线将每个圆分割成相等的2*m个部分,每条直线和每个圆都有两个交点。 P P P是交点的集合,求集合中任何两个点的最短距离的和。

  1. m m m条直线将每个圆分成均等的 2 m 2m 2m个部分,圆上有 2 m 2m 2m个点
  2. 首先我们考虑同一个圆上两两点的最短距离:要么是弧长,要么是直径。所以我们直接遍历判断,求得点1,到其他点的最短距离 r e s res res, 然后有 2 m 2m 2m个点,因为每个距离都被算了两遍,所以这个圆上两两点的最短距离就是 r e s ∗ 2 m 2 = r e s ∗ m \frac {res*2m}{2}=res*m 2res2m=resm
  3. 然后我们考虑从第j个圆到第i个圆上的点的距离,我们以下图为例子,点A要到1,2,3,4的最短距离,首先必定经过半径差d,点A点2,3,4的最短距离,等价于点1到点2,3,4的距离加上d..所以点A到点1,2,3,4的最短距离等于 d ∗ 2 m + r e s d*2m+res d2m+res, 由于外圆上也有 2 m 2m 2m个点,对应内圆的 2 m 2m 2m个点,所以外圆到内圆点的距离之和为 2 m ∗ 2 m ∗ d + r e s ∗ 2 m 2m*2m*d + res*2m 2m2md+res2m
    在这里插入图片描述
  4. 如果m>1时,圆心也会出现交点5,点5到点1,2,3,4的最短距离就是 2 m ∗ r 2m*r 2mr
    在这里插入图片描述
  5. 把以上计算结果加起来就是答案

代码

提供两份

#include<bits/stdc++.h>


using namespace std;
const double PI = acos(-1);
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	double ans=0;
	//每个圆被分成了2*m个部分 
	int sum=2*m;
	//枚举每个圆的半径 
	for(int k=1; k<=n; k++)
	{
		double r=k;
		//因为圆被分成了2*m个部分,所以每个部分的弧长是tmp 
		double tmp=2*PI*r/sum;
		//当前圆两两点直接的距离之和 
		double res=0; 
		//这里计算的是圆上的点到圆心的距离
		//前提是圆心要有交点,故需要判断m>1 
		if(m>1) ans+=sum*r;
		for(int j=2; j<=sum; j++)
		{
				int d=abs(1-j);
				if(d>m) d=sum-d;
				//圆上两个点之间的距离要么是,弧长最短,要么是直径最短 
				res+=min(d*tmp,2*r);
		} 
		res=res*2*m/2;
		//这里不仅要加上res,还要加上res对后面圆的贡献 
		ans+=res+res*(n-k)*2;
	}
	//计算两两圆直接的半径差 
	for(int i=1; i<=n; i++)
	{
		for(int j=i+1; j<=n; j++)
		{
			ans+=abs(i-j)*(2*m*2*m);
		}
	}
	printf("%f\n",ans);
	return 0;
}
#include<bits/stdc++.h>


using namespace std;
const double PI = acos(-1);
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	double ans=0;
	int sum=2*m;
	for(int k=1; k<=n; k++)
	{
		double r=k;
		double tmp=2*PI*r/sum;
		double res=0;
		if(m>1) ans+=sum*r;
		for(int i=1; i<=sum; i++)
		{
			for(int j=i+1; j<=sum; j++)
			{
				int d=abs(i-j);
				if(d>m) d=sum-d;
				res+=min(d*tmp,2*r);
			} 
		}
		ans+=res+res*(n-k)*2;
	}
	for(int i=1; i<=n; i++)
	{
		for(int j=i+1; j<=n; j++)
		{
			ans+=abs(i-j)*(2*m*2*m);
		}
	}
	printf("%f\n",ans);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值