[解题报告] CSDN竞赛第23期
Posted AlgoComp
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[解题报告] CSDN竞赛第23期相关的知识,希望对你有一定的参考价值。
CSDN编程竞赛报名地址:https://edu.csdn.net/contest/detail/37
1. 排查网络故障
题目
A地跟B地的网络中间有n个节点(不包括A地和B地),相邻的两个节点是通过网线连接。正常的情况下,A地和B地是可以连通的,有一天,A地和B地突然不连通了,已知只有一段网线出问题(两个相邻的节点)小明需要排查哪段网线出问题。他的排查步骤是:
1。 选择某个中间节点
2。 在这个节点上判断跟A地B地是否连通,用来判断那一边出问题
请问小明最少要排查多少次,才能保证一定可以找到故障网线
输入描述:
一个正整数 n (n <= 10^18),表示A地和B地之间的节点数
输出描述:
输出一个数字,代表保证一定可以找到故障网线的前提下,小明最少要排查多少次
输入样例:
2
输出样例:
2
解题报告
模拟,答案为 ⌈ l o g 2 ( n + 1 ) ⌉ \\lceil log_2(n + 1) \\rceil ⌈log2(n+1)⌉
class Solution:
def __init__(self) -> None:
pass
def solution(self, n):
if n < 2:
return n
import math
n += 1
result = int(math.log(n))
while 2**result < n:
result += 1
return result
if __name__ == "__main__":
n = int(input().strip())
sol = Solution()
result = sol.solution(n)
print(result)
2. 零钱兑换
题目
给定数组arr,arr中所有的值都为正整数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个aim,代表要找的钱数,求组成aim的最少货币张数。 如果无解,请返回-1. 数据范围:数组大小满足 0 <= n <=10000 , 数组中每个数字都满足 0 < val <=10000,0 <= aim <=100000 要求:时间复杂度 O(n×aim) ,空间复杂度 O(aim)。
输入描述:
输入包括两行,第一行两个整数n(0<=n<=1000)代表数组长度和aim(0<=aim<=5000),
第二行n个不重复的正整数,代表arr(1 <= arri <=10^9)
输出描述:
输出一个整数,表示组成aim的最小货币数,无解时输出-1.
输入样例:
[5,2,3],20
输出样例:
4
解题报告
动态规划,设 f[i] 为组成 i 的最少货币数,初始时 f[i] = oo,则 f[i] = minf[i - j] + 1, 其中 j 遍历 arr 中每个值
若 f[aim] > oo 则答案为 -1 否则为 f[aim]
class Solution:
def __init__(self) -> None:
pass
def solution(self, str1):
arr, aim = eval(str1)
f = [aim + 1] * (aim + 1)
f[0] = 0
for i in range(1, aim + 1):
for j in arr:
if j <= i:
f[i] = min(f[i], f[i - j] + 1)
if f[aim] > aim:
return -1
return f[aim]
if __name__ == "__main__":
str1 = input().strip()
sol = Solution()
result = sol.solution(str1)
print(result)
3. 清理磁盘空间
题目
小明电脑空间满了,决定清空间。为了简化问题,小明列了他个人文件夹(/data)中所有末级文件路径和大小,挑选出总大小为 m 的删除方案,求所有删除方案中,删除操作次数最小是多少。
一次删除操作:删除文件或者删除文件夹。如果删除文件夹,那么该文件夹包含的文件都将被删除。
文件夹的大小:文件夹中所有末级文件大小之和
输入描述:
第一行输入 n (n <= 1000)和 m(m <= 1000),表示文件数量,和需要删除的大小
接下去有 n 行,每一行都是一个文件绝对路径(路径长度小于 100),和这个文件的大小(小于 1000)
输出描述:
输出所有删除方案中,删除操作次数最小是多少。如果找不到恰好删除的大小为 m 的方案,则打印 -1
输入样例:
6 10
/data/movie/a.mp4 5
/data/movie/b.mp4 3
/data/movie/c.mp4 2
/data/movie/d.mp4 4
/data/picture/a.jpg 4
/data/picture/b.jpg 1
输出样例:
2
解题报告
动态规划,把所有文件排序,设第 i 个文件名和大小分别为 x, y
设 f[i][j] 为删除前 i 个文件,总大小为 j 时的最少操作数,初始时 f[i][j] = oo,f[0][0] = 0
则 f[i][j] = minf[i - 1][j], f[i - 1][j - y] + 1,其中 1 <= j <= m
维护上一次的文件夹名称及编号 k 和文件夹总大小 yy,当 x 的文件夹名称与上一次不同时,则 f[i][j] = minf[i - 1][j], f[i - 1][j - y] + 1, f[k][j - yy] + 1
若 f[n][m] > oo 则答案为 -1 否则为 f[n][m]
class Solution:
def __init__(self) -> None:
pass
def solution(self, n, m, vector):
if m == 0:
return 0
if n == 0:
return -1
oo = n * 2
f = [[oo for j in range(m + 1)] for i in range(n + 1)]
vector = sorted(vector)
zz = vector[0][0].split('/')[2]
s = 0
j = 0
f[0][0] = 0
for k, (x, y) in enumerate(vector):
y = int(y)
for i in range(m):
f[k + 1][i] = min(f[k + 1][i], f[k][i])
if f[k][i] < oo and i + y <= m:
f[k + 1][i + y] = min(f[k + 1][i + y], f[k][i] + 1)
z = x.split('/')[2]
if z != zz:
for i in range(m):
if f[j][i] < oo and i + s <= m:
f[k + 1][i + s] = min(f[k + 1][i + s], f[j][i] + 1)
s = y
zz = z
j = k
else:
s += y
for i in range(m):
if f[j][i] < oo and i + s <= m:
f[k + 1][i + s] = min(f[k + 1][i + s], f[j][i] + 1)
ans = min([f[k][m] for k in range(n + 1)])
if ans < oo:
return ans
return -1
if __name__ == "__main__":
arr_temp = [int(item) for item in input().strip().split()]
n = int(arr_temp[0])
m = int(arr_temp[1])
vector = []
for i in range(n):
vector.append([item for item in input().strip().split()])
sol = Solution()
result = sol.solution(n, m, vector)
print(result)
4. 交际圈
题目
小明参加了个大型聚会。聚会上有n个人参加,我们将他们编号为1…n,有些人已经互相认识了,有些人还不认识。聚会开始后,假设A跟B认识,A会给所有他认识的人介绍B,原先跟A认识,但不认识B的人,都会在此时,跟B互相认识。当所有人都把自己认识的人介绍一遍后,此时n个人就会形成k个交际圈,同一个交际圈中,两两互相认识,不同的交际圈之间,互相不认识
问题:当所有人都把自己认识的人介绍一遍后,形成了多少个交际圈
输入描述:
第1行包含两个数字n(n <= 100000), m(m <= 100000),n表示参加聚会的人数,m表示聚会前,有多少对人已经互相认识了
第2行到第m+1行,每一行包含两个数字,a和b(a != b, 1 <= a, b <= n),代表的是聚会前,a和b已经互相认识
输出描述:
输出一个数字,表示形成的交际圈的个数
输入样例:
3 3
1 2
1 3
2 3
输出样例:
1
解题报告
图论。用并查集统计有多少个连通块即可
class Solution:
def __init__(self) -> None:
pass
def getf(self, x):
if self.f[x] != x:
self.f[x] = self.getf(self.f[x])
return self.f[x]
def solution(self, n, m, vector):
self.f = [i for i in range(n + 1)]
v = set()
for x, y in vector:
x = self.getf(self.f[x])
y = self.getf(self.f[y])
self.f[x] = y
for i in range(1, n + 1):
self.f[i] = self.getf(i)
return len(set(self.f[1:]))
if __name__ == "__main__":
arr_temp = [int(item) for item in input().strip().split()]
n = int(arr_temp[0])
m = int(arr_temp[1])
vector = []
for i in range(m):
vector.append([int(item) for item in input().strip().split()])
sol = Solution()
result = sol.solution(n, m, vector)
print(result)
以上是关于[解题报告] CSDN竞赛第23期的主要内容,如果未能解决你的问题,请参考以下文章