直接上中文题面
King's Problem?
时间限制:3.0s 内存限制:256.0MB Special Judge
问题描述
每一个真正的国王在他的一生中,一定会征服世界,取得 codeforces 的世界冠军,在射击场赢得粉色的熊猫(= =),并游历整个王国。
国王 Copa 已经完成了前三件事。现在他只需要游历完整个王国了。他的王国在一个无限大的笛卡尔坐标系上,每个城市是平面上的一个点。王国里有 n 个城市,坐标分别为 (x_1, 0),(x_2, 0), ..., (x_n, 0) ,除此之外还有一个城市坐标为 (x_{n + 1}, y_{n + 1}) 。
国王 Copa 从标号为 k 的城市开始旅行。你的任务是为国王找一条可以遍历所有城市的路径(任何顺序都可以),并且路径长度最小。一个城市允许访问两次。国王可以在任意一个城市结束旅行。任意一对城市之间都存在一条道路,长度为两点之间的欧几里得距离。数据保证没有任意两个点重合。
输入格式( kings.in)
第一行包含两个整数 n, k (1<= n <= 10^5, 1 <= k <= n + 1) ,意义见题。
第二行包含 n + 1 个整数 x_i 。
第三行包含一个整数 y_{n + 1} 。
任意坐标均为整数,绝对值不超过 10^6 ,且没有两个点重合。
输出格式
输出一行,表示最小的可能的路径长度。你的答案与标准答案的绝对误差或相对误差不应超过 10^-6 。
样例输入(kings.out)
3 1
0 1 2 1
1
样例输出
3.41421356237309490000
样例输入
3 1
1 0 2 1
1
样例输出
3.82842712474619030000
样例输入
4 5
0 5 -1 -5 2
3
样例输出
14.24264068711928400000
数据规模和约定
对于 10% 的数据: n <= 5
对于 30% 的数据: n <= 10
对于 50% 的数据: n <= 20
对于 100% 的数据: n <= 10^5
存在 20% 的数据: k > n
【题解】
一直不明白枚举K是什么意思- = 远程ORZ了一下YGW神犇以后秒懂了233
枚举断点i, 1~i-1设为从P出发的策略(策略一),i~n设为策略二 或 1~i-1设为策略二,i~n设为策略一 ,取二者最小值,再用这个最小值更新答案
策略一、二能够保证从K出发,在P汇聚,连接两条子路径
#include<cstdio> #include<cmath> #include<algorithm> #include<cstring> using namespace std; int k,i,j,n; double ans,x[100010],xp,yp,xk; double C(int z){ return hypot(x[z]-xp,yp); } //p到z点距离 double A(int l,int r){ return x[r]-x[l]+min(C(l),C(r)); } //l->r->p double B(int l,int r){ return x[r]-x[l]+min(abs(xk-x[l])+C(r),abs(xk-x[r])+C(l)); }//k->l->r->p void inlinework(){ //给定起点在轴上 ans=B(1,n); //起点为断点的情况 for (i=2;i<=n;i++){ //从2开始 double t=min(A(1,i-1)+B(i,n),A(i,n)+B(1,i-1)); if (t<ans) ans=t; } } void outlinework(){ //给定起点就是轴外点时必为最优 ans=A(1,n); } int main() { freopen("kings.in","r",stdin); freopen("kings.out","w",stdout); scanf("%d%d",&n,&k); for (i=1;i<=n;i++) scanf("%lf",&x[i]); scanf("%lf%lf",&xp,&yp); xk=x[k]; sort(x+1,x+n+1); if (k<=n) inlinework(); else outlinework(); printf("%.20lf\n",ans); }