leetcode 力扣 750 隔离病毒题解 算法题.docx

上传人:b****4 文档编号:4210916 上传时间:2022-11-28 格式:DOCX 页数:21 大小:62.33KB
下载 相关 举报
leetcode 力扣 750 隔离病毒题解 算法题.docx_第1页
第1页 / 共21页
leetcode 力扣 750 隔离病毒题解 算法题.docx_第2页
第2页 / 共21页
leetcode 力扣 750 隔离病毒题解 算法题.docx_第3页
第3页 / 共21页
leetcode 力扣 750 隔离病毒题解 算法题.docx_第4页
第4页 / 共21页
leetcode 力扣 750 隔离病毒题解 算法题.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

leetcode 力扣 750 隔离病毒题解 算法题.docx

《leetcode 力扣 750 隔离病毒题解 算法题.docx》由会员分享,可在线阅读,更多相关《leetcode 力扣 750 隔离病毒题解 算法题.docx(21页珍藏版)》请在冰豆网上搜索。

leetcode 力扣 750 隔离病毒题解 算法题.docx

leetcode力扣750隔离病毒题解算法题

题目:

隔离病毒

病毒扩散得很快,现在你的任务是尽可能地通过安装防火墙来隔离病毒。

假设世界由 mxn 的二维矩阵 isInfected 组成, isInfected[i][j]==0 表示该区域未感染病毒,而 isInfected[i][j]==1 表示该区域已感染病毒。

可以在任意2个相邻单元之间的共享边界上安装一个防火墙(并且只有一个防火墙)。

每天晚上,病毒会从被感染区域向相邻未感染区域扩散,除非被防火墙隔离。

现由于资源有限,每天你只能安装一系列防火墙来隔离其中一个被病毒感染的区域(一个区域或连续的一片区域),且该感染区域对未感染区域的威胁最大且保证唯一 。

你需要努力使得最后有部分区域不被病毒感染,如果可以成功,那么返回需要使用的防火墙个数;如果无法实现,则返回在世界被病毒全部感染时已安装的防火墙个数。

 

示例1:

输入:

isInfected=[[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]]

输出:

10

解释:

一共有两块被病毒感染的区域。

在第一天,添加5墙隔离病毒区域的左侧。

病毒传播后的状态是:

第二天,在右侧添加5个墙来隔离病毒区域。

此时病毒已经被完全控制住了。

示例2:

输入:

isInfected=[[1,1,1],[1,0,1],[1,1,1]]

输出:

4

解释:

虽然只保存了一个小区域,但却有四面墙。

注意,防火墙只建立在两个不同区域的共享边界上。

示例 3:

输入:

isInfected=[[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]]

输出:

13

解释:

在隔离右边感染区域后,隔离左边病毒区域只需要2个防火墙。

 

提示:

•m== isInfected.length

•n== isInfected[i].length

•1<=m,n<=50

•isInfected[i][j] iseither 0 or 1

•在整个描述的过程中,总有一个相邻的病毒区域,它将在下一轮严格地感染更多未受污染的方块 

 

语言:

Python

classSolution(object):

defcontainVirus(self,grid):

R,C=len(grid),len(grid[0])

defneighbors(r,c):

fornr,ncin((r-1,c),(r+1,c),(r,c-1),(r,c+1)):

if0<=nr

yieldnr,nc

defdfs(r,c):

if(r,c)notinseen:

seen.add((r,c))

regions[-1].add((r,c))

fornr,ncinneighbors(r,c):

ifgrid[nr][nc]==1:

dfs(nr,nc)

elifgrid[nr][nc]==0:

frontiers[-1].add((nr,nc))

perimeters[-1]+=1

ans=0

whileTrue:

#Findallregions,withassociatedfrontiersandperimeters.

seen=set()

regions=[]

frontiers=[]

perimeters=[]

forr,rowinenumerate(grid):

forc,valinenumerate(row):

ifval==1and(r,c)notinseen:

regions.append(set())

frontiers.append(set())

perimeters.append(0)

dfs(r,c)

#Iftherearenoregionsleft,break.

ifnotregions:

break

#Addtheperimeteroftheregionwhichwillinfectthemostsquares.

triage_index=frontiers.index(max(frontiers,key=len))

ans+=perimeters[triage_index]

#Triagethemostinfectiousregion,andspreadtherestoftheregions.

fori,reginenumerate(regions):

ifi==triage_index:

forr,cinreg:

grid[r][c]=-1

else:

forr,cinreg:

fornr,ncinneighbors(r,c):

ifgrid[nr][nc]==0:

grid[nr][nc]=1

returnans

语言:

Java

classSolution{

Setseen;

List>regions;

List>frontiers;

Listperimeters;

int[][]grid;

intR,C;

int[]dr=newint[]{-1,1,0,0};

int[]dc=newint[]{0,0,-1,1};

publicintcontainVirus(int[][]grid){

this.grid=grid;

R=grid.length;

C=grid[0].length;

intans=0;

while(true){

seen=newHashSet();

regions=newArrayList();

frontiers=newArrayList();

perimeters=newArrayList();

for(intr=0;r

for(intc=0;c

if(grid[r][c]==1&&!

seen.contains(r*C+c)){

regions.add(newHashSet());

frontiers.add(newHashSet());

perimeters.add(0);

dfs(r,c);

}

}

}

if(regions.isEmpty())break;

inttriageIndex=0;

for(inti=0;i

if(frontiers.get(triageIndex).size()

triageIndex=i;

}

ans+=perimeters.get(triageIndex);

for(inti=0;i

if(i==triageIndex){

for(intcode:

regions.get(i))

grid[code/C][code%C]=-1;

}else{

for(intcode:

regions.get(i)){

intr=code/C,c=code%C;

for(intk=0;k<4;++k){

intnr=r+dr[k],nc=c+dc[k];

if(nr>=0&&nr=0&&nc

grid[nr][nc]=1;

}

}

}

}

}

returnans;

}

publicvoiddfs(intr,intc){

if(!

seen.contains(r*C+c)){

seen.add(r*C+c);

intN=regions.size()

regions.get(N-1).add(r*C+c);

for(intk=0;k<4;++k){

intnr=r+dr[k],nc=c+dc[k];

if(nr>=0&&nr=0&&nc

if(grid[nr][nc]==1){

dfs(nr,nc);

}elseif(grid[nr][nc]==0){

frontiers.get(N-1).add(nr*C+nc);

perimeters.set(N-1,perimeters.get(N-1)+1);

}

}

}

}

}

}

语言:

cpp

constintN=55;

classSolution{

public:

intres;

constintdir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};//方向变量

intn,m;//row,col

boolvi[55][55];//访问标记

intCal(vector>&g,intx,inty){

//计算有(x,y)的区域的危险度

queueq;

unordered_setst;//会感染的位置集合自动去重

vi[x][y]=true;

q.push(x*N+y);

while(!

q.empty()){

intt=q.front();q.pop();

intu=t/N;

intv=t%N;

for(inti=0;i<4;i++){

intnx=u+dir[i][0];

intny=v+dir[i][1];

if(nx<0||nx==n||ny<0||ny==m||g[nx][ny]==2||vi[nx][ny])continue;//表示下一个是墙或者已经访问过了

if(g[nx][ny]==0){//如果是0说明这块是要感染的

st.insert(nx*N+ny);

}elseif(g[nx][ny]){//否则加入队列

vi[nx][ny]=true;

q.push(nx*N+ny);

}

}

}

returnst.size();

}

voidhelp_close(vector>&g,intx,inty){

//安装挡板操作变成2表示变成墙了

queueq;

vi[x][y]=true;

g[x][y]=2;

q.push(x*N+y);

while(!

q.empty()){

intt=q.front();q.pop();

intu=t/N;

intv=t%N;

for(inti=0;i<4;i++){

intnx=u+dir[i][0];

intny=v+dir[i][1];

if(nx<0||nx==n||ny<0||ny==m||vi[nx][ny]||g[nx][ny]==2)continue;//表示下一个是墙或者已经访问了

if(g[nx][ny]==0){

res++;//需要安装挡板

continue;

}

vi[nx][ny]=true;

g[nx][ny]=2;

q.push(nx*N+ny);

}

}

}

voidhelp_spread(vector>&g,intx,inty){

//含有(x,y)点的连通区域开始扩散

queueq;

vi[x][y]=true;

q.push(x*N+y);

while(!

q.empty()){

intt=q.front();q.pop();

intu=t/N;

intv=t%N;

for(inti=0;i<4;i++){

intnx=u+dir[i][0];

intny=v+dir[i][1];

if(nx<0||nx==n||ny<0||ny==m||vi[nx][ny]||g[nx][ny]==2)continue;//访问过了

if(g[nx][ny]==0){

g[nx][ny]=1;

vi[nx][ny]=true;

continue;

}

vi[nx][ny]=true;

q.push(nx*N+ny);

}

}

}

intcontainVirus(vector>&g){

//按照题目意思模拟即可

//重点就是如何判断每一个连通区域

res=0;

n=g.size(),m=g[0].size();

while(true){

//直到没有空闲位置或者全部被封闭

for(inti=0;i

intx,y,curn;

curn=-1;//当前的威胁

intnum=0;//连通区域的个数

vectorh;//存储每一个联通块中的一个点

for(inti=0;i

for(intj=0;j

if(!

vi[i][j]&&g[i][j]==1){

num++;

h.push_back(i*N+j);

intt=Cal(g,i,j);

if(t>curn)x=i,y=j,curn=t;

}

}

}

if(num==0)returnres;//如果没有一个病毒块则直接返回

for(inti=0;i

help_close(g,x,y);//把威胁最大的连通块放置挡板

if(num==1)break;

//剩下的进行扩散

for(auto&i:

h){

intu=i/N;

intv=i%N;

if(vi[u][v])continue;

help_spread(g,u,v);//扩散

}

}

returnres;

}

};

语言:

cpp

/*

*/

classSolution{

private:

structArea

{

unordered_setdead;

unordered_settoDead;

//设置障碍的数量

intcnt=0;

};

//数组的行数和列数

introws;

intcols;

bool**visited;

//遍历四个方向,写到一个数组里了

intdires[5]={0,1,0,-1,0};

//基于深度优先的找没处理病毒区域(grid[x][y]==1)

voiddfs(constvector>&grid,Area&area,intx,inty)

{

if(grid[x][y]==0)

{

++t;

area.toDead.insert(x*50+y);

}

else

{

//其实这里只有1的情况,-1已经隔离的病毒在下面会过滤

area.dead.insert(x*50+y);

visited[x][y]=true;

//四个方向去查找1

for(intk=0;k<4;++k)

{

intnx=x+dires[k];

intny=y+dires[k+1];

//有效范围;没有遍历;且没被隔离

if(nx>=0&&nx=0&&ny

visited[nx][ny]&&grid[nx][ny]!

=-1)

{

dfs(grid,area,nx,ny);

}

}

}

}

public:

intcontainVirus(vector>&grid){

rows=grid.size();

cols=grid[0].size();

intres=0;

//visisted来避免循环遍历

visited=newbool*[rows];

for(inti=0;i

{

visited[i]=newbool[cols];

memset(visited[i],0,sizeof(bool)*cols);

}

while(true)

{

for(inti=0;i

{

memset(visited[i],0,sizeof(bool)*cols);

}

//用一个简单数组记录最大值来模拟优先队列

vectorq;

intmaxIndex=0;

//遍历每个点去dfs找区域

for(inti=0;i

{

for(intj=0;j

{

//只有没遍历,而且为没隔离的病毒区域才考虑

if(!

visited[i][j]&&grid[i][j]==1)

{

Areaarea;

dfs(grid,area,i,j);

q.emplace_back(area);

if(area.toDead.size()>q[maxIndex].toDead.size())

{

maxIndex=q.size()-1;

}

}

}

}

//所有病毒都处理完

if(q.empty())

{

break;

}

intn=q.size();

for(inti=0;i

{

auto&a=q[i];

if(i!

=maxIndex)

{

for(constint&p:

a.toDead)

{

grid[p/50][p%50]=1;

}

}

else

{

for(constint&p:

a.dead)

{

grid[p/50][p%50]=-1;

}

res+=t;

}

}

}

returnres;

}

};

语言:

cpp

classSolution{

public:

intflag;

intm;

intn;

intex[4][2]={{1,0},{-1,0},{0,1},{0,-1}};

boolisvalidxy(intx,inty)

{

return(x>=0&&x=0&&y

}

voiddfsarea(vector>&grid,vector&st,vector>&vst,set&toinject,vector&inject,int&sfn)

{

intlen=st.size();

if(len==0)

{

return;

}

vectornewst;

for(inti=0;i

{

intx=st[i]/n;

inty=st[i]%n;

for(intj=0;j<4;j++)

{

intnx=x+ex[j][0];

intny=y+ex[j][1];

if(!

isvalidxy(nx,ny)||vst[nx][ny]==1)

{

continue;

}

if(grid[nx][ny]==0)

{

toinject.insert(nx*n+ny);

sfn++;

continue;

}

elseif(grid[nx][ny]==1)

{

newst.push_back(nx*n+ny);

vst[nx][ny]=1;

inject.push_back(nx*n+ny);

}

}

}

dfsarea(grid,newst,vst,toinject,inject,sfn);

}

voidsetarea(vector>&grid,vector&st,intflag)

{

intlen=st.size();

for(inti=0;i

{

intx=st[i]/n;

inty=st[i]%n;

grid[x][y]=flag;

}

}

voidsetarea(vector>&grid,set&st,intflag)

{

for(autoit=st.begin()

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 其它模板

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1