第二次周赛_E邪恶的猫王

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了,陆续发现了好多的问题。很脑残的没有把文件的输入输出删掉。还有两个数组弄混了。虽然在一些数据中看不出来,但是有很大的影响。

解题思想是枚举法。主要还是读题,找路径的时候不能想当然,要多考虑几种情况。

两种走法,一种是先走完直线再走到皇后点。一种是走一段直线之后走到皇后点,再从皇后点走到终点。(只考虑到了第一种,忽略了第二种。智商问题。)

所以从第一个点开始到最后一个点枚举计算路径长度,每一个点按照两种方式走取较小的那个值,后一个点的较小值再和之前的较小值比较,那么最后的值就是最短的路径。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值