【题解】CF30D King's Problem?

CF30D

题意

\(n+1\) 个点,其中的 \(n\) 个点在数轴上。求以点 \(k\) 为起点走过所有点的最短距离,允许重复。

思路

有两种情况:

  • \(k\) 在数轴上(如图1)。
  • \(k\) 在第 \(n+1\) 个点上(如图2)。

图1:

图2:

像第一种情况:

一定存在数轴上某点 \(k\) ,使得人先走遍 \(1\sim k\) ,回来,再走遍 \(k + 1\sim n\)

或点 \(k\) ,使得人先走遍 \(k + 1\sim n\) ,回来,再走遍 \(1\sim k\)

从点 \(p\) 出发,走一个区间 \(\left [ l,r \right ]\)

最短方案显然是从 \(p\)\(l\)\(r\) 中较近的一个,然后一路走到对面。 距离是\(dist (a_l ,a_r ) + \min(dist(p,a_l ),dist(p,a_r ))\)

从点 \(k\) 出发,走一个区间 \([l ,r]\) ,再回到 \(p\) 。最佳方案可以证明是从 \(k\) 走到 \(l\)\(r\) 中的某一个,然后走到对面,然后走到 \(p\) 。距离是 \(|a_l-a_r| + \min(|a_k-a_l| +dist(r),| a_k-a_r | +dist(l))\)

AC Code

#include<bits/stdc++.h>
using namespace std;
int k,i,j,n;
double ans,x[100010],xp,yp,xk;
double C(int z) {
	return hypot(a[z]-xp,yp);//hypot勾股定理 
}
double A(int l,int r) {
	return a[r]-a[l]+min(C(l),C(r)); 
}
double B(int l,int r) {
	return a[r]-a[l]+min(abs(xk-a[l])+C(r),abs(xk-a[r])+C(l)); 
}
int main() {
	cin>>n>>k;
	for (i=1; i<=n; i++) cin>>a[i];
	cin>>xp>>yp;
	xk=a[k];
	sort(a+1,a+n+1);
	if (k<=n) {
		ans=B(1,n);
		for (i=2; i<=n; i++) {
			double t=min(A(1,i-1)+B(i,n),A(i,n)+B(1,i-1));
			if (t<ans) ans=t;
		}
		printf("%.20lf\n",ans);
	} else printf("%.20lf\n",A(1,n));
	return 0;
}
posted @ 2024-04-06 17:59  Kcjhfqr  阅读(33)  评论(0)    收藏  举报
.poem-wrap { position: relative; width: 1000px; max-width: 80%; border: 2px solid #797979; border-top: none; text-align: center; margin: 40px auto; } .poem-left { left: 0; } .poem-right { right: 0; } .poem-border { position: absolute; height: 2px; width: 27%; background-color: #797979; } .poem-wrap p { width: 70%; margin: auto; line-height: 30px; color: #797979; } .poem-wrap h1 { position: relative; margin-top: -20px; display: inline-block; letter-spacing: 4px; color: #797979; font-size: 2em; margin-bottom: 20px; } #poem_sentence { font-size: 25px; } #poem_info { font-size: 15px; margin: 15px auto; }