牛客周赛 Round 53 解题报告 | 珂学家

小红小紫投硬币

https://ac.nowcoder.com/acm/contest/86387/A


前言

alt


题解

赞助场,果然难。

每次周赛都能学到知识,^_^.


A. 小红小紫投硬币

思路: 数学

假设都是n次投硬币

  • p(win)为小红胜利的概率

  • P(draw)为平局的概率d

  • p(lose)为小红失利的概率

根据对称性, p=p(win)=p(lose)

此时小红多投一次,那么

  • 原先胜利,多投一次还是胜利
  • 原先失败,多投一次最多平局
  • 原先平局,多投一次,有一半概率转化为胜局

这就是恒为 1/2=0.5 的由来

print ("%.06f" %(0.5))

B. 小红的字符串

思路: 谈心

左移/右移的最小代价为

s = input()

i, j = 0, len(s) - 1
res = 0
while i < j:
    p1, p2 = ord(s[i]), ord(s[j])
    res += min(abs(p1 - p2), 26 - abs(p1 - p2))
    i += 1
    j -= 1
    
print (res)

C. 小红的 01 消除

思路: 栈模拟

其实'11', '00', 没有任何价值,操作只会让'01'配对数变少

因此单纯的栈模拟,模拟01配对消除

n = int(input())

s = input()

x, y, z = list(map(int, input().split()))

res = 0
stk = 0 # 模拟栈上的1个数
for c in s:
    if c == '0':
        stk += 1
    else:
        if stk > 0:
            stk -= 1
            res += 1

# 取两者的最小值
print (min(res, y))

D. 小红组比赛

思路: 分组背包

板子题

不过需要注意的是

  • 取每组的最大值总和,作为背包最大容量S
  • 不能取Target作为背包容量

因为和target最接近,是一个 绝对值最小的概念

n, m = list(map(int, input().split()))

g = []

for _ in range(n):
    tmp = list(map(int, input().split()))
    g.append(tmp)
    
target = int(input())

# 取每组的最大和,作为背包的最大容量
MX = sum([max(row) for row in g])
dp = [False] * (MX + 1)
dp[0] = True

for i in range(n):
    arr = g[i]
    dp2 = [False] * (MX + 1)
    for v in arr:
        for k in range(MX - v, -1, -1):
            if dp[k]:
                dp2[k + v] = True
    dp = dp2

from math import inf
ans = inf
for i in range(MX, -1, -1):
    if dp[i]:
        ans = min(ans, abs(target - i))
    
print (ans)

E. 折半丢弃

思路: 二分+贪心

这个数组的mex存在单调性,所以二分一定可行。

问题在于这个check如何构造验证呢?

这里有个贪心技巧,就是从大到小去构造补足。


为啥从小到大贪心构造不行呢?

比如存在,[0,1,2,4,5,6,7,7] 这个数组 从小到大贪,容易得到非最优解.


推而广之:


t = int(input())

def solve():
    n = int(input())
    arr = list(map(int, input().split()))
    
    def check(m):
        vis = [0] * (m + 1)
        for v in arr:
            while v > m:
                v //= 2
            vis[v] += 1
        ptr = m
        while vis[ptr] > 0 and ptr >= 0:
            if vis[ptr] == 0:
                return False
            vis[ptr // 2] += vis[ptr] - 1
            ptr -= 1
        return ptr == -1
    
    l, r = 0, n - 1
    while l <= r:
        m = l + (r - l) // 2
        if check(m):
            l = m + 1
        else:
            r = m - 1
    
    print (r + 1)
        
for _ in range(t):
    solve()


F. 小红走矩阵

思路: 分层BFS

这题应该属于多状态的分层BFS

  • 没有用技能, 普通BFS
  • 使用技能(枚举某个方向)+ 分层BFS

设计状态:

h, w = list(map(int, input().split()))

g = []
for _ in range(h):
    g.append(input())
    
from math import inf
dp = [[[[inf] * w for _ in range(h)] for _ in range(2)] for _ in range(5)]

from collections import deque

deq = deque()
if g[0][0] == '.':
    deq.append((4, 0, 0, 0))
    dp[4][0][0][0] = 0
    
    for i in range(4):
        dp[i][0][0][0] = 0
        deq.append((i, 0, 0, 0))
else:
    for i in range(4):
        dp[i][1][0][0] = 0
        deq.append((i, 1, 0, 0))
        
while len(deq) > 0:
    op, d, y, x = deq.popleft()
    cost = dp[op][d][y][x]
    
    for (i, (dy, dx)) in enumerate([(-1, 0), (1, 0), (0, -1), (0, 1)]):
        ty, tx = y + dy, x + dx
        if 0 <= ty < h and 0 <= tx < w:
            if g[ty][tx] == '.':
                if dp[op][d][ty][tx] > cost + 1:
                    dp[op][d][ty][tx] = cost + 1
                    deq.append((op, d, ty, tx))
            elif g[ty][tx] == 'X' and op != 4:
                if d == 0 and op != i:
                    if dp[op][1][ty][tx] > cost + 1:
                        dp[op][1][ty][tx] = cost + 1
                        deq.append((op, 1, ty, tx))
    
res = inf
for i in range(5):
    for j in range(2):
        res = min(res, dp[i][j][-1][-1])
        
print (-1 if res == inf else res)     
  

备注: 这题好像卡python,同等的java代码能过


G. 游游的删点直径


写在最后

alt

全部评论
qwq
1 回复 分享
发布于 2024-07-29 10:10 北京

相关推荐

XingHaozhe:没啥大问题啊,Agent + 后端业务,勇敢投!
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
05-13 16:09
我入职那天分到的mentor是个工作三年的哥们儿,外号杰哥,浙大本硕,技术贼好,人也特别耐心。第一周他手把手带我熟悉项目,下班还带我去公司食堂吃晚饭,跟我讲组里的人际关系、哪个产品好沟通、哪个测试爱挑刺。我当时心里那个踏实啊,心想这mentor是真带我,运气真好。我甚至已经开始幻想转正后跟着他干。周一下午四点多,我正在改一个特别恶心的bug,他飞书突然发我:"小x,跟你说个事儿,我下周一是最后一天,我跳槽了,你之后跟着王哥学。"我当时直接回复了“????”真的以为他在开玩笑。他发了一个尴尬笑的表情,"真的,offer上个月就拿了,一直没说"。我那一瞬间真的不知道说啥。下班的时候我特意去他工位转了一圈,他已经在收拾东西来,看见我笑了一下,说"我请你吃个饭吧"。我们去了公司楼下的麻辣烫。吃饭的时候他跟我说了很多,说大厂这边晋升路径太卷,说他家在外地啊老婆怀孕了啊想离家近点什么的,说新公司虽然小但是给的钱多。我一边吃一边点头,看到一个快到中年研发人的无奈,感觉也看到了未来的我,心里挺不是滋味的。今早上午他飞书里发我一个文档链接,是他这两年攒的项目笔记,模块分工、踩过的坑、谁负责啥都有。他说"这个你留着,遇到问题先看这个再找王哥吧"。说实话,我当时贼感动,工作的这两周,他可能是我在公司里唯一真正把我当回事儿的人了。最后,我想说兄弟们,找实习真的别只看大厂光环,mentor稳定性也是玄学之一。我现在心里有点空,感觉靠山没了
鹿LF:你mt不是才工作三年吗,怎么就中年研发人了
点赞 评论 收藏
分享
评论
23
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务