Leetcode Contain Virus

231 篇文章 0 订阅

A virus is spreading rapidly, and your task is to quarantine the infected area by installing walls.

The world is modeled as a 2-D array of cells, where 0 represents uninfected cells, and 1 represents cells contaminated with the virus. A wall (and only one wall) can be installed between any two 4-directionally adjacent cells, on the shared boundary.

Every night, the virus spreads to all neighboring cells in all four directions unless blocked by a wall. Resources are limited. Each day, you can install walls around only one region -- the affected area (continuous block of infected cells) that threatens the most uninfected cells the following night. There will never be a tie.

Can you save the day? If so, what is the number of walls required? If not, and the world becomes fully infected, return the number of walls used.

 

Example 1:

Input: grid = 
[[0,1,0,0,0,0,0,1],
 [0,1,0,0,0,0,0,1],
 [0,0,0,0,0,0,0,1],
 [0,0,0,0,0,0,0,0]]
Output: 10
Explanation:
There are 2 contaminated regions.
On the first day, add 5 walls to quarantine the viral region on the left. The board after the virus spreads is:

[[0,1,0,0,0,0,1,1],
 [0,1,0,0,0,0,1,1],
 [0,0,0,0,0,0,1,1],
 [0,0,0,0,0,0,0,1]]

On the second day, add 5 walls to quarantine the viral region on the right. The virus is fully contained.

 

Example 2:

Input: grid = 
[[1,1,1],
 [1,0,1],
 [1,1,1]]
Output: 4
Explanation: Even though there is only one cell saved, there are 4 walls built.
Notice that walls are only built on the shared boundary of two different cells.

 

Example 3:

Input: grid = 
[[1,1,1,0,0,0,0,0,0],
 [1,0,1,0,1,1,1,1,1],
 [1,1,1,0,0,0,0,0,0]]
Output: 13
Explanation: The region on the left only builds two new walls.

 

Note:

  1. The number of rows and columns of grid will each be in the range [1, 50].
  2. Each grid[i][j] will be either 0 or 1.
  3. Throughout the described process, there is always a contiguous viral region that will infect strictly more uncontaminated squares in the next round.

---------------------------------------------------------------------------------------------

算法本身不难,难点是对题目的理解。有几点需要理解清楚:

  1. 防火墙可以包围某个连通病毒区域,而不是要求防火墙是连通的
  2. 从0到1相当于1一次感染。针对一个连通区域,感染几次要几个防火墙,相当于代码里的edges。edges里是可以重复的,也就是从四面八方感染某一个cell。
  3. 防火墙个数可能多于新感染区域个数,题目的意思是按照新感染个数排序,也就是set(edges)

以下是代码:

from collections import Counter
class Solution:
    def bfs(self, grid, x, y, seen):
        pos, edge = [(x,y)], []
        r, c = len(grid), len(grid[0])
        layers = [{(x, y)}, set()]
        seen.add((x,y)) #bug2
        cur, nxt = 0, 1
        while (layers[cur]):
            for cx, cy in layers[cur]:
                for (dx, dy) in [(1,0), (0,1), (-1,0), (0,-1)]: #bug1:(0,0)
                    nx, ny = cx + dx, cy + dy
                    if (nx >= 0 and nx < r and ny >= 0 and ny < c and (nx, ny) not in seen):
                        if (grid[nx][ny] == 0):
                            edge.append((nx, ny))
                        elif (grid[nx][ny] == 1):
                            seen.add((nx, ny))
                            pos.append((nx, ny))
                            layers[nxt].add((nx, ny))
            layers[cur].clear()
            cur, nxt = nxt, cur
        return pos, edge

    def get_virus(self, grid):
        r, c = len(grid), len(grid[0])
        vpos, edges = [], []
        seen = set()
        for i in range(r):
            for j in range(c):
                if (grid[i][j] == 1 and (i,j) not in seen):
                    pos, edge = self.bfs(grid, i, j, seen)
                    vpos.append(pos)
                    edges.append(edge)
        return vpos, edges

    def containVirus(self, grid):
        vpos, edges = self.get_virus(grid)
        res = 0
        while (edges):
            maxi, maxv = 0, 0 #bug3
            for i in range(len(edges)):
                cl = len(set(edges[i]))     #按感染最多的cell算,不是按最长的墙算
                if (cl > maxv):
                    maxi, maxv = i, len(set(edges[i]))
            res += len(edges[maxi])
            for (x, y) in vpos[maxi]:
                grid[x][y] = 2
            for i in range(len(edges)):
                if (i != maxi):
                    for (x, y) in edges[i]:
                        grid[x][y] = 1
            vpos, edges = self.get_virus(grid)
        return res

s = Solution()
print(s.containVirus([[0,1,0,1,1,1,1,1,1,0],
                      [0,0,0,1,0,0,0,0,0,0],
                      [0,0,1,1,1,0,0,0,1,0],
                      [0,0,0,1,1,0,0,1,1,0],
                      [0,1,0,0,1,0,1,1,0,1],
                      [0,0,0,1,0,1,0,1,1,1],
                      [0,1,0,0,1,0,0,1,1,0],
                      [0,1,0,1,0,0,0,1,1,0],
                      [0,1,1,0,0,1,1,0,0,1],
                      [1,0,1,1,0,1,0,1,0,1]]))

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
疫情居家办公系统管理系统按照操作主体分为管理员和用户。管理员的功能包括办公设备管理、部门信息管理、字典管理、公告信息管理、请假信息管理、签到信息管理、留言管理、外出报备管理、薪资管理、用户管理、公司资料管理、管理员管理。用户的功能等。该系统采用了MySQL数据库,Java语言,Spring Boot框架等技术进行编程实现。 疫情居家办公系统管理系统可以提高疫情居家办公系统信息管理问题的解决效率,优化疫情居家办公系统信息处理流程,保证疫情居家办公系统信息数据的安全,它是一个非常可靠,非常安全的应用程序。 管理员权限操作的功能包括管理公告,管理疫情居家办公系统信息,包括外出报备管理,培训管理,签到管理,薪资管理等,可以管理公告。 外出报备管理界面,管理员在外出报备管理界面中可以对界面中显示,可以对外出报备信息的外出报备状态进行查看,可以添加新的外出报备信息等。签到管理界面,管理员在签到管理界面中查看签到种类信息,签到描述信息,新增签到信息等。公告管理界面,管理员在公告管理界面中新增公告,可以删除公告。公告类型管理界面,管理员在公告类型管理界面查看公告的工作状态,可以对公告的数据进行导出,可以添加新公告的信息,可以编辑公告信息,删除公告信息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值