[Codeforces 30D] Kings Problem

Brief Intro:

有n+1个点,其中n个点在X轴上,求从第k个点出发最短的汉密尔顿路径

Solution:

分类讨论+逐个枚举

设dist(i)是第i个点到n+1的距离

cal1(l,r)是n+1到dat[l]~dat[r]的最短距离

cal2(l,r)是dat[k]到dat[l]~dat[r]再到n+1的最短距离

1、如果k=n+1,则答案明显是线段长+min(dist(1),dist(n))

2、否则要逐个枚举

可以发现共有2种可能:n+1连到线段的边有1条/2条

如为1条,则结果为cal1(1,n);

如为2条,则可将路径分为dat[k]到dat[l]~dat[r]再到n+1  +  n+1到剩余的点

明显剩余的点连续时有最优解

于是res[i]=min( cal1(1,i-1)+cal2(i,n) , cal2(1,i-1)+cal1(i,n) )。

Code:

#include <bits/stdc++.h>

using namespace std;

const int MAXN=1e5+10;
double dat[MAXN],x,y,kx;
int n,k;

double dist(int pos){return hypot(x-dat[pos],y);}

double cal1(int l,int r)
{
    return dat[r]-dat[l]+min(dist(l),dist(r));
}

double cal2(int l,int r)
{
    return dat[r]-dat[l]+min(dist(l)+fabs(kx-dat[r]),dist(r)+fabs(kx-dat[l]));
}

int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++) scanf("%lf",&dat[i]);
    scanf("%lf%lf",&x,&y);
    
    kx=dat[k];sort(dat+1,dat+n+1);
    
    double res;
    if(k==n+1) res=cal1(1,n);
    else
    {
        res=cal2(1,n);
        for(int i=2;i<=n;i++)
            res=min(res,min(cal1(1,i-1)+cal2(i,n),cal2(1,i-1)+cal1(i,n)));
    }
    printf("%.10f",res);
    return 0;
}
原文地址:https://www.cnblogs.com/newera/p/9086692.html