Codeforces 838E Convex Countour

  OvO http://codeforces.com/contest/838/problem/E

  (IndiaHacks 2nd Elimination 2017 (unofficial, unrated mirror, ICPC rules) - E)

  dp[i][j][k]表示左端点为i,右端点为j这个区间(如果i>j,就是(i~n),(1,j)),状态为k(k=0说明i这端可以接,k=1说明j这端可以接)

  枚举长度,

  那么对于dp[i][j][0],可以从dp[i-1][j][0]接上i-1与i这一段,或者dp[i-1][j][1]接上j与i这一段

  对于状态为1的时候,类似可以得到答案

  (思路来自KOKOZDRA的提交

  

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iomanip>

using namespace std;

typedef long double ld;

const int M=2544;

struct node
{
	int x,y;
}	p[M];

ld dis(node a,node b)
{
	ld dx=a.x-b.x;
	ld dy=a.y-b.y;
	return sqrt(dx*dx+dy*dy);
}

int n;
ld mp[M][M];
ld dp[M][M][2],ans;	//dp[i][j][k]  k==0 means i is ok to connect, otherwise j 

void init()
{
	int i,j,pi,qi;
	for(i=1;i<=n;i++)
		for(j=i;j<=n;j++)
			mp[i][j]=mp[j][i]=dis(p[i],p[j]);
	ans=0;
}

int trf(int x)
{
	if(x>n) return x-n;
	if(x<1) return x+n;
	return x;
}

void solve()
{
	memset(dp,0,sizeof(dp));
	int i,j,ti,tj;
	ld tmp;
	for(ti=2;ti<=n;ti++)	//length
		for(tj=1;tj<=n;tj++)
		{
			i=tj; j=trf(tj+ti-1);	//string of ([i~j] (if(j<i) j+=n)) 
			dp[i][j][0]=max(dp[trf(i+1)][j][0]+mp[trf(i+1)][i],dp[trf(i+1)][j][1]+mp[j][i]);
			dp[i][j][1]=max(dp[i][trf(j-1)][0]+mp[i][j],dp[i][trf(j-1)][1]+mp[trf(j-1)][j]);
			ans=max(ans,max(dp[i][j][0],dp[i][j][1]));
		}
}

int main()
{
	int i,j,it,qi,pi;
	ld tmp,mx;
	scanf("%d",&n);
	for(i=1;i<=n;i++)
		scanf("%d%d",&p[i].x,&p[i].y);
	init();
	solve();
//	printf("%.10Lf
",ans);
	cout<<fixed<<setprecision(10)<<ans<<endl;
	return 0;
}

/*

7
0 0
0 1000
1 1000
1000 999
1001 1
1000 0
1 -1

*/

  

  赛时真的贼痛苦、太菜

  

原文地址:https://www.cnblogs.com/FxxL/p/7301572.html