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\n",ans); cout<<fixed<<setprecision(10)<<ans<<endl; return 0; } /* 7 0 0 0 1000 1 1000 1000 999 1001 1 1000 0 1 -1 */
赛时真的贼痛苦、太菜