首页 > 其他分享 >[蓝桥杯 2020 国 C] 补给

[蓝桥杯 2020 国 C] 补给

时间:2024-12-16 11:45:27浏览次数:3  
标签:每个 ll 距离 蓝桥 小蓝 补给 村庄 2020 dp

题目

Description

小蓝是一个直升飞机驾驶员,他负责给山区的 nn 个村庄运送物资。

每个月,他都要到每个村庄至少一次,可以多于一次,将村庄需要的物资运送过去。

每个村庄都正好有一个直升机场,每两个村庄之间的路程都正好是村庄之间的直线距离。

由于直升机的油箱大小有限,小蓝单次飞行的距离不能超过 DD。每个直升机场都有加油站,可以给直升机加满油。

每个月,小蓝都是从总部出发,给各个村庄运送完物资后回到总部。如果方便,小蓝中途也可以经过总部来加油。

总部位于编号为 11 的村庄。

请问,要完成一个月的任务,小蓝至少要飞行多长距离?

Input

输入的第一行包含两个整数 nn,DD,分别表示村庄的数量和单次飞行的距离。

接下来 nn 行描述村庄的位置,其中第 ii 行两个整数 xixi​,yiyi​ 分别表示编号为 ii 的村庄的坐标。村庄 ii 和村庄 jj 之间的距离为 欧几里得距离。

Output

输出一行,包含一个实数,四舍五入保留正好 22 位小数,表示答案。

Sample Input

4 6
1 1
4 5
8 5
11 1

Sample Output

28.00

思路

这是一道状压$dp$的经典题

但不同的是每个村庄可以经过多次;

我们首先考虑什么情况下需要多次经过;

很明显如果两点距离大于$D$时,无法直接到达,就需要通过其他点去到达目标点,而在这个过程中其他点可能已经被经过了;

对于多次经过的点,记录状态十分困难;

所以,我们可以提前用最短路预处理每个点到其他点的最短距离;

这样记录状态时就可以忽略中间重复经过的点而直接记录包含目标点的状态集合;

那么状态转移方程很显然就是:

$dp[i][k]=min(dp[i][k],dp[j][k \oplus (1<<(i-1))]+a[j][i]);$

$k$ 是枚举的到达过的点的集合,$i$ 和 $j$ 都是枚举当前到达的点;

 


 

代码

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll _=21;
ll n;
double m;
double b[_],c[_];
double a[_][_],dp[_][1<<20];
int main()
{
    memset(dp,127,sizeof(dp));
    scanf("%lld%lf",&n,&m);
    for(ll i=1;i<=n;i++)
        scanf("%lf%lf",&b[i],&c[i]);
    for(ll i=1;i<=n;i++)
    for(ll j=1;j<=n;j++)
    {
        double num=sqrt(pow(b[i]-b[j],2)+pow(c[i]-c[j],2));
        if(num<=m)
            a[i][j]=num;
        else
            a[i][j]=INT_MAX;
    }
    for(ll k=1;k<=n;k++)
    for(ll i=1;i<=n;i++)
    for(ll j=1;j<=n;j++)//最短路预处理
    if(a[i][j]>a[i][k]+a[k][j])
        a[i][j]=a[i][k]+a[k][j];
    dp[1][1]=0;//从第一个村庄出发
    for(ll k=1;k<=(1<<n)-1;k+=2)//k每次加二保证k集合永远包含第一个村庄
    for(ll i=1;i<=n;i++)
    for(ll j=1;j<=n;j++)
    if(k&(1<<(i-1))&&k&(1<<(j-1)))
    {
        dp[i][k]=min(dp[i][k],dp[j][k^(1<<(i-1))]+a[j][i]);//转移
    }
    double ans=INT_MAX;
    for(ll i=2;i<=n;i++)
        ans=min(ans,dp[i][(1<<n)-1]+a[i][1]);
    printf("%.2lf",ans);
    return 0;
}

 

 

 

 

 

 

 

标签:每个,ll,距离,蓝桥,小蓝,补给,村庄,2020,dp
From: https://www.cnblogs.com/wzx-RS-STHN/p/18609657

相关文章

  • [蓝桥杯 2019 省 A] 糖果
    题目Description糖果店的老板一共有 MM 种口味的糖果出售。为了方便描述,我们将 MM 种口味编号 11 ∼ MM。小明希望能品尝到所有口味的糖果。遗憾的是老板并不单独出售糖果,而是 KK 颗一包整包出售。幸好糖果包装上注明了其中 KK 颗糖果的口味,所以小明可以在买之前......
  • 2024年蓝桥杯Java B组省赛真题超详解析(全)
    目录前言第一题『报数游戏』问题描述:解题思路AC代码:第二题『类斐波那契循环数』问题描述解题思路AC代码第三题『分布式队列』问题描述解题思路AC代码第四题『食堂』问题描述评测用例规模与约定解题思路贪心的核心优先级:具体贪心策略步骤AC代码:第五题『最优分组......
  • 蓝桥杯数列求值(2019试题C)
    【问题描述】     给定数列1,1,1,3,5,7,17……从第4项开始,每项都是前3项的和。求第20190324项的最后4位数字。【答案提交】    这是一道结果填空题,考生只需要计算出结果并提交即可。本题的结果为一个4位整数(提示:答案的千位不为0),在提交答案时只填写这个......
  • 题解:P11319 [NOISG2020 Qualification] Cryptography
    康托展开模版给大家一个式子,这个式子就是康托展开的模版。\(rank=1+\sum_{i=1}^{n}a_n\times(n-i)!\)然后我们对这个排列\(P\)进行离散化,最后直接来个康托展开的模版就行了。代码#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>usi......
  • 蓝桥 小白入门赛24
    https://www.lanqiao.cn/oj-contest/newbie-24/1. 分配辣条签到题。#include<iostream>usingnamespacestd;intmain(){cout<<20250601/305*305;return0;}ViewCode2. 决出国特题意为求出最小的不能被前n个质数整除的数。根据埃氏筛的思想,前n个质数会将第......
  • [CSP2020-J4] 直播获奖
    题面题目描述NOI2130即将举行。为了增加观赏性,CCF决定逐一评出每个选手的成绩,并直播即时的获奖分数线。本次竞赛的获奖率为$w%$,即当前排名前$w%$的选手的最低成绩就是即时的分数线。更具体地,若当前已评出了$p$个选手的成绩,则当前计划获奖人数为$\max(1,\lfloorp\tim......
  • 大一新生的蓝桥杯备考指南
    大一是打基础的黄金时期,选择在明年4月参加蓝桥杯正当其时。让我们从基础知识、学习规划和备考策略三个维度,详细谈谈如何准备这场含金量颇高的程序设计大赛。你已经学完CPrimerPlus前九章,这是个不错的起点。接下来的章节包含了指针、动态内存分配、文件操作等重要知识点。这......
  • 2020年蓝桥杯省赛:JAVA
    代码:importjava.util.Scanner;publicclassT14{  publicstaticvoidmain(String[]args){    //创建一个Scanner对象用于从控制台读取输入    Scannerscanner=newScanner(System.in);         //读取输入字符串并将其......
  • 蓝桥云课 | 求和
    问题描述给定nnn个整数a1,......
  • 蓝桥云课 | 图书管理员
    题目描述图书馆中每本书都有一个图书编码,可以用于快速检索图书,这个图书编码是一个正整数。每位借书的读者手中有一个需求码,这个需求码也是一个正整数。如果一本书的图书编码恰好以读者的需求码结尾,那么这本书就是这位读者所需要的。小D刚刚当上图书馆的管理员,她知道图......