mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-06 23:28:29 +08:00
添加 卡码网0103.水流问题 JS版
This commit is contained in:
@ -362,6 +362,350 @@ public class Main {
|
||||
|
||||
### Javascript
|
||||
|
||||
#### 深搜
|
||||
|
||||
```javascript
|
||||
const r1 = require('readline').createInterface({ input: process.stdin });
|
||||
// 创建readline接口
|
||||
let iter = r1[Symbol.asyncIterator]();
|
||||
// 创建异步迭代器
|
||||
const readline = async () => (await iter.next()).value;
|
||||
|
||||
let graph // 地图
|
||||
let N, M // 地图大小
|
||||
const dir = [[0, 1], [1, 0], [0, -1], [-1, 0]] //方向
|
||||
|
||||
|
||||
// 读取输入,初始化地图
|
||||
const initGraph = async () => {
|
||||
let line = await readline();
|
||||
[N, M] = line.split(' ').map(Number);
|
||||
graph = new Array(N).fill(0).map(() => new Array(M).fill(0))
|
||||
|
||||
for (let i = 0; i < N; i++) {
|
||||
line = await readline()
|
||||
line = line.split(' ').map(Number)
|
||||
for (let j = 0; j < M; j++) {
|
||||
graph[i][j] = line[j]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @description: 从(x,y)开始深度优先遍历地图
|
||||
* @param {*} graph 地图
|
||||
* @param {*} visited 可访问节点
|
||||
* @param {*} x 开始搜索节点的下标
|
||||
* @param {*} y 开始搜索节点的下标
|
||||
* @return {*}
|
||||
*/
|
||||
const dfs = (graph, visited, x, y) => {
|
||||
if (visited[x][y]) return
|
||||
visited[x][y] = true // 标记为可访问
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
let nextx = x + dir[i][0]
|
||||
let nexty = y + dir[i][1]
|
||||
if (nextx < 0 || nextx >= N || nexty < 0 || nexty >= M) continue //越界,跳过
|
||||
if (graph[x][y] < graph[nextx][nexty]) continue //不能流过.跳过
|
||||
dfs(graph, visited, nextx, nexty)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @description: 判断地图上的(x, y)是否可以到达第一组边界和第二组边界
|
||||
* @param {*} x 坐标
|
||||
* @param {*} y 坐标
|
||||
* @return {*} true可以到达,false不可以到达
|
||||
*/
|
||||
const isResult = (x, y) => {
|
||||
let visited = new Array(N).fill(false).map(() => new Array(M).fill(false))
|
||||
|
||||
let isFirst = false //是否可到达第一边界
|
||||
let isSecond = false //是否可到达第二边界
|
||||
|
||||
// 深搜,将(x, y)可到达的所有节点做标记
|
||||
dfs(graph, visited, x, y)
|
||||
|
||||
// 判断能否到第一边界左边
|
||||
for (let i = 0; i < N; i++) {
|
||||
if (visited[i][0]) {
|
||||
isFirst = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// 判断能否到第一边界上边
|
||||
for (let j = 0; j < M; j++) {
|
||||
if (visited[0][j]) {
|
||||
isFirst = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// 判断能否到第二边界右边
|
||||
for (let i = 0; i < N; i++) {
|
||||
if (visited[i][M - 1]) {
|
||||
isSecond = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// 判断能否到第二边界下边
|
||||
for (let j = 0; j < M; j++) {
|
||||
if (visited[N - 1][j]) {
|
||||
isSecond = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return isFirst && isSecond
|
||||
}
|
||||
|
||||
(async function () {
|
||||
|
||||
// 读取输入,初始化地图
|
||||
await initGraph()
|
||||
|
||||
// 遍历地图,判断是否能到达第一组边界和第二组边界
|
||||
for (let i = 0; i < N; i++) {
|
||||
for (let j = 0; j < M; j++) {
|
||||
if (isResult(i, j)) console.log(i + ' ' + j);
|
||||
}
|
||||
}
|
||||
})()
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### 广搜-解法一
|
||||
|
||||
```java
|
||||
const r1 = require('readline').createInterface({ input: process.stdin });
|
||||
// 创建readline接口
|
||||
let iter = r1[Symbol.asyncIterator]();
|
||||
// 创建异步迭代器
|
||||
const readline = async () => (await iter.next()).value;
|
||||
|
||||
let graph // 地图
|
||||
let N, M // 地图大小
|
||||
const dir = [[0, 1], [1, 0], [0, -1], [-1, 0]] //方向
|
||||
|
||||
|
||||
// 读取输入,初始化地图
|
||||
const initGraph = async () => {
|
||||
let line = await readline();
|
||||
[N, M] = line.split(' ').map(Number);
|
||||
graph = new Array(N).fill(0).map(() => new Array(M).fill(0))
|
||||
|
||||
for (let i = 0; i < N; i++) {
|
||||
line = await readline()
|
||||
line = line.split(' ').map(Number)
|
||||
for (let j = 0; j < M; j++) {
|
||||
graph[i][j] = line[j]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @description: 从(x,y)开始广度优先遍历地图
|
||||
* @param {*} graph 地图
|
||||
* @param {*} visited 可访问节点
|
||||
* @param {*} x 开始搜索节点的下标
|
||||
* @param {*} y 开始搜索节点的下标
|
||||
* @return {*}
|
||||
*/
|
||||
const bfs = (graph, visited, x, y) => {
|
||||
let queue = []
|
||||
queue.push([x, y])
|
||||
visited[x][y] = true
|
||||
|
||||
while (queue.length) {
|
||||
const [xx, yy] = queue.shift()
|
||||
for (let i = 0; i < 4; i++) {
|
||||
let nextx = xx + dir[i][0]
|
||||
let nexty = yy + dir[i][1]
|
||||
if (nextx < 0 || nextx >= N || nexty < 0 || nexty >= M) continue //越界, 跳过
|
||||
|
||||
// 可访问或者不能流过, 跳过 (注意这里是graph[xx][yy] < graph[nextx][nexty], 不是graph[x][y] < graph[nextx][nexty])
|
||||
if (visited[nextx][nexty] || graph[xx][yy] < graph[nextx][nexty]) continue
|
||||
|
||||
queue.push([nextx, nexty])
|
||||
visited[nextx][nexty] = true
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @description: 判断地图上的(x, y)是否可以到达第一组边界和第二组边界
|
||||
* @param {*} x 坐标
|
||||
* @param {*} y 坐标
|
||||
* @return {*} true可以到达,false不可以到达
|
||||
*/
|
||||
const isResult = (x, y) => {
|
||||
let visited = new Array(N).fill(false).map(() => new Array(M).fill(false))
|
||||
|
||||
let isFirst = false //是否可到达第一边界
|
||||
let isSecond = false //是否可到达第二边界
|
||||
|
||||
// 深搜,将(x, y)可到达的所有节点做标记
|
||||
bfs(graph, visited, x, y)
|
||||
|
||||
// console.log(visited);
|
||||
|
||||
// 判断能否到第一边界左边
|
||||
for (let i = 0; i < N; i++) {
|
||||
if (visited[i][0]) {
|
||||
isFirst = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// 判断能否到第一边界上边
|
||||
for (let j = 0; j < M; j++) {
|
||||
if (visited[0][j]) {
|
||||
isFirst = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// 判断能否到第二边界右边
|
||||
for (let i = 0; i < N; i++) {
|
||||
if (visited[i][M - 1]) {
|
||||
isSecond = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// 判断能否到第二边界下边
|
||||
for (let j = 0; j < M; j++) {
|
||||
if (visited[N - 1][j]) {
|
||||
isSecond = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return isFirst && isSecond
|
||||
}
|
||||
|
||||
(async function () {
|
||||
|
||||
// 读取输入,初始化地图
|
||||
await initGraph()
|
||||
|
||||
// 遍历地图,判断是否能到达第一组边界和第二组边界
|
||||
for (let i = 0; i < N; i++) {
|
||||
for (let j = 0; j < M; j++) {
|
||||
if (isResult(i, j)) console.log(i + ' ' + j);
|
||||
}
|
||||
}
|
||||
})()
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### 广搜-解法二
|
||||
|
||||
从第一边界和第二边界开始向高处流, 标记可以流到的位置, 两个边界都能到达的位置就是所求结果
|
||||
|
||||
```javascript
|
||||
const r1 = require('readline').createInterface({ input: process.stdin });
|
||||
// 创建readline接口
|
||||
let iter = r1[Symbol.asyncIterator]();
|
||||
// 创建异步迭代器
|
||||
const readline = async () => (await iter.next()).value;
|
||||
|
||||
let graph // 地图
|
||||
let N, M // 地图大小
|
||||
const dir = [[0, 1], [1, 0], [0, -1], [-1, 0]] //方向
|
||||
|
||||
|
||||
// 读取输入,初始化地图
|
||||
const initGraph = async () => {
|
||||
let line = await readline();
|
||||
[N, M] = line.split(' ').map(Number);
|
||||
graph = new Array(N).fill(0).map(() => new Array(M).fill(0))
|
||||
|
||||
for (let i = 0; i < N; i++) {
|
||||
line = await readline()
|
||||
line = line.split(' ').map(Number)
|
||||
for (let j = 0; j < M; j++) {
|
||||
graph[i][j] = line[j]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @description: 从(x,y)开始广度优先遍历地图
|
||||
* @param {*} graph 地图
|
||||
* @param {*} visited 可访问节点
|
||||
* @param {*} x 开始搜索节点的下标
|
||||
* @param {*} y 开始搜索节点的下标
|
||||
* @return {*}
|
||||
*/
|
||||
const bfs = (graph, visited, x, y) => {
|
||||
if(visited[x][y]) return
|
||||
|
||||
let queue = []
|
||||
queue.push([x, y])
|
||||
visited[x][y] = true
|
||||
|
||||
while (queue.length) {
|
||||
const [xx, yy] = queue.shift()
|
||||
for (let i = 0; i < 4; i++) {
|
||||
let nextx = xx + dir[i][0]
|
||||
let nexty = yy + dir[i][1]
|
||||
if (nextx < 0 || nextx >= N || nexty < 0 || nexty >= M) continue //越界, 跳过
|
||||
|
||||
// 可访问或者不能流过, 跳过 (注意因为是从边界往高处流, 所以这里是graph[xx][yy] >= graph[nextx][nexty], 还要注意不是graph[xx][yy] >= graph[nextx][nexty])
|
||||
if (visited[nextx][nexty] || graph[xx][yy] >= graph[nextx][nexty]) continue
|
||||
|
||||
queue.push([nextx, nexty])
|
||||
visited[nextx][nexty] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(async function () {
|
||||
|
||||
// 读取输入,初始化地图
|
||||
await initGraph()
|
||||
|
||||
// 记录第一边界可到达的节点
|
||||
let firstBorder = new Array(N).fill(false).map(() => new Array(M).fill(false))
|
||||
|
||||
// 记录第二边界可到达的节点
|
||||
let secondBorder = new Array(N).fill(false).map(() => new Array(M).fill(false))
|
||||
|
||||
// 第一边界左边和第二边界右边
|
||||
for (let i = 0; i < N; i++) {
|
||||
bfs(graph, firstBorder, i, 0)
|
||||
bfs(graph, secondBorder, i, M - 1)
|
||||
}
|
||||
|
||||
// 第一边界上边和第二边界下边
|
||||
for (let j = 0; j < M; j++) {
|
||||
bfs(graph, firstBorder, 0, j)
|
||||
bfs(graph, secondBorder, N - 1, j)
|
||||
}
|
||||
|
||||
// 遍历地图,判断是否能到达第一组边界和第二组边界
|
||||
for (let i = 0; i < N; i++) {
|
||||
for (let j = 0; j < M; j++) {
|
||||
if (firstBorder[i][j] && secondBorder[i][j]) console.log(i + ' ' + j);
|
||||
}
|
||||
}
|
||||
})()
|
||||
```
|
||||
|
||||
|
||||
|
||||
### TypeScript
|
||||
|
||||
### PhP
|
||||
|
Reference in New Issue
Block a user