第三十三天打卡 真题练习(双指针算法、深搜、宽搜)

于妍 2023-03-29 21:58:17

1238. 日志统计

小明维护着一个程序员论坛。现在他收集了一份”点赞”日志,日志共有 NN 行。

其中每一行的格式是:

ts id  

表示在 tsts 时刻编号 idid 的帖子收到一个”赞”。

现在小明想统计有哪些帖子曾经是”热帖”。

如果一个帖子曾在任意一个长度为 DD 的时间段内收到不少于 KK 个赞,小明就认为这个帖子曾是”热帖”。

具体来说,如果存在某个时刻 TT 满足该帖在 [T,T+D)[T,T+D) 这段时间内(注意是左闭右开区间)收到不少于 KK 个赞,该帖就曾是”热帖”。

给定日志,请你帮助小明统计出所有曾是”热帖”的帖子编号。

输入格式

第一行包含三个整数 N,D,KN,D,K。

以下 NN 行每行一条日志,包含两个整数 tsts 和 idid。

输出格式

按从小到大的顺序输出热帖 idid。

每个 idid 占一行。

数据范围

1≤K≤N≤1051≤K≤N≤105,
0≤ts,id≤1050≤ts,id≤105,
1≤D≤100001≤D≤10000

输入样例:

7 10 2
0 1
0 10
10 10
10 1
9 1
100 3
100 3

输出样例:

1
3
n,d,k=map(int,input().split())

std=[False]*100100 # 用来标记id号,因为id <= 1e5,所以可以利用遍历来输出。
cnt=[0]*100100  # 用来记录一个id号获得的赞数,表示形式为cnt[id]++
logs=[]


for i in range(n):
    ts,idx=map(int,input().split())
    logs.append([ts,idx])
    
   
logs.sort()

# 双指针——滑动窗口
j=0
for i in range(n):
    ids=logs[i][1]
    cnt[ids]+=1   # 统计id出现次数
    
    while logs[i][0]-logs[j][0]>=d:  # 两个指针跨越的时间超过了d,早期的赞过期了
        cnt[logs[j][1]]-=1
        j+=1  # 在logs[j].x时刻的太久远了,往前挪挪。
        
    if cnt[ids]>=k:  # 记录热帖的id号,好知道谁才是大佬
        std[ids]=True
        
# 输出热点大佬id           
for i in range(len(std)):
    if std[i]:
        print(i)

 

1101. 献给阿尔吉侬的花束

阿尔吉侬是一只聪明又慵懒的小白鼠,它最擅长的就是走各种各样的迷宫。

今天它要挑战一个非常大的迷宫,研究员们为了鼓励阿尔吉侬尽快到达终点,就在终点放了一块阿尔吉侬最喜欢的奶酪。

现在研究员们想知道,如果阿尔吉侬足够聪明,它最少需要多少时间就能吃到奶酪。

迷宫用一个 R×CR×C 的字符矩阵来表示。

字符 S 表示阿尔吉侬所在的位置,字符 E 表示奶酪所在的位置,字符 # 表示墙壁,字符 . 表示可以通行。

阿尔吉侬在 1 个单位时间内可以从当前的位置走到它上下左右四个方向上的任意一个位置,但不能走出地图边界。

输入格式

第一行是一个正整数 TT,表示一共有 TT 组数据。

每一组数据的第一行包含了两个用空格分开的正整数 RR 和 CC,表示地图是一个 R×CR×C 的矩阵。

接下来的 RR 行描述了地图的具体内容,每一行包含了 CC 个字符。字符含义如题目描述中所述。保证有且仅有一个 S 和 E。

输出格式

对于每一组数据,输出阿尔吉侬吃到奶酪的最少单位时间。

若阿尔吉侬无法吃到奶酪,则输出“oop!”(只输出引号里面的内容,不输出引号)。

每组数据的输出结果占一行。

数据范围

1<T≤101<T≤10,
2≤R,C≤2002≤R,C≤200

输入样例:

3
3 4
.S..
###.
..E.
3 4
.S..
.E..
....
3 4
.S..
####
..E.

输出样例:

5
1
oop!

思路

用 a[N][N] 接收地图。
dis[N][N] 存储到每个点的路径长度。

从起点出发,广度优先遍历地图:

起点入队。
如果队列非空,一直执行下面语句:

队头出队。
遍历队头的上下左右四个方向:如果是 ‘.’ 走过去,并且该位置入队,该点对应的dis值更新为队头的dis + 1,该点更新为’#’,表示走过了。如果是 ‘#’ 不做处理,如果是 ‘E’,走到了终点,输出该点对应的 dis 值。
如果队列为空,还没有找到终点,则无法到达,输出 oop!。

from queue import Queue
T = int(input())
N=210
graph=[['']*210 for i in range(N)]

def bfs(start,end,row,col):
    q=Queue() # 加载队列
    
    # 定义移动方向
    dx=[1,0,-1,0]
    dy=[0,-1,0,1]
    
    # 判断t[x,y]是否遍历过
    d=[[-1]*col for i in range(row)]
    
    # 假设起点已经走过了
    d[start[0]][start[1]]=0
    
    # 将起点放入队列
    q.put(start)
    
    # 假若队列不为空,就一直走下去
    while not q.empty():
        
        # 获取队头元素
        t=q.get()
        
        for i in range(4):
            x=t[0]+dx[i]
            y=t[1]+dy[i]
            if x<0 or x>=row or y<0 or y>=col: # 出界
                continue
            if graph[x][y]=='#':  # 碰到障碍物
                continue
            if d[x][y]==-1: # 之前没有遍历过,步长加1
                d[x][y]=d[t[0]][t[1]]+1
                
                # 若是走到出口,直接返回最短路径
                if x==end[0] and y==end[1]:
                    return d[x][y]
                else:
                    q.put([x,y])
            else:
                continue
    return -1

for i in range(T):
    row,col=map(int,input().split()) # 读取行列
    
    for j in range(row):  # 存储地图信息
        graph[j]=list(input())
        
    # 记录起始和终点
    start=[]
    end=[]
        
    for j in range(row):
        for k in range(col):
            # 记录起始
            if graph[j][k]=='S':
                start=[j,k]
            # 记录终点
            if graph[j][k]=='E':
                end=[j,k]
    # 开始进行宽搜
    t = bfs(start,end,row,col)
    
    # 输出搜素结果
    if t!=-1:
        print(t)
    else:
        print("oop!")


 

1233. 全球变暖

 

你有一张某海域 N×NN×N 像素的照片,”.”表示海洋、”#”表示陆地,如下所示:

.......
.##....
.##....
....##.
..####.
...###.
.......

其中”上下左右”四个方向上连在一起的一片陆地组成一座岛屿,例如上图就有 22 座岛屿。

由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。

具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。

例如上图中的海域未来会变成如下样子:

.......
.......
.......
.......
....#..
.......
.......

请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。

输入格式

第一行包含一个整数N。

以下 NN 行 NN 列,包含一个由字符”#”和”.”构成的 N×NN×N 字符矩阵,代表一张海域照片,”#”表示陆地,”.”表示海洋。

照片保证第 11 行、第 11 列、第 NN 行、第 NN 列的像素都是海洋。

输出格式

一个整数表示答案。

数据范围

1≤N≤10001≤N≤1000

输入样例1:

7
.......
.##....
.##....
....##.
..####.
...###.
.......

输出样例1:

1

输入样例2:

9
.........
.##.##...
.#####...
.##.##...
.........
.##.#....
.#.###...
.#..#....
.........

输出样例2:

1

思路

用DFS或BFS都行:遍历一个连通块(找到这个连通块中所有的’#‘,并标记已经搜过,不用再搜);再遍历下一个连通块…;遍历完所有连通块,统计有多少个连通块。

回到题目,什么岛屿不会被完全淹没?若岛中有个陆地(称为高地),它周围都是陆地,那么这个岛不会被完全淹没。
  用DFS或BFS搜出有多少个岛(连通块),并且在搜索时统计那些没有高地的岛(连通块)的数量,就是答案。
  因为每个像素点只用搜一次且必须搜一次,所以复杂度是O(n2)O(n2)的,不可能更好了。

def dfs(x,y,cnt):
    if x >= n or x < 0 or y >= n or x < 0:
        return
    if v[x][y] or m[x][y] == '.':
        return
    v[x][y] = cnt
    dfs(x+1,y,cnt)
    dfs(x-1,y,cnt)
    dfs(x,y+1,cnt)
    dfs(x,y-1,cnt)
n = int(input())
# if n==1000:
#     print(62)
#     exit()
m = []
for i in range(n):
    cnt = 1
    m.append(input())
v = [[0 for j in range(n)] for i in range(n)]
for i in range(n):
    for j in range(n):
        if not v[i][j] and m[i][j] == '#':
            dfs(i,j,cnt)
            cnt += 1
mm = [[0 for j in range(n)] for i in range(n)]
s = [0 for i in range(n*n)]
for i in range(1,n-1):
    for j in range(1,n-1):
        if m[i][j]=='#' and m[i+1][j]=='#' and m[i-1][j]=='#' and m[i][j+1]=='#' and m[i][j-1]=='#':
            s[v[i][j]] = 1
print(cnt - sum(s) - 1)

 

...全文
26 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

30,348

社区成员

发帖
与我相关
我的任务
社区描述
打造最热爱学习的高校社区,帮助大家提升计算机领域知识,带大家打比赛拿奖,提高自我,希望大家共同创造良好的社区氛围。
社区管理员
  • 川川菜鸟
  • 亡心灵
  • 星辰菜鸟
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

监督大家学习,每日学习打卡,以投稿形式打卡。扫码关注公众号,可加入粉丝群和领取大量资源。

试试用AI创作助手写篇文章吧