列表

详情


NC234577. 最短路

描述

题目背景

嘤嘤最近在摸鱼。她每天原神只上线20分钟,做一下每日、清一下体力就下号了。(你看,她题面都写的那么简洁,这摸鱼,多是一件美事啊!)

她在摸鱼,所以她渊下宫还没有开始肝,有很多的宝箱、常世之荚、渊海矿髓、珊瑚蝶物资,她必须全部拿完!

她在摸鱼,所以她想找到一条最短路径将这些物资收集完全!

她在摸鱼,所以这个任务就交给你了!

PS: 爱摸鱼的嘤嘤同学拿着从渊下宫收集的原石在0人池歪了77,嘤嘤气的说起了嘤语:嘤!嘤嘤嘤!嘤嘤嘤嘤嘤嘤!嘤嘤嘤!!嘤嘤嘤!!嘤嘤嘤嘤嘤!



题目描述

首先,我们忽略高度,将渊下宫看成二维地图,嘤嘤的初始位置为 (0,0)

嘤嘤知道地图上所有宝箱、常世之荚、渊海矿髓、珊瑚蝶、传送锚点的位置,她可以在初始位置或到达一个宝箱、常世之荚、渊海矿髓珊瑚蝶的位置时在此位置建立一个口袋锚点

传送锚点口袋锚点的作用是:你可以在任意位置传送至任意锚点。(注意:口袋锚点可以同时存在多个,此处与游戏设定不同

你需要帮助嘤嘤计算出她找完所有物资所需的最短路径。

输入描述

在第一行中,先输入四个整数  ,表示宝箱、常世之荚、渊海矿髓、珊瑚蝶的个数,再输入一个整数  表示传送锚点的位置。

接下来 a 行,每行两个整数  ,表示宝箱的位置。

接下来 b 行,每行两个整数  ,表示常世之荚的位置。

接下来 c 行,每行两个整数  ,表示渊海矿髓的位置。

接下来 d 行,每行两个整数  ,表示珊瑚蝶的位置。

接下来 n 行,每行两个整数  ,表示传送锚点的位置。

数据保证一个位置最多只有一个宝箱常世之荚渊海矿髓珊瑚蝶

输出描述

一个实数,表示嘤嘤从初始位置 (0,0)开始收集完所有物资的最短路径经过的距离。

你的答案与正确答案误差的绝对值不应超过 

示例1

输入:

1 1 1 0 1
2 0
3 0
2 1
1 0

输出:

3.0000000000

说明:

你可以从初始位置(0,0)传送至传送锚点(1,0),然后从(1,0)移动1到达宝箱(2,0),并在(2,0)建立一个口袋锚点,再从(2,0)移动1到达常世之荚(3,0),从(3,0)传送回口袋锚点(2,0),从(2,0)移动1到达渊海矿髓(2,1),所以最短路径为3

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 39ms, 内存消耗: 492K, 提交时间: 2022-08-18 16:46:37

#include<iostream>
#include<cmath>
#include<climits>
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int N=5e3+5;
const ll inf=LLONG_MAX;
PII p[N],q[N];
double dis[N];
bool vis[N];
int n,m;
 
double get_dis(PII a,PII b)
{
    return sqrt((double)(a.x-b.x)*(a.x-b.x)+(double)(a.y-b.y)*(a.y-b.y));
}
 
 
int main()
{
    int a,b,c,d;
    scanf("%d%d%d%d",&a,&b,&c,&d);
    scanf("%d",&m);
    n=a+b+c+d;
    for(int i=1;i<=n;++i)
        scanf("%lld%lld",&p[i].x,&p[i].y);
    for(int i=1;i<=m;++i)
        scanf("%lld%lld",&q[i].x,&q[i].y);
    PII O;
    O.first=0,O.second=0;
    for(int i=1;i<=n;++i)
    {
        dis[i]=get_dis(p[i],O);
        for(int j=1;j<=m;++j)
            dis[i]=min(dis[i],get_dis(p[i],q[j]));
    }
//  for(int i=1;i<=n;++i)
//      printf("%lf ",dis[i]);
//  puts("");
    double res=0;
    for(int t=0;t<n;++t)
    {
        int u=-1;
        for(int i=1;i<=n;++i)
            if(!vis[i]&&(u==-1||dis[u]>dis[i]))
                u=i;
        res+=dis[u];
        vis[u]=1;
        for(int i=1;i<=n;++i)
            dis[i]=min(dis[i],get_dis(p[i],p[u]));
    }
    printf("%lf\n",res);
    return 0;
}

C++ 解法, 执行用时: 44ms, 内存消耗: 484K, 提交时间: 2022-04-01 19:30:02

#include<bits/stdc++.h>
using namespace std;

const int N = 2010;

double dp[N];

int x[N], y[N];
bool vis[N];

double sqr(double x){
  return x * x;
}

int main(){
  int n, m;
  n = m = 0;
  for(int i=0; i<4; ++i){
    scanf("%d", &m);
    n += m;
  }
  scanf("%d", &m);
  for(int i=0; i<n; ++i){
    scanf("%d %d", x+i, y+i);
    dp[i] = sqrt(sqr(x[i]) + sqr(y[i]));
  }
  int a, b;
  for(int i=0; i<m; ++i){
    scanf("%d %d", &a, &b);
    for(int j=0; j<n; ++j){
      dp[j] = min(dp[j], sqrt(sqr(x[j] - a) + sqr(y[j] - b)));
    }
  }

  double ans = 0.0;
  for(int i=0; i<n; ++i){
    int k = -1;
    for(int j=0; j<n; ++j){
      if(!vis[j] && (k == -1 || dp[j] < dp[k])) k = j;
    }
    vis[k] = 1;
    ans += dp[k];
    for(int j=0; j<n; ++j){
      if(!vis[j]) dp[j] = min(dp[j], sqrt(sqr(x[j] - x[k]) + sqr(y[j] - y[k])));
    }
  }
  
  printf("%.8f\n", ans);

  return 0;
}

上一题