【蓝桥杯】每日练习 Day15

目录

前言

奶牛选美

分析

代码

大臣的旅费

分析

代码

飞机降落

分析

代码

母亲的牛奶

分析

代码

扫雷

分析

代码


前言

虽为诞辰,但也不忘完成每日的训练。

今天给大家带来五道dfs的题目,包括组合数,连通块,数的直径等方面的内容。

因为时间较为仓促,很多地方可能讲的不是很全面,请见谅。


奶牛选美

分析

题目保证图中存在且仅存在两个连通块,说实话这道题挺水的,不知道为什么难度是中等。

第一步,dfsbfs找出两个连通块。

随后的问题就是求两个连通块的最小曼哈顿距离,枚举两个连通块中的点,随后取最小值即可(这题题目的结果要减一)。

abs(x1 - x2) + abs(y1 - y2)

最后我们来分析一下时间复杂度,dfs或bfs的时间复杂度都是O(n ^ 2),求曼哈顿距离的时间复杂度是O(x * (n - x))x表示第一个连通块中的连通块数量),可以发现这是一个基本不等式,最大值为(n ^ 2) / 4,所以总的时间复杂度就是O(n ^ 2)。通过本题绰绰有余。


代码

// dfs连通块
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#define s second
#define f first
using namespace std;
typedef pair<int, int> PII;
const int N = 55;
int n, m;
char map[N][N];
bool read[N][N];
vector<PII> v[3];
int cnt;
int l = 0x3f3f3f3f;
PII s[] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};void dfs(int x, int y, vector<PII>& v)
{read[x][y] = true;v.push_back({x, y});for(int i = 0; i < 4; i++)if(map[x + s[i].f][y + s[i].s] == 'X' && !read[x + s[i].f][y + s[i].s])dfs(x + s[i].f, y + s[i].s, v);
}int main()
{scanf("%d%d", &n, &m);for(int i = 1; i <= n; i++)scanf("%s", map[i] + 1);for(int i = 1; i <= n; i++)for(int j = 1; j <= m; j++)if(map[i][j] == 'X' && !read[i][j])dfs(i, j, v[cnt++]);for(PII a : v[0])for(PII b : v[1]){//printf("111");l = min(l, abs(a.s - b.s) + abs(a.f - b.f));}printf("%d", l - 1);return 0;
}

大臣的旅费


分析

从题目的描述中可以知道题目给的是一颗树。所以我们每次读取的边的数量就是n - 1(这个好像不用我说题目也说了)。而根据题目描述的所花路费只与总路程有关,路费是一个等差数列,所以对于这道题我们只需要求出路中的最长路径随后用n项和公式计算即可。

那么怎样求树中的最长路径呢?树的最长路径,其实就是树的直径

树的直径问题解法一边是使用两次dfs,一次找到离根节点(对于双向的树来说这个根可以是树中的任何点)最远的点,随后再用一次dfs遍历出的最长路径就是树的直径。

如何证明呢?

我们先来思考一下从一个点遍历一遍这棵树又回到起点的路径是多长,显而易见,这个路径长是边长和的二倍,在这条路中每条边是都被走了两遍的。

我们若想找到树中的直径显然是不能重复经过一条边的,所以直径要小于边长和的两倍

我们再思考,直径的理想情况是遍历树中的每一条边,这种情况是有可能的(一条直线),所以树的直径要小于等于树的边长和

铺垫完了这些我们就可以将求树的直径转化成树的边长和减去不经过的边长的长度,也就是:

d = l - x

d表示直径,l表示树边长之和,x表示未经过的边长,那么问题就转化成了求x的最小值

那么如何来求这个最小值呢?为方便理解,主包画了一个草图。

可以明显的看出直径就是最长的那一条(这是废话)。

我们按照我们的算法思路先以A为根节点找到D随后再一遍dfs找到C,那么从DC就是树的直径

为何这样是正确的呢?其实不难想,因为我们前面的分析,我们要求直径其实就是求避开的边长的最小值。

而我们在遍历树的过程中每次只记录距离最长的一条边(类似于dp),自然而然的就避开了所有短的边。

又根据树的性质两点之间的路径是唯一的,并且树中不存在环。所以就不存在图中那些弯弯绕,每次丢弃权重最小的一部分即可。

时间复杂度不必多说,两次都是O(n)


代码

/*树中的最长路,树的直径问题。先求长度,然后公式求解
*/
#include<iostream>
#include<vector>
#include<cstring>
#define s second
#define f first
using namespace std;
typedef pair<int, int> PII;
typedef long long LL;
const int N = 100010;
int n;
vector<int> tree[N];
vector<int> w[N];
bool read[N];
PII dfs(int v)
{PII l = {0, v};read[v] = true;for(int i = 0; i < tree[v].size(); i++){int z = tree[v][i];if(!read[z]){PII m = dfs(z);if(m.f + w[v][i] > l.f)l = {m.f + w[v][i], m.s};}}return l; //最长距离
}int main()
{scanf("%d", &n);for(int i = 1; i < n; i++){int x, y, z;scanf("%d%d%d", &x, &y, &z);tree[x].push_back(y);w[x].push_back(z);tree[y].push_back(x);w[y].push_back(z); }int i = dfs(1).s;memset(read, false, sizeof read);i = dfs(i).f;//printf("%d", i);printf("%lld", ((LL)i * (11 + 10 + i))/2);return 0;
}

飞机降落


分析

第一眼感觉是贪心,但是看到数据量之后发现不是贪心,数据量很小所以我们考虑搜索状态压缩dp

初步分析,总共有n太飞机,每台飞机都要在固定的区间内降落。

发现n很小,我们可以考虑组合数,而组合数的时间复杂度是n * n!这道题就是36288000,三千六百万,再乘上t就是3.6亿,时间限制是两秒钟。

虽然组合数的常数很小可能通过但是也有TLE的风险,考虑优化。

优化不必多说,搜索的常见优化就是打表和剪枝,对于组合数问题打表显然不行,所以我们考虑剪枝

我们枚举组合数就是枚举每台飞机降落的顺序,显然后面的飞机不可能在前面的飞机降落前完成降落,所以剪枝的判断条件就是后面的飞机能否在前面的飞机完成降落后降落

还有一步贪心就是如果这台飞机可以降落,我们该选择哪个时间使其降落。很好想尽量让开始降落的时间靠前(和线性dp很像)因为降落时间早的状态是包含降落时间晚的所有状态的。

剪枝后运行时间是38ms,说明我们的代码效率还是很高的。(实际剪枝后的时间复杂度是接近O(n ^ 2)的)


代码

/*全排列降落顺序即可
*/
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
const int N = 15;
int t, n;
int l[N], r[N], d[N];
vector<int> vtr;
bool read[N];bool dfs(int t) 
{if(vtr.size() == n)return true;for(int i = 1; i <= n; i++){if(!read[i]){if(l[i] + r[i] >= t) //可以放下{read[i] = true;vtr.push_back(i);if(dfs(max(t, l[i]) + d[i])) return true;read[i] = false;vtr.pop_back();}}}return false;
}
int main()
{scanf("%d", &t);while(t--){memset(read, false, sizeof read);vtr.clear();scanf("%d", &n);for(int i = 1; i <= n; i++)scanf("%d%d%d", l + i, r + i, d + i);if(dfs(0))puts("YES");elseputs("NO");}}

母亲的牛奶


分析

不得不吐槽一下这个名字好怪……

看完题目后发现数据量很小,分析一下能不能直接用搜索

初步分析的话是可以的,但是我们发现一个问题,那就是不知道搜索什么时候结束。

这个简单,因为每次倒牛奶都不会有损失也不会有增加,所以根据某某定理(主包忘了),在之后某一个时间点的状态一定会和当前状态完全相同。

也就是一个循环,所以我们只需要存储一下每次遍历到的状态,当发现重复遍历时退出即可。

分析一下时间复杂度,我们分析极限情况

每个桶的大小是小于等于20的,也就是每个桶有21种状态。所以总的状态量就是21 * 21 * 21,大概是一万,通过本题绰绰有余。


代码

#include<iostream>
using namespace std;
const int N = 22;
bool read[N][N][N]; //dfs遇到重复状态时就退出
bool C[N]; 
int a, b, c;
void dfs(int x, int y, int z)
{if(read[x][y][z]) return;read[x][y][z] = true;if(!x)  C[z] = true;//printf("%d %d %d", x, y, z);if(x != 0){dfs(max(0, x - (b - y)), min(b, y + x), z);dfs(max(0, x - (c - z)), y, min(c, z + x));}if(y != 0){dfs(min(a, x + y), max(0, y - (a - x)), z);dfs(x, max(0, y - (c - z)), min(c, z + y));}if(z != 0){dfs(min(a, x + z), y, max(0, z - (a - x)));dfs(x, min(b, y + z), max(0, z - (b - y)));}}int main()
{scanf("%d%d%d", &a, &b, &c);dfs(0, 0, c);for(int i = 0; i < 21; i++)if(C[i])printf("%d ", i);return 0;
}

扫雷


分析

今天的最后一道题(因为主包以前做过千奇百怪的扫雷游戏所以这种题感觉闭着眼睛都能写),不得不感慨,刷那么多题没记住几个,写着玩的东西倒是记忆犹新。

数据量是100 * 300 * 300,大概是1e7,所以我们需要将时间复杂度控制在线性

怎么写呢?我们先根据每个雷的位置处理出每个点应该有的数字,随后我们可以将0看为连通块,随后我们发现我们在点击非零块的时候一次只能解开一个,而在点击0时每次可以解开多个块(包括部分非0块)。

所以我们的思路是先解开0的连通块,随后再统计没有解开的非零块的数量即可。


代码

/*先找全0的连通块
*/
#include<iostream>
#include<cstring>
#define s second
#define f first
using namespace std;
typedef pair<int, int> PII;
const int N = 310;
int t, n;
char map[N][N];
bool read[N][N];
int st[N][N];
PII s[] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}, {-1, -1}, {1, 1}, {-1, 1}, {1, -1}};void init()
{for(int i = 1; i <= n; i++)for(int j = 1; j <= n; j++)if(map[i][j] == '*')for(int k = 0; k < 8; k++)st[i + s[k].f][j + s[k].s]++; //统计数字
}void dfs(int x, int y)
{read[x][y] = true;if(st[x][y] == 0 && map[x][y] == '.'){for(int i = 0; i < 8; i++)if(!read[x + s[i].f][y + s[i].s]){read[x + s[i].f][y + s[i].s] = true;dfs(x + s[i].f, y + s[i].s); //dfs求连通块}}
}int main()
{scanf("%d", &t);for(int i = 1; i <= t; i++){memset(read, 0, sizeof read);memset(st, 0, sizeof st);scanf("%d", &n);for(int i = 1; i <= n; i++)scanf("%s", &map[i][1]);init();/*for(int i = 1; i <= n;puts(""), i++)for(int j = 1; j <= n; j++)printf("%d ", st[i][j]);*/int l = 0;for(int i = 1; i <= n; i++)for(int j = 1; j <= n; j++)if(map[i][j] == '.' && !read[i][j] && st[i][j] == 0){//printf("%d %d\n", i, j);dfs(i, j);l++;}//printf("%d\n", l); for(int i = 1; i <= n; i++)for(int j = 1; j <= n; j++)if(map[i][j] == '.' && !read[i][j])l++;printf("Case #%d: %d\n", i, l);}return 0;
}

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

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

相关文章

ipconfig、ping、ipconfig/all 4个常用 **Windows终端(CMD)命令** 的详细解释

ipconfig、ping、ipconfig/all 4个常用 Windows终端&#xff08;CMD&#xff09;命令 的详细解释、用途分析和使用示例 1. ipconfig 作用 快速查看本地网络连接的 IP地址、子网掩码、默认网关 等基础信息。 示例输出 Windows IP 配置无线局域网适配器 WLAN:IPv4 地址 . . .…

@emotion/css + react+动态主题切换

1.下载插件 npm install --save emotion/css 2.创建ThemeContext.tsx // src/ThemeContext.tsx import React, { createContext, useContext, useState } from "react";// 定义主题类型 export type Theme "light" | "dark";// 定义主题上下…

【信奥一本通提高篇】基础算法之贪心算法

原文 https://bbs.fmcraft.top/blog/index.php/archives/22/ 贪心算法 概述 近年来的信息学竞赛试题&#xff0c;经常出现求一个问题的可行解或最优解的题目。这类问题就是我们通常所说的最优化问题。贪心算法是求解这类问题的一种常用算法。在众多的算法中&#xff0c;贪心…

CentOS-7.0系统基础操作

配置ip地址 编辑网卡文件&#xff1a; vi etc/sysconfig/network-scripts/ifcfg-ens33 在网卡文件里参照如下设置&#xff1a; BOOTPROTO"static" IPADDR192.168.61.233 GATEWAY192.168.61.2 NETMASK255.255.255.0 ONBOOT"yes" 防火墙管理 开启防火墙&am…

【大模型应用】信息抽取的调研

老规矩&#xff0c;先占坑&#xff0c;后续更新。 关键词&#xff1a; Pydantic functioncal 参考文献&#xff1a;小白学大模型&#xff1a;自定义信息抽取Agent-CSDN博客

MySQL内存使用率高问题排查与解决方案:

目录标题 **一、问题现象****二、核心排查步骤****1. 参数检查****2. 内存使用分析****3. 存储过程/函数/视图检查****4. 操作系统级检查** **三、解决方案****1. 调整MySQL配置****2. 关闭透明大页&#xff08;THP&#xff09;****3. 优化查询与存储过程****4. 硬件与环境优化…

华为GaussDB数据库的手动备份与还原操作介绍

数据库的备份以A机上的操作为例。 1、使用linux的root用户登录到GaussDB服务器。 2、用以下命令切换到 GaussDB 管理员用户&#xff0c;其中&#xff0c;omm 为当前数据库的linux账号。 su - omm 3、执行gs_dump命令进行数据库备份&#xff1a; 这里使用gs_dump命令进行备…

How to install OpenJ9 JDK 17 on Ubuntu 24.04

概述 OpenJ9 是一款由 IBM 开发并开源的 Java 虚拟机&#xff08;JVM&#xff09;&#xff0c;现由 ​Eclipse 基金会管理&#xff08;名为 ​Eclipse OpenJ9&#xff09;。它旨在提供高性能、低内存消耗和快速启动时间&#xff0c;特别适用于云原生和容器化环境。 关键特性 …

洛谷题单1-P5705 【深基2.例7】数字反转-python-流程图重构

题目描述 输入一个不小于 100 100 100 且小于 1000 1000 1000&#xff0c;同时包括小数点后一位的一个浮点数&#xff0c;例如 123.4 123.4 123.4 &#xff0c;要求把这个数字翻转过来&#xff0c;变成 4.321 4.321 4.321 并输出。 输入格式 一行一个浮点数 输出格式 …

【云服务器】在Linux CentOS 7上快速搭建我的世界 Minecraft 服务器搭建,并实现远程联机,详细教程

【云服务器】在Linux CentOS 7上快速搭建我的世界 Minecraft 服务器搭建&#xff0c;详细详细教程 一、 服务器介绍二、下载 Minecraft 服务端三、安装 JDK 21四、搭建服务器五、本地测试连接六、添加服务&#xff0c;并设置开机自启动 前言&#xff1a; 推荐使用云服务器部署&…

内网穿透_ZeroTiers部署_广和通SC171_aidlux_嵌入式

下载 sudo curl -s https://install.zerotier.com | sudo bash &#xff08;需要科学上网&#xff09; 所有涉及硬件的操作好像都需要 root 权限&#xff0c;curl 在这里需要连接网络&#xff0c;所以也需要 sudo sudo zerotier-cli status 若返回 200 info 及设备 ID&#xff…

Faster RCNN Pytorch 实现 代码级 详解

基本结构&#xff1a; 采用VGG提取特征的Faster RCNN. self.backbone:提取出特征图->features self.rpn:选出推荐框->proposals self.roi heads:根据proposals在features上进行抠图->detections features self.backbone(images.tensors)proposals, proposal_losses…

【Matlab】-- 基于MATLAB的美赛常用多种算法

文章目录 文章目录 01 内容概要02 各种算法基本原理03 部分代码04 代码下载 01 内容概要 本资料集合了多种数学建模和优化算法的常用代码资源&#xff0c;旨在为参与美国大学生数学建模竞赛&#xff08;MCM/ICM&#xff0c;简称美赛&#xff09;的参赛者提供实用的编程工具和…

Vue2和Vue3响应式的基本实现

目录 简介Vue2 响应式Vue2 响应式的局限性 Vue3 响应式Vue3 响应式的优点 Vue2 和 Vue3 响应式对比 简介 在 Vue 框架中&#xff0c;数据的响应式是其核心特性之一。当页面数据发生变化时&#xff0c;我们希望界面能自动更新&#xff0c;而不是手动操作 DOM。这就需要对数据进…

Linux系统中快速安装docker

1 查看是否安装docker 要检查Ubuntu是否安装了Docker&#xff0c;可以使用以下几种方法&#xff1a; 方法1&#xff1a;使用 docker --version 命令 docker --version如果Docker已安装&#xff0c;输出会显示Docker的版本信息&#xff0c;例如&#xff1a; Docker version …

ElasticSearch 分词器

文章目录 一、安装中文分词插件Linux安装7.14.1版本&#xff1a;测试1&#xff1a;ik_smart测试2&#xff1a;ik_max_word 二、es内置的分词器&#xff1a;三、拼音插件安装以及&#xff08;IKpinyin使用&#xff09;配置 IK pinyin 分词配置 一、安装中文分词插件 IK Analys…

arm64位FFmpeg与X264库

参考链接&#xff1a; https://blog.csdn.net/gitblog_09700/article/details/142945092

机器学习与深度学习4:数据集处理Dataset,DataLoader,batch_size

深度学习中&#xff0c;我们能看到别人的代码中都有一个继承Dataset类的数据集处理过程&#xff0c;这也是深度学习处理数据集的的基础&#xff0c;下面介绍这个数据集的定义和使用&#xff1a; 1、数据集加载 1.1 通用的定义 Bach&#xff1a;表示每次喂给模型的数据 Epoc…

MySQL数据库和表的操作之SQL语句

&#x1f3af; 本文专栏&#xff1a;MySQL深入浅出 &#x1f680; 作者主页&#xff1a;小度爱学习 MySQL数据库和表的操作 关系型数据库&#xff0c;都是遵循SQL语法进行数据查询和管理的。 SQL语句 什么是sql SQL&#xff1a;结构化查询语言(Structured Query Language)&…

ubuntu开发mcu环境

# 编辑 vim或者vscode # 编译 arm-none-eabi # 烧写 openocd 若是默认安装&#xff0c;会在/usr/share/openocd/scripts/{interface,target} 有配置接口和目标版配置 示例&#xff1a; openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg 启动后&#xff0c;会…