当前位置: 首页 > java >正文

代码随想录算法训练营四十六天|图论part04

岛屿问题(八)岛屿的周长

题目描述

给定一个由 1(陆地)和 0(水)组成的矩阵,岛屿是被水包围,并且通过水平方向或垂直方向上相邻的陆地连接而成的。

你可以假设矩阵外均被水包围。在矩阵中恰好拥有一个岛屿,假设组成岛屿的陆地边长都为 1,请计算岛屿的周长。岛屿内部没有水域。

输入描述

第一行包含两个整数 N, M,表示矩阵的行数和列数。之后 N 行,每行包含 M 个数字,数字为 1 或者 0,表示岛屿的单元格。

输出描述

输出一个整数,表示岛屿的周长。

输入示例

5 5
0 0 0 0 0 
0 1 0 1 0
0 1 1 1 0
0 1 1 1 0
0 0 0 0 0

输出示例

14

提示信息

岛屿的周长为 14。

数据范围:

1 <= M, N <= 50。

思路:

首先为了防止有的岛屿外没有水包围,我们给原有的矩阵外包一圈水。

之后遍历矩阵(不需要遍历外面那一圈水),如果当前坐标是陆地,那么遍历它上下左右看是否有水,如果有的话,那一条边就是周长的一部分,就需要算在周长里。

代码如下:

import java.util.*;public class Main{private static int ans=0;public static void main(String[] args){Scanner in=new Scanner(System.in);int n=in.nextInt();int m=in.nextInt();int[][] graph=new int[n+2][m+2];for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){graph[i][j]=in.nextInt();}}boolean[][] visited=new boolean[n+2][m+2];for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(graph[i][j]==1&&visited[i][j]==false){visited[i][j]=true;dfs(graph,visited,i,j);}}}System.out.println(ans);}private static int[][] dir={{0,1},{1,0},{-1,0},{0,-1}};public static void dfs(int[][] graph,boolean[][] visited,int x,int y){for(int i=0;i<4;i++){int nextx=x+dir[i][0];int nexty=y+dir[i][1];if(nextx<0||nexty<0||nextx>=graph.length||nexty>=graph[0].length)continue;if(graph[nextx][nexty]==0)ans++;if(graph[nextx][nexty]==1&&visited[nextx][nexty]==false){visited[nextx][nexty]=true;dfs(graph,visited,nextx,nexty);}}}
}

字符串接龙

题目描述

字典 strList 中从字符串 beginStr 和 endStr 的转换序列是一个按下述规格形成的序列:

序列中第一个字符串是 beginStr。

序列中最后一个字符串是 endStr。

每次转换只能改变一个位置的字符(例如 ftr 可以转化 fty ,但 ftr 不能转化 frx)。

转换过程中的中间字符串必须是字典 strList 中的字符串。

beginStr 和 endStr 不在 字典 strList 中

字符串中只有小写的26个字母

给你两个字符串 beginStr 和 endStr 和一个字典 strList,找到从 beginStr 到 endStr 的最短转换序列中的字符串数目。如果不存在这样的转换序列,返回 0。

输入描述

第一行包含一个整数 N,表示字典 strList 中的字符串数量。 第二行包含两个字符串,用空格隔开,分别代表 beginStr 和 endStr。 后续 N 行,每行一个字符串,代表 strList 中的字符串。

输出描述

输出一个整数,代表从 beginStr 转换到 endStr 需要的最短转换序列中的字符串数量。如果不存在这样的转换序列,则输出 0。

输入示例:

6
abc def
efc
dbc
ebc
dec
dfc
yhn

输出示例

4

提示信息

从 startStr 到 endStr,在 strList 中最短的路径为 abc -> dbc -> dec -> def,所以输出结果为 4,如图:

数据范围:

2 <= N <= 500

思路:

首先我们要解决两个问题:

1.图中的边是怎么来的?我们用26个英文字母替换当前字符串的每一个字符,看替换后是否在strList中出现过,如果出现过,那么这里就有一条边。

2.起点和终点的最短路径长度:

直接使用广搜法,只要搜到了终点(也就是endString),那么就一定是最短路径。这里如果用深搜法会比较麻烦,因为需要再到达终点的不同路径中选一条最短路径。

需要注意的是我们需要标记节点是否走过,这里使用set集合来检查会更快一点。

代码如下:

import java.util.*;public class Main{public static void main(String[] args){Scanner in=new Scanner(System.in);int n=in.nextInt();String begin=in.next();String end=in.next();List<String> list=new ArrayList<>();list.add(begin);list.add(end);for(int i=0;i<n;i++){list.add(in.next());}int ans=bfs(begin,end,list);System.out.println(ans);}public static int bfs(String begin,String end,List<String> list){int len=1;Set<String> set=new HashSet<>();//相当于visitedQueue<String> q=new LinkedList<>();q.offer(begin);q.offer(null);while(!q.isEmpty()){String tmp=q.poll();if(tmp==null){if(!q.isEmpty()){len++;q.offer(null);}continue;}set.add(tmp);char[] array=tmp.toCharArray();for(int i=0;i<array.length;i++){char old=array[i];for(char ch='a';ch<='z';ch++){array[i]=ch;String newString=new String(array);if(!set.contains(newString)&&list.contains(newString)){set.add(newString);q.offer(newString);if(newString.equals(end))return len+1;}}array[i]=old;}}return 0;}
}

有向图的完全联通

题目描述

给定一个有向图,包含 N 个节点,节点编号分别为 1,2,...,N。现从 1 号节点开始,如果可以从 1 号节点的边可以到达任何节点,则输出 1,否则输出 -1。

输入描述

第一行包含两个正整数,表示节点数量 N 和边的数量 K。 后续 K 行,每行两个正整数 s 和 t,表示从 s 节点有一条边单向连接到 t 节点。

输出描述

如果可以从 1 号节点的边可以到达任何节点,则输出 1,否则输出 -1。

输入示例

4 4
1 2
2 1
1 3
2 4

输出示例

1

提示信息

从 1 号节点可以到达任意节点,输出 1。

数据范围:

1 <= N <= 100;
1 <= K <= 2000。

思路:

深搜法,如果节点1可以到达节点2,继续看节点2能否到达其他节点,如果节点2能到达其他节点,说明节点1也可以到达这些节点,将这些节点都标记为true。最后遍历所有节点是否都标记为true,如果是的话输出1,否则输出-1。

代码如下:

import java.util.*;public class Main{public static void main(String[] args){Scanner in=new Scanner(System.in);int n=in.nextInt();int k=in.nextInt();int[][] graph=new int[n+1][n+1];for(int i=0;i<k;i++){int x=in.nextInt();int y=in.nextInt();graph[x][y]=1;}boolean[] visited=new boolean[n+1];visited[1]=true;dfs(graph,visited,1,n);for(int i=1;i<=n;i++){if(visited[i]==false){System.out.println(-1);return;}}System.out.println(1);}public static void dfs(int[][] graph,boolean[] visited,int x,int n){for(int j=1;j<=n;j++){if(graph[x][j]==1&&visited[j]==false){visited[j]=true;dfs(graph,visited,j,n);}}}
}

其实深搜广搜的难度并不在广搜深搜本身,而是如何应用深搜广搜去解决问题,要想明白这个逻辑。

http://www.xdnf.cn/news/18189.html

相关文章:

  • MFC中使用EXCEL的方法之一
  • UDI数据库应用之后端本地数据库搭建实战(二)
  • 【高并发内存池】一、简介 定长内存池实现
  • 156-基于Flask的北京市商铺数据可视化分析系统
  • k8sday11服务发现(2/2)
  • 微服务如何集成swagger3
  • 工业相机基本知识解读:像元、帧率、数据接口等
  • 解决linux中磁盘爆满(准确说是文件系统爆满)导致mysql启动失败的问题——对文件系统进行扩容
  • 微信小程序实现蓝牙开启自动播放BGM
  • Git#revert
  • Ansible 角色管理指南
  • UART串口通信编程自学笔记30000字,嵌入式编程,STM32,C语言
  • 【Linux仓库】进程创建与进程终止【进程·柒】
  • 第八十三章:实战篇:文 → 图:Prompt 控制图像生成系统构建——从“咒语”到“神作”的炼成!
  • 数据结构——单链表
  • STL库——string(类模拟实现)
  • 【PHP】模拟斗地主后端编写
  • Redis--day8--黑马点评--分布式锁(一)
  • electron 开发笔记
  • 拓扑排序详解:从力扣 207 题看有向图环检测
  • 第一阶段C#-14:委托,事件
  • 【牛客刷题】最大公约数与最小公倍数:算法详解与实现
  • 一个基于纯前端技术实现的五子棋游戏,无需后端服务,直接在浏览器中运行。
  • Leetcode 3649. Number of Perfect Pairs
  • 面向R语言用户的Highcharts
  • 浅谈 Python 正则表达式中的 groups()
  • SpringBoot3整合OpenAPI3(Swagger3)完整指南
  • 【Python】Python 多进程与多线程:从原理到实践
  • Nodejs学习
  • CPTS---Active 复现