• 2020 ICPC Shanghai I


    题目链接:
    https://vjudge.net/contest/416227#problem/I
    这个题要分2种情况讨论
    1.m=1
    按照题目的意思,由于只有一条直径,不会在圆心产生交点,中间的原点是不存在的,所以任意两个点间走线段即可,可以推一波公式,也可以枚举
    2.m>1
    由于这个图是旋转对称以及左右对称的,我们不用求出每两个点的间距,我们可以设(dis[i][j][k])表示从半径为(i)的同心圆走到半径为(j)的同心圆上,且两个点的极角的差的绝对值为(frac{kpi}{m})时,最短路径是多少,其中(jle ile n,kle m)
    那么当(i>j),我们现在有一种普通的走法,就是从半径为(i)的圆,沿着直径走到半径为(j)的圆,然后再沿着圆弧走到对应位置,这个长度为(i-j+frac{jkpi}{m}),那么(dis[i][j][k])一定不大于它。
    由于两个点极角的差的绝对值为(frac{kpi}{m}),我们必须在圆弧上走过对应的极角长度。假如我们在半径大于(j)的圆上走过了(frac{kpi}{m})的角度,那么圆弧长大于(frac{jkpi}{m}),然而在直径上肯定要走不少于(i-j)的长度,所以一定不是最优的。
    那么,我们可以认为,走这段路一定经过了从半径为(i)的圆到半径为(j)的圆的直径,这个线段的长度为(i-j)。然后我们现在和终点在同一个圆上,极角为(frac{kpi}{m}),这段距离就是(dis[j][j][k])
    (i=j)时,起点和终点在一个圆上,我们可以选择走圆弧,也可以选择向圆心走一段,然后走一个较小的圆弧,再回到那个半径为(i)的圆

    代码如下:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    double dis[510][510][510];
    const double pi=acos(-1.0);
    int main()
    {
    	int n,m;
    	scanf("%d%d",&n,&m);
    	double ans=0;
    	if(m==1)
    	{
    		for(int i=1;i<=n;i++)
    		{
    			double ans1=0;
    			for(int j=1;j<i;j++)
    			{
    				for(int k=0;k<=1;k++)
    				{
    					dis[i][j][k]=i-j+(k)*2.0*j;
    					ans1+=dis[i][j][k];
    				}
    			}
    			ans1*=2;
    			dis[i][i][0]=0;
    			dis[i][i][1]=2*i;
    			ans1+=dis[i][i][1];
    			ans+=ans1;
    		}
    		printf("%.10lf
    ",ans);
    		return 0;
    	}
    	
    	for(int i=1;i<=n;i++)
    	{
    		for(int k=0;k<=m;k++)dis[i][0][k]=i;
    		
    		for(int j=1;j<i;j++)
    		{
    			for(int k=0;k<=m;k++)dis[i][j][k]=i-j+dis[j][j][k];
    		}
    		for(int k=0;k<=m;k++)
    		{
    			dis[i][i][k]=(i*k*pi)/m;
    			for(int j=0;j<i;j++)dis[i][i][k]=min(dis[i][j][k]+i-j,dis[i][i][k]);
    		}
    		double ans1=0;
    		for(int j=1;j<i;j++)
    		{
    			for(int k=1;k<m;k++)ans1+=2*dis[i][j][k];
    			ans1+=dis[i][j][0]+dis[i][j][m];
    		}
    		ans1+=dis[i][0][0];
    		ans1=ans1*2*m;
    		double ans2=0;
    		ans2+=dis[i][i][m];
    		for(int k=1;k<m;k++)ans2+=2*dis[i][i][k];
    		ans2=ans2*m;
    		ans+=ans1+ans2;
    	}
    	printf("%.10lf
    ",ans);
    }
    
    
  • 相关阅读:
    学习游戏设计
    AspectJ
    Spring AOP进行日志记录,管理 (使用Spring的拦截器功能获取对action中每个方法的调用情况,在方法调用前和调用后记录相关日志。)
    Java内存泄露测试及工具
    使用Tomcat插件开发WEB应用
    想学习建个网站?WAMP Server助你在Windows上快速搭建PHP集成环境
    UML 基础:类图
    Impala学习--Impala前端代码分析,Impala后端代码分析
    Impala学习--Impala概述,Impala系统架构
    图论--2-SAT--HDU/HDOJ 1814 Peaceful Commission
  • 原文地址:https://www.cnblogs.com/ssdfzhyf/p/14513516.html
Copyright © 2020-2023  润新知