首先将n个点排序,找出排序后的K,然后分情况讨论。
当 k == n+1时,显然是 k->1->n || k->n->1这两种的较小值,因为三角形的两边之和大于第三边。
当1 <= k && k <= n 时:
1 , k -> 1 -> n+1 -> k+1 ->n || k -> n -> n+1 -> k-1 -> 1,当k+1 || k-1 不存在时将对应步骤忽略。
2 , k - > 1 -> n+1 -> n -> k+1 || k ->n -> n+1 -> 1 -> k-1,当k+1 || k-1 不存在时将对应步骤忽略。
3,这是一种比较奇葩的策略,刚开始做时直觉上认为这种情况是不会存在的,可是.....5个WA教做人。
k -> i -> n -> n+1 -> i-1 -> 1 (i < k) || k -> i -> 1 -> n+1 - > i+1 -> n (i > k) 。
可以理解为花费了 abs(site[k]-site[i]) 的代价以更换起点使得总价值最小,智商好捉急。
#include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #include <cmath> #include <stack> #include <map> #include <ctime> #include <iomanip> #pragma comment(linker, "/STACK:1024000000"); #define EPS (1e-6) #define _LL long long #define ULL unsigned long long #define LL __int64 #define INF 0x3f3f3f3f #define Mod 1000000007 /** I/O Accelerator Interface .. **/ #define g (c=getchar()) #define d isdigit(g) #define p x=x*10+c-'0' #define n x=x*10+'0'-c #define pp l/=10,p #define nn l/=10,n template<class T> inline T& RD(T &x) { char c; while(!d); x=c-'0'; while(d)p; return x; } template<class T> inline T& RDD(T &x) { char c; while(g,c!='-'&&!isdigit(c)); if (c=='-') { x='0'-g; while(d)n; } else { x=c-'0'; while(d)p; } return x; } inline double& RF(double &x) //scanf("%lf", &x); { char c; while(g,c!='-'&&c!='.'&&!isdigit(c)); if(c=='-')if(g=='.') { x=0; double l=1; while(d)nn; x*=l; } else { x='0'-c; while(d)n; if(c=='.') { double l=1; while(d)nn; x*=l; } } else if(c=='.') { x=0; double l=1; while(d)pp; x*=l; } else { x=c-'0'; while(d)p; if(c=='.') { double l=1; while(d)pp; x*=l; } } return x; } #undef nn #undef pp #undef n #undef p #undef d #undef g using namespace std; LL num[100010]; double Cal(LL x,LL x0,LL y0) { return sqrt((x-x0)*(x-x0) + y0*y0); } int main() { int n,i; LL x,y,k; scanf("%d %I64d",&n,&k); for(i = 1;i <= n; ++i) scanf("%I64d",&num[i]); scanf("%I64d %I64d",&x,&y); if(k == n+1) { sort(num+1,num+n+1); double anw = num[n]-num[1] + min( Cal(num[n],x,y),Cal(num[1],x,y) ); for(i = 2;i < n; ++i) anw = min(anw,min(num[n]-num[i],num[i]-num[1]) + num[n]-num[1] + Cal(num[i],x,y)); printf("%.10lf\n",anw); return 0; } k = num[k]; sort(num+1,num+n+1); for(i = 1;i <= n && num[i] != k; ++i) ; k = i; double Min = 1000000000; double tmp; tmp = num[k]-num[1] + num[n]-num[1]; for(i = 2;i <= n; ++i) Min = min(Min,tmp + Cal(num[i-1],x,y) + Cal(num[i],x,y) - (num[i]-num[i-1])); tmp = num[n]-num[k] + num[n]-num[1]; for(i = 2;i <= n; ++i) Min = min(Min,tmp + Cal(num[i-1],x,y) + Cal(num[i],x,y) - (num[i]-num[i-1])); tmp = num[n]-num[1]; if(k-1) { Min = min(Min,tmp + Cal(num[n],x,y) + Cal(num[k-1],x,y) - (num[k]-num[k-1])); Min = min(Min,tmp + Cal(num[n],x,y) + Cal(num[1],x,y) - (num[k]-num[k-1])); } else { Min = min(Min,tmp + Cal(num[n],x,y)); } if(k+1 <= n) { Min = min(Min,tmp + Cal(num[1],x,y) + Cal(num[k+1],x,y) - (num[k+1]-num[k]) ); Min = min(Min,tmp + Cal(num[1],x,y) + Cal(num[n],x,y) - (num[k+1]-num[k]) ); } else { Min = min(Min,tmp + Cal(num[1],x,y)); } Min = min(Min,num[n]-num[1]+num[k]-num[1] + Cal(num[n],x,y)); Min = min(Min,num[n]-num[1]+num[n]-num[k] + Cal(num[1],x,y)); for(i = k+1;i <= n; ++i) { if(i!=n) { Min = min(Min,num[i]-num[k]+num[i]-num[1]+Cal(num[1],x,y)+Cal(num[i+1],x,y)+num[n]-num[i+1]); } else { Min = min(Min,num[i]-num[k]+num[i]-num[1]+Cal(num[1],x,y)+Cal(num[i+1],x,y)); } } for(i = k-1;i >= 1; --i) { if(i!=1) { Min = min(Min,num[k]-num[i]+num[n]-num[i]+Cal(num[n],x,y)+Cal(num[i-1],x,y)+num[i-1]-num[1]); } else { Min = min(Min,num[k]-num[i]+num[n]-num[i]+Cal(num[n],x,y)+Cal(num[i-1],x,y)); } } printf("%.10lf\n",Min); return 0; }
Codeforces 30D King's Problem? 模拟
时间: 2024-11-10 09:44:54