Description
一只邪恶的猫王组建了一个庞大的后宫,她们的寝宫排成一条直线(x1,0),(x2,0),...,(xn,0),王后住在(xn+1,yn+1),一天,猫王突然兴起,想要一夜之间游遍所有寝宫,所以它想雇用聪明的你帮他计算最短的路径。刚开始,猫王在第k个寝宫,可以终止于任意寝宫,且可以经过同一寝宫多次。
Input:
有多组测试数据,对于每组测试数据
第一行n,k,n表示直线上的寝宫数,k表示起始编号(1=<n<=10^5,1=<k<=n+1)
第二行n+1个整数,分别表示x1,x2...,xn+1
第三行输入yn+1
xi,yn+1的绝对值不超过10^6。
Output:
对于每组测试数据
输出最短路径,保留10位小数
Sample input:
4 1
0 5 -1 -5 2
3
1 1
8 4
5
3 1
0 1 2 1
1
3 1
1 0 2 1
1
Sample output:
16.8584137930
6.4031242374
3.4142135624
3.8284271247
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int n,p;
double s[100001],b[100001],xm,ym;
double getdist(int i)
{
return sqrt((b[i]-xm)*(b[i]-xm)+ym*ym);
}
double solve(int l,int r)
{
if(l>r) return 0;
double sum=b[r]-b[l];
if(l<=p&&p<=r) return sum+min(getdist(l)+b[r]-b[p],getdist(r)+b[p]-b[l]);
return sum+min(getdist(l),getdist(r));
}
int main()
{
long long k,j;
int i;
double sum,z;
while(cin>>n>>k)
{
memset(s,0,n);
j=1;
sum=9999999999.0;
for(i=0;i<n;i++)
cin>>s[i];
cin>>xm>>ym;
z=s[k-1];
sort(s,s+n);
b[0]=s[0];
for(i=1;i<n;i++)
if(s[i]>s[i-1]) b[j++]=s[i];
if(k==n+1) sum=b[j-1]-b[0]+min(getdist(0),getdist(j-1));
else
{
for(i=0;i<j;i++)
if(b[i]==z) p=i;
for(i=0;i<j;i++)
sum=min(sum,solve(0,i-1)+solve(i,j-1));
}
printf("%.10lf\n",sum);
}
return 0;
}
做了一下午的题,一开始觉得只是有一个数据不能过而已,后来才知道是根本就少考虑了一种情况。传说中的差一点差万里。交了好多次都WA了,陆续发现了好多的问题。很脑残的没有把文件的输入输出删掉。还有两个数组弄混了。虽然在一些数据中看不出来,但是有很大的影响。
解题思想是枚举法。主要还是读题,找路径的时候不能想当然,要多考虑几种情况。
两种走法,一种是先走完直线再走到皇后点。一种是走一段直线之后走到皇后点,再从皇后点走到终点。(只考虑到了第一种,忽略了第二种。智商问题。)
所以从第一个点开始到最后一个点枚举计算路径长度,每一个点按照两种方式走取较小的那个值,后一个点的较小值再和之前的较小值比较,那么最后的值就是最短的路径。