leetcode 力扣 750 隔离病毒题解 算法题Word格式文档下载.docx
- 文档编号:17126925
- 上传时间:2022-11-28
- 格式:DOCX
- 页数:21
- 大小:62.33KB
leetcode 力扣 750 隔离病毒题解 算法题Word格式文档下载.docx
《leetcode 力扣 750 隔离病毒题解 算法题Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《leetcode 力扣 750 隔离病毒题解 算法题Word格式文档下载.docx(21页珍藏版)》请在冰豆网上搜索。
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<
Rand0<
=nc<
C:
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:
ifgrid[nr][nc]==0:
grid[nr][nc]=1
returnans
Java
classSolution{
Set<
Integer>
seen;
List<
Set<
>
regions;
frontiers;
perimeters;
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<
R;
++r){
for(intc=0;
c<
C;
++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<
frontiers.size();
++i){
if(frontiers.get(triageIndex).size()<
frontiers.get(i).size())
triageIndex=i;
ans+=perimeters.get(triageIndex);
regions.size();
if(i==triageIndex){
for(intcode:
regions.get(i))
grid[code/C][code%C]=-1;
}else{
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<
R&
nc>
nc<
C&
grid[nr][nc]==0)
grid[nr][nc]=1;
returnans;
publicvoiddfs(intr,intc){
if(!
seen.add(r*C+c);
intN=regions.size()
regions.get(N-1).add(r*C+c);
C){
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;
public:
intres;
constintdir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
//方向变量
intn,m;
//row,col
boolvi[55][55];
//访问标记
intCal(vector<
vector<
int>
g,intx,inty){
//计算有(x,y)的区域的危险度
queue<
q;
unordered_set<
st;
//会感染的位置集合自动去重
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<
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<
//安装挡板操作变成2表示变成墙了
g[x][y]=2;
0||ny==m||vi[nx][ny]||g[nx][ny]==2)continue;
//表示下一个是墙或者已经访问了
if(g[nx][ny]==0){
res++;
//需要安装挡板
continue;
}
g[nx][ny]=2;
voidhelp_spread(vector<
//含有(x,y)点的连通区域开始扩散
//访问过了
g[nx][ny]=1;
intcontainVirus(vector<
g){
//按照题目意思模拟即可
//重点就是如何判断每一个连通区域
res=0;
n=g.size(),m=g[0].size();
while(true){
//直到没有空闲位置或者全部被封闭
n;
i++)memset(vi[i],false,m);
intx,y,curn;
curn=-1;
//当前的威胁
intnum=0;
//连通区域的个数
vector<
h;
//存储每一个联通块中的一个点
for(intj=0;
j<
m;
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;
//如果没有一个病毒块则直接返回
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;
};
/*
*/
private:
structArea
{
dead;
toDead;
//设置障碍的数量
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
++k)
intnx=x+dires[k];
intny=y+dires[k+1];
//有效范围;
没有遍历;
且没被隔离
if(nx>
nx<
rows&
ny>
=0&
ny<
cols&
visited[nx][ny]&
grid[nx][ny]!
=-1)
dfs(grid,area,nx,ny);
grid){
rows=grid.size();
cols=grid[0].size();
intres=0;
//visisted来避免循环遍历
visited=newbool*[rows];
rows;
++i)
visited[i]=newbool[cols];
memset(visited[i],0,sizeof(bool)*cols);
while(true)
//用一个简单数组记录最大值来模拟优先队列
Area>
intmaxIndex=0;
//遍历每个点去dfs找区域
for(intj=0;
j<
cols;
++j)
//只有没遍历,而且为没隔离的病毒区域才考虑
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();
auto&
a=q[i];
if(i!
=maxIndex)
for(constint&
p:
a.toDead)
grid[p/50][p%50]=1;
a.dead)
grid[p/50][p%50]=-1;
res+=t;
intflag;
intm;
intn;
intex[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
boolisvalidxy(intx,inty)
return(x>
x<
m&
y>
y<
n);
voiddfsarea(vector<
grid,vector<
st,vector<
vst,set<
toinject,vector<
inject,int&
sfn)
intlen=st.size();
if(len==0)
return;
newst;
len;
i++)
intx=st[i]/n;
inty=st[i]%n;
j++)
intnx=x+ex[j][0];
intny=y+ex[j][1];
isvalidxy(nx,ny)||vst[nx][ny]==1)
if(grid[nx][ny]==0)
toinject.insert(nx*n+ny);
sfn++;
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<
st,intflag)
grid[x][y]=flag;
grid,set<
{
for(autoit=st.begin()
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- leetcode 力扣 750 隔离病毒 题解 算法题 隔离 病毒 算法