Biweekly Contest 91

Biweekly Contest 91

Problem A

Number of Distinct Averages

思路

按照题意模拟即可,最后set的大小就是所求结果

代码

class Solution:
    def distinctAverages(self, nums: List[int]) -> int:
        nums.sort()
        s =set()
        n = len(nums)
        for i in range(n//2):
            s.add(nums[i]+nums[n-i-1])
        return len(s)

Problem B

Count Ways To Build Good Strings

思路

比赛时想偏了,一直以为是组合数推公式,后面才反应过来是DP题。最开始的想法自然是0,1分开处理,反正开个2维内存也不会很大。第一维是长度,第二维是0、1,后面转移方程感觉有点问题,但是所幸过了。后面看了大佬的题解才搞明白正确的转移方程,而且0、1是可以合并的,不会干扰到计算。

代码

比赛代码

import numpy as np
class Solution:
    def countGoodStrings(self, low: int, high: int, zero: int, one: int) -> int:
        ans = 0
        MOD = int(1e9+7)
        # print(MOD)
        dp = np.zeros((high+1,2),dtype = np.int)
        dp[zero][0] = 1
        dp[one][1] = 1
        for i in range(high+1):
            # print(i)
            if i-zero>=0:
                dp[i][0] = max(dp[i][0],dp[i-zero][0]+dp[i-zero][1])%MOD
            if i - one>=0:
                dp[i][1] = max(dp[i][1],dp[i-one][0]+dp[i-one][1])%MOD
            # print(dp)
        ans = 0
        for i in range(low,high+1):
            ans = (ans+dp[i][0]+dp[i][1])%MOD
        return ans

补题代码

class Solution:
    def countGoodStrings(self, low: int, high: int, zero: int, one: int) -> int:
        MOD = 10**9+7
        dp = [1]+[0]*(high)
        for i in range(high+1):
            if i>=one: dp[i] = (dp[i]+dp[i-one])%MOD
            if i>=zero: dp[i] = (dp[i]+dp[i-zero])%MOD
        return sum(dp[low:])%MOD

Problem C

Most Profitable Path in a Tree

思路

思路不难,bob找0的路径是固定的,先1遍DFS求这个,然后从0开始dfs,找一个最小代价的到叶节点的路径就好了,代价计算就按照题目要求来写,我比赛的时候是对遍建的邻接表,感觉建树会好处理一点。这题蛮可惜的,B题花了太多时间,赛后才过。大佬的想法跟我差不多,优化的点一个是用fa保证不会重复访问,这是树的特点,我用的是visit数组,还有就是相遇节点如何判定,大佬用的是一个时间数组,而我因为用的是visit数组,导致判定比较复杂,也出了不少BUG.

代码

比赛代码

import numpy as np
class Solution:
    def mostProfitablePath(self, edges: List[List[int]], bob: int, amount: List[int]) -> int:
        n = len(edges)
        G = []
        for i in range(n+1):
            G.append([])
        for i in range(n):
            x,y,c = edges[i][0],edges[i][1],amount[i]
            # print(x,y,c)
            G[x].append(y)
            G[y].append(x)
        B = []
        # print(G)
        visit = np.zeros(n+1,dtype= np.int)
        def getSite(x):
           
            if x == 0:
                B.append(x)
                return True
            for item in G[x]:
                if visit[item]==0:
                    visit[item]=1
                    if getSite(item):
                        # print(B)
                        B.append(x)
                        return True
                    visit[item] = 0
            return False
        visit[bob] =1
        getSite(bob)
        B = B[::-1]
        # print(B)
        self.t = len(B)
        self.ans = "S"
        visit = np.zeros(n+1,dtype= np.int)
        visit1 = np.zeros(n+1,dtype= np.int)
        def dfs(x,v,d):
            # print(x,v,d)
            if x!=0 and len(G[x])==1:
                if self.ans == "S":
                    self.ans = v
                else:
                    self.ans= max(self.ans,v)
                return 
            if d+1<self.t:
                visit1[B[d+1]] = 1
            for item in G[x]:
                # print(x,item)
                c = amount[item]
                if visit[item]==0:
                    visit[item] = 1
                    if d+1<self.t and item == B[d+1]:
                        dfs(item,v+c//2,d+1)  
                        continue
                    if visit1[item]==0:
                        dfs(item,v+c,d+1)
                    else:
                        dfs(item,v,d+1)
                    visit[item] = 0
            if d+1<self.t:
                visit1[B[d+1]] = 0
            # print("end",x,visit)
            return 
        c = 0
        if B[0]==0:
            c = amount[0]//2
        else:
            c = amount[0]
        visit[0] = 1
        visit1[bob] = 1
        dfs(0,c,0)
        return self.ans
        

补题代码

class Solution:
    def mostProfitablePath(self, edges: List[List[int]], bob: int, amount: List[int]) -> int:
        n = len(amount)+1
        G = [[] for _ in range(n)]
        for x,y in edges:
            G[x].append(y)
            G[y].append(x)
        bob_time = [n]*n
        bob_time[bob] = 0
        def dfs_bob(x,fa,t):
            if x==0:
                return True
            for y in G[x]:
                if y!=fa:
                    if dfs_bob(y,x,t+1):
                        bob_time[y]=t+1
                        return True
            return False
        dfs_bob(bob,-1,0)
        ans = -inf
        def dfs_a(x,fa,t,tot):
            if t<bob_time[x]:
                tot+=amount[x]
            elif t==bob_time[x]:
                tot+=amount[x]//2
            if x!=0 and len(G[x])==1:
                nonlocal ans
                ans = max(ans,tot)
                return
            for y in G[x]:
                if y!=fa:
                    dfs_a(y,x,t+1,tot)
            return
        dfs_a(0,-1,0,0)
        return ans

Problem D

Split Message Based on Limit

思路

大佬的思路用的暴力,从小到大而枚举分割的数量,注意当数量的位数发生变化时尾部的长度也会发生变化,在代码中使用cap表示当前能最大能存储多少个字符,只有当这个数量大于len(message)时,才找到一个最小长度的划分,代码里的-9、-99、-999时在位数增加时所能存储的有效信息会少一位。最后构造即可

代码

补题代码

class Solution:
    def splitMessage(self, message: str, limit: int) -> List[str]:
        i,cap = 0,0
        n = len(message)
        while True:
            i+=1
            if i <10:
                tail = 5
            elif i<100:
                if i == 10:cap-=9
                tail = 7
            elif i<1000:
                if i == 100:cap-=99
                tail = 9
            elif i<10000:
                if i == 1000:cap-=999
                tail = 11
            if limit-tail<=0: return []
            cap+=limit-tail
            if cap < n:continue
            ans = []
            k = 0
            # print(i)
            for j in range(1,i+1):
                tail = f'<{j}/{i}>'
                m = 0
                if j<i:
                    m = limit -len(tail)
                    ans.append(message[k:k+m]+tail)
                else:
                    ans.append(message[k:]+tail)
                k+=m
            return ans

总结

出了2题,C题赛后出的,感觉主要问题是B题开始思路想错了,耽误了不少时间,导致C题没调出来,估计要掉分了。

posted @ 2022-11-15 13:34  浅花迷人  阅读(25)  评论(0编辑  收藏  举报