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