zoukankan      html  css  js  c++  java
  • 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);
    }
    
    
  • 相关阅读:
    uva 11294 Wedding
    uvalive 4452 The Ministers’ Major Mess
    uvalive 3211 Now Or Later
    uvalive 3713 Astronauts
    uvalive 4288 Cat Vs. Dog
    uvalive 3276 The Great Wall Game
    uva 1411 Ants
    uva 11383 Golden Tiger Claw
    uva 11419 SAM I AM
    uvalive 3415 Guardian Of Decency
  • 原文地址:https://www.cnblogs.com/ssdfzhyf/p/14513516.html
Copyright © 2011-2022 走看看