【贪心】codeforces30D King‘s problem

来源:互联网 发布:华中博盈软件 编辑:程序博客网 时间:2024/05/22 22:28

直接上中文题面

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->pvoid 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);}    

0 0
原创粉丝点击