蓝桥杯:城邦

news2024/11/16 6:23:18

题目链接

问题描述

答案提交

        本题答案是:4046。

运行限制

思路分析

代码(Java)


问题描述

        小蓝国是一个水上王国, 有 2021 个城邦, 依次编号 1 到 2021。在任意两 个城邦之间, 都有一座桥直接连接。

        为了庆祝小蓝国的传统节日, 小蓝国政府准备将一部分桥装饰起来。

        对于编号为 a 和 b 的两个城邦, 它们之间的桥如果要装饰起来, 需要的费 用如下计算:

        找到 a 和 b 在十进制下所有不同的数位, 将数位上的数字求和。

        例如, 编号为 2021 和 922 两个城邦之间, 千位、百位和个位都不同, 将这些数位上的数字加起来是 (2+0+1)+(0+9+2)=14 。注意 922 没有千位, 千位看成 0 。

        为了节约开支, 小蓝国政府准备只装饰 2020 座桥, 并且要保证从任意一个 城邦到任意另一个城邦之间可以完全只通过装饰的桥到达。

        请问, 小蓝国政府至少要花多少费用才能完成装饰。

        提示: 建议使用计算机编程解决问题。

答案提交

        这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一 个整数, 在提交答案时只填写这个整数, 填写多余的内容将无法得分。

        本题答案是:4046。

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M

思路分析

        首先,他的花费计算是,两个数A,B,如果A和B相对应的位数不同,就相加。

        如:2017和917这两个数的花费是:(2+0)+(0+9),因为个位他们都是7,所以省略了,十位也是同理,然后917没有千位,默认是0。所以2017和917的花费就是(2+0)+(0+9)=11

        然后再看题目,很明显跟图有关,一共有2021个节点,题目要求我们让所有节点都能连通起来,让我们使用2020条边,同时要求花费最少。

        判断是否连通需要用到并查集,然后在确保花费最少可以用贪心的策略,每次选择花费最少的一条边,让两个节点相连。

        条件这么清楚了,很明显的要用到最小生成树了,这道题就是经典板子题。

        如果不了解什么是最小生成树,可以搭配视频理解,我下面简单说一下。

        视频链接:最小生成树(Kruskal(克鲁斯卡尔)和Prim(普里姆))算法动画演示

         首先,需要是一个带权的图,在本题中,两个城堡之间如果需要连接起来,那么需要花费一定费用,将两座城堡之间建立连接。那么,换个思路来,两个城堡是图中的节点,然后他们之间互相连接的边,就是这两座城邦建立连接所需要的花费;而且,我们需要任意一个城堡都能到达另一个城堡,那么,就代表着这些节点之间需要互相连通,这样他们才能互相到达另一边。

        因此可以把题目的城堡当作连通带权无向图来处理。

        题目条件也给出了,一共有2021个城堡,也就是一共有2021个节点。我们需要用2020座桥把他们连接起来,也就是一共有2020条边。并且我们要让花费最小。

        所谓的最小成本了:就是n个顶点,用n-1条边把一个连通图连接起来,并使得权值的和最小。所以,我们把构成连通图的最小代价生成树叫做最小生成树。

        而最小生成树,有两个经典的算法,Kruskal和Prim,这里我们使用Kruskal比较容易理解。

        我们可以将节点x与节点y的花费存起来,用一个类(结构体)来存储节点x,节点y,节点x与y的连通花费。

class Node{
        // x <-> y
        int x;  //节点x
        int y;  //节点y
        int cost;   //连接x和y的花费
        public Node(int x, int y, int cost) {
            this.x = x;
            this.y = y;
            this.cost = cost;
        }
    }

        然后将其存入一个数组之中,之后遍历1-2021,算出所有节点互相之间连通需要的花费,并存入数组之中,后续按照连通花费,进行升序排序,这样保证前面的连通花费是最少的,我们根据Kruskal的思想,从最少连通花费进行连接,把x和y连接起来。

        将1-2021之间所有节点与边的关系添加到数组之后,我们就需要对数组进行排序了,要完成Kruskal算法之中花费从小到大排序,也就是升序,我们就需要对数组进行排序。

        但是我们开的数组肯定是远大于我们实际需要使用到的大小,所以我们需要用一个变量记录使用到哪个位置,然后排序的时候选择从0-变量记录的位置,然后使用升序排序即可(一般默认排序都是升序排序)。之后就是判断连通的问题了。

        既然要判断是否连通,那么就要用到并查集来检查连通了。

        如果对并查集不太懂,可以看:【算法与数据结构】—— 并查集 (写的非常好)。

        这里贴上代码,不展开介绍了。

    int[] pre;
    public void initPre(){
        //并查集找连通
        pre = new int[2022];
        //初始化并查集
        for(int i = 0;i<pre.length;i++){
            pre[i] = i;
        }
    }
    public int find(int x){
        //做一下路径压缩
        if(pre[x] == x) return x;
        return pre[x] = find(pre[x]);
    }
    public void join(int x,int y){
        int fx = find(x);
        int fy = find(y);
        if(fx!=fy)
            pre[fx] = fy;
    }

        如果将x和y连通,将产生环,该如何判断呢?

        我们需要通过并查集找到节点x它的父亲是谁,和y的父亲进行比较,如果他们的父亲相同,代码x已经可以和y同时到达同一个地点,如果我们再让x和y进行连接,那么肯定会产生环。

        如:

         如果我们的x是1,y是3,我们通过并查集的find()可以知道他们的父亲都是4,如果再让他们连通,则肯定会产生环。

        所以我们需要判断x和y的父亲是不是同一个,如果不是,那么就可以使用并查集的join()将他们连接起来,并且将连接他们的花费记录到答案之中,因为这是构造连通的最优解。

        之后根据定义,我们只需要成功连通2020个边(n个节点需要n-1个边),就完成了1-2021之间的连通,他们之间就可以从任意一个节点到另一个节点,并且花费是最小的了。

代码(Java)

        不知道为什么在蓝桥那边提交显示超时,我在本地跑就只用了380±20ms。

import java.util.*;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
    static int[] pre;
    public static int find(int x){
        //做一下路径压缩
        if(pre[x] == x) return x;
        return pre[x] = find(pre[x]);
    }
    public static void join(int x,int y){
        int fx = find(x);
        int fy = find(y);
        if(fx!=fy)
            pre[fx] = fy;
    }

    static class Node{
        // x <-> y
        int x;  //节点x
        int y;  //节点y
        int cost;   //连接x和y的花费
        public Node(int x, int y, int cost) {
            this.x = x;
            this.y = y;
            this.cost = cost;
        }
    }
    public static void main(String[] args) {
        //程序开始时间
        long startTime = System.currentTimeMillis();

        //并查集找连通
        pre = new int[2022];
        //初始化并查集
        for(int i = 0;i<pre.length;i++){
            pre[i] = i;
        }
        //空间换时间
        Node[] minTree = new Node[2021*2021];
        int index = 0;
        //将边的信息存储到数组中
        for(int i = 1;i<2021;i++){
            for(int j = i+1;j<=2021;j++){
                int cost = cost(i,j);
                minTree[index++] = new Node(i,j,cost);
            }
        }
        //按照花费进行升序排序,排序范围是0-index,也就是存储有边信息的部分
        Arrays.sort(minTree,0,index,(n1,n2)->(n1.cost-n2.cost));
        //总花费
        int res = 0;
        //依次取出顶部(前面)的边,判断该x和y添加进去是否会产生环,如果不会就使用这条边;如果会就丢弃这条边
        for(int i = 0;i<index;i++){
            Node node = minTree[i];
            if(find(node.x)!=find(node.y)){
                join(node.x,node.y);
                res += node.cost;
            }
        }

        System.out.println(res);

        //程序结束时间
        long endTime = System.currentTimeMillis();
        System.out.println("程序执行耗时: "+(endTime-startTime)+" ms");
    }

    public static int cost(int x,int y){
        int res = 0;
        while(x>0 || y>0){
            int a = x%10;
            int b = y%10;
            if(a!=b) res += a+b;
            x /= 10;
            y /= 10;
        }
        return res;
    }
}

        程序运行结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/170875.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

登录授权方案:JSON Web Tokens (JWT)

登录授权方案&#xff1a;JSON Web Tokens (JWT) JWT官方文档&#xff1a;https://jwt.io/introduction 1.简介&#xff1a; JWT 即 json web tokens&#xff0c;通过JSON形式作为Web应用中的令牌&#xff0c;用于在各方之间安全地将信息作为JSON对象传输&#xff0c;在数据传…

【博客598】从netfilter hook执行原理分析iptables为什么自定义链无法主动调用只能从其它链跳转过来

从netfilter hook执行原理分析iptables为什么自定义链无法主动调用只能从其它链跳转过来 1、netfilter hook执行原理 netfilter 框架是 Linux 网络子系统里的一个核心模块&#xff0c;iptables 就是基于 netfilter 框架实现的一个网络包处理工具。 netfilter hook被调用后执行…

2023年“科学探索奖”申报启动及指南

2023年“科学探索奖”资助不超过50位青年科学家&#xff0c;每位获奖人5年内将获得总计300万元奖金。今年的申报时间为2023年1月1日至3月15日。获奖名单拟定于2023年8月揭晓。本文知识人网小编整理该奖项的概要及申报指南&#xff0c;以飨读者。“科学探索奖”是一项由科学家主…

【高并发内存池】第二弹之threadcache 线程缓存

1.为什么线程向threadcache申请内存不需要加锁&#xff1f; 因为没有把cache设置成全局变量&#xff0c;而是使用了TLS(线程局部存储)&#xff0c;作用是当前内存只可当前线程见到&#xff0c;其他线程没有使用权&#xff0c;避免了加锁的操作&#xff0c;保证了线程数据的独立…

基于paddlex图像分类模型训练(一):图像分类数据集切分:文件夹转化为imagenet训练格式

背景 在使用paddlex GUI训练图像分类时&#xff0c;内部自动对导入的分类文件夹进行细分&#xff0c;本文主要介绍其图像分类数据切分源码&#xff0c;或可作为其他项目储备代码&#xff1a;https://github.com/PaddlePaddle/PaddleX/blob/develop/paddlex/tools/dataset_spli…

[Linux]进程概念以及进程状态

&#x1f941;作者&#xff1a; 华丞臧. &#x1f4d5;​​​​专栏&#xff1a;【LINUX】 各位读者老爷如果觉得博主写的不错&#xff0c;请诸位多多支持(点赞收藏关注)。如果有错误的地方&#xff0c;欢迎在评论区指出。 推荐一款刷题网站 &#x1f449; LeetCode刷题网站 文…

vs2019 + qt5.12.11 打包

目录 你以为打包方式 实际要添加步骤 你以为打包方式 先吐槽一番&#xff0c;感觉vsqt打包有点巨坑&#xff0c;还是说我第一次打包其实都是这样子的 首先我们将生成的.exe弄到一个打包文件夹里面 然后嘞 我用qt自带的打包工具windeployqt exe &#xff08;因为我的再C盘下…

Mysql基础篇(11)—— MySQL8.0新特性之窗口函数

举例1 假设我现在有这样一个数据表&#xff0c;它显示了某购物网站在每个城市每个区的销售额&#xff1a; CREATE TABLE sales( id INT PRIMARY KEY AUTO_INCREMENT, city VARCHAR(15), county VARCHAR(15), sales_value DECIMAL ); INSERT INTO sales(city,county,sales_val…

【xgboost】XGBoost

XGBoost1. 原理改进及特点1.1 遵循Boosting算法的基本建模流程1.2 平衡精确性与复杂度1.3 降低模型复杂度、提升运行效率1.4 保留部份GBDT属性2. sklearn接口(回归)2.1 导库 & 数据2.2 sklearn api普通训练2.3 sklearn api交叉验证2.4 查看属性接口3. xgboost原生代码(回归…

Redis数据持久化方案

作为集中式缓存的优秀代表&#xff0c;Redis可以帮助我们在项目中完成很多特定的功能。Redis准确的说是一个非关系型数据库&#xff0c;但是由于其超高的并发处理性能&#xff0c;及其对于缓存场景所提供的一系列能力构建&#xff0c;使其成为了分布式系统中的集中缓存的绝佳选…

深入学习Vue.js(十)异步组件和函数式组件

文章目录异步组件需要解决的问题异步组件实现原理1.封装defineAsyncComponent函数2.超时与error3.延迟和Loading组件函数式组件异步组件需要解决的问题 允许用户指定加载出错时要渲染的组件允许用户指定Loading组件&#xff0c;以及展示该组件的延迟时间允许用户设置加载组件的…

8. R语言绘图系统介绍、高级绘图与低级绘图、【绘图参数】、绘图函数包

b站课程视频链接&#xff1a; https://www.bilibili.com/video/BV19x411X7C6?p1 腾讯课堂(最新&#xff0c;但是要花钱&#xff0c;我花99&#x1f622;&#x1f622;元买了&#xff0c;感觉讲的没问题&#xff0c;就是知识点结构有点乱&#xff0c;有点废话&#xff09;&…

筑基一层 —— 高质量C编程建议、详解猜数字游戏

目录 一.修炼必备 二.高质量C编程 2.1 高质量C编程的思维导图&#xff08;需要思维导图的加qq:972606225获取) 2.2 文件结构 2.3 程序的形式 2.4 命名规则 三.猜数字游戏详解 一.修炼必备 1.入门必备&#xff1a;VS2019社区版&#xff0c;下载地址&#xff1a;Visual S…

torch_geometric -- Pooling Layers

torch_geometric – Pooling Layers global_add_pool 通过在节点维度上添加节点特征来返回批量图级输出&#xff0c;因此对于单个图 它的输出由下式计算 from torch_geometric.nn import global_mean_pool, global_max_pool, global_add_pool import torch as thf [[1,2,3,4…

Wider Face+YOLOV8人脸检测

YOLO系列的算法更新实在太快了&#xff0c;前些天刚学习完YOLOV7&#xff0c;YOLOV8就出来了。今天先理解模型的训练过程&#xff0c;后续再学习V8的网络结构等细节。YOLOV8源码链接&#xff1a;https://github.com/ultralytics/ultralytics1 数据格式转换Wider Face数据格式转…

java -- 14 多态、内部类、常用API

自动类型转换&#xff1a;多态下引用数据类型的类型转换强制类型转换案例&#xff1a;定义usb接口&#xff1a;定义鼠标和键盘的usb实现类&#xff0c;并有自己特有的方法&#xff0c;重写usb接口的方法&#xff0c;里面穿插了多态创建电脑类&#xff0c;把usb接口揉和进去&…

如何改变视频的MD5值?一分钟让你学会操作

肯定很多不是从事自媒体的朋友对MD5不是很熟悉&#xff0c;但其实它类似于人的身份证&#xff0c;只不过我们的身份证是一串数字&#xff0c;而它则是视频的后台编码&#xff0c;所以这也是一些平台用MD5来判断视频是否重复的依据。那么有人会问了&#xff0c;既然MD5这么特殊&…

Java实战:使用Hutool中的MailUtil实现邮件的发送

❤️作者主页&#xff1a;IT技术分享社区 ❤️作者简介&#xff1a;大家好,我是IT技术分享社区的博主&#xff0c;从事C#、Java开发九年&#xff0c;对数据库、C#、Java、前端、运维、电脑技巧等经验丰富。 ❤️荣誉&#xff1a; CSDN博客专家、数据库优质创作者&#x1f3c6;&…

EasyExcel的导入导出使用

1、说明 EasyExcel是阿里出的一款基于Java的、快速、简洁、解决大文件内存溢出的处理Excel的开源工具&#xff0c;本文主要是使用这个工具对Excel导入导出进行讲解。 官网&#xff1a; https://easyexcel.opensource.alibaba.com/github&#xff1a; https://github.com/alib…

达梦主备之备库失联后在线恢复加入集群

一、主库故障重启&#xff08;备库接管前重启&#xff09; 主库故障后立即重启&#xff0c;此时主库的守护进程变成 Startup 状态&#xff0c;重新进入守护进程的 启动流程&#xff0c;将数据一致的备库归档设置为有效状态&#xff0c;其余备库归档设置成无效状态&#xff0c;并…