Gym-102576H Lighthouses

题目传送门

分析:
把凸多边形简化成一个圆,一次电车游览会把圆分割成两部分,之后只能在其中一部分里面进行游览
考虑DP,设\(F_{i,j,0/1}\)表示,目前我们只能游览逆时针方向\((i,j)\)中的点,并且下一步是从\(i\)还是\(j\)出发
枚举区间中的某个点\(k\),分类讨论,简单转移

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>

#define maxn 305
#define eps 1e-7

using namespace std;

inline int getint()
{
	int num=0,flag=1;char c;
	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
	while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
	return num*flag;
}

int n,m;
struct node{
	double x,y;
}p[maxn];
double dis[maxn][maxn],f[maxn][maxn][2];
inline double getdis(node x,node y)
{return sqrt(pow(x.x-y.x,2)+pow(x.y-y.y,2));}

int main()
{
	int T=getint();
	while(T--)
	{
		memset(dis,0,sizeof dis),memset(f,0,sizeof f);
		n=getint();
		for(int i=0;i<n;i++)p[i].x=getint(),p[i].y=getint();
		m=getint();
		for(int i=1;i<=m;i++)
		{
			int u=getint()-1,v=getint()-1;
			dis[u][v]=dis[v][u]=getdis(p[u],p[v]);
			f[u][v][0]=f[v][u][0]=f[u][v][1]=f[v][u][1]=dis[u][v];
		}
		for(int d=n-1;d;d--)for(int i=0;i<n;i++)
		{
			int j=(i+d)%n;
			for(int k=(i+1)%n;k!=j;k=(k+1)%n)
			{
				if(dis[k][j]>0)
				{
					f[i][k][1]=max(f[i][k][1],f[i][j][1]+dis[k][j]);
					f[k][j][0]=max(f[k][j][0],f[i][j][1]+dis[k][j]);
				}
				if(dis[i][k]>0)
				{
					f[i][k][1]=max(f[i][k][1],f[i][j][0]+dis[k][i]);
					f[k][j][0]=max(f[k][j][0],f[i][j][0]+dis[k][i]);
				}
			}
		}
		double ans=0;
		for(int i=0;i<n;i++)for(int j=0;j<n;j++)ans=max(ans,max(f[i][j][0],f[i][j][1]));
		printf("%.10lf\n",ans);
	}
}

posted @ 2020-06-27 15:29  Izayoi_Doyo  阅读(318)  评论(0编辑  收藏  举报