Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit c910803

Browse files
添加 卡码网0103.水流问题 JS版
1 parent eea315e commit c910803

File tree

1 file changed

+344
-0
lines changed

1 file changed

+344
-0
lines changed

‎problems/kamacoder/0103.水流问题.md‎

Lines changed: 344 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,350 @@ public class Main {
362362

363363
### Javascript
364364

365+
#### 深搜
366+
367+
```javascript
368+
const r1 = require('readline').createInterface({ input: process.stdin });
369+
// 创建readline接口
370+
let iter = r1[Symbol.asyncIterator]();
371+
// 创建异步迭代器
372+
const readline = async () => (await iter.next()).value;
373+
374+
let graph // 地图
375+
let N, M // 地图大小
376+
const dir = [[0, 1], [1, 0], [0, -1], [-1, 0]] //方向
377+
378+
379+
// 读取输入,初始化地图
380+
const initGraph = async () => {
381+
let line = await readline();
382+
[N, M] = line.split(' ').map(Number);
383+
graph = new Array(N).fill(0).map(() => new Array(M).fill(0))
384+
385+
for (let i = 0; i < N; i++) {
386+
line = await readline()
387+
line = line.split(' ').map(Number)
388+
for (let j = 0; j < M; j++) {
389+
graph[i][j] = line[j]
390+
}
391+
}
392+
}
393+
394+
395+
/**
396+
* @description: 从(x,y)开始深度优先遍历地图
397+
* @param {*} graph 地图
398+
* @param {*} visited 可访问节点
399+
* @param {*} x 开始搜索节点的下标
400+
* @param {*} y 开始搜索节点的下标
401+
* @return {*}
402+
*/
403+
const dfs = (graph, visited, x, y) => {
404+
if (visited[x][y]) return
405+
visited[x][y] = true // 标记为可访问
406+
407+
for (let i = 0; i < 4; i++) {
408+
let nextx = x + dir[i][0]
409+
let nexty = y + dir[i][1]
410+
if (nextx < 0 || nextx >= N || nexty < 0 || nexty >= M) continue //越界,跳过
411+
if (graph[x][y] < graph[nextx][nexty]) continue //不能流过.跳过
412+
dfs(graph, visited, nextx, nexty)
413+
}
414+
}
415+
416+
417+
/**
418+
* @description: 判断地图上的(x, y)是否可以到达第一组边界和第二组边界
419+
* @param {*} x 坐标
420+
* @param {*} y 坐标
421+
* @return {*} true可以到达,false不可以到达
422+
*/
423+
const isResult = (x, y) => {
424+
let visited = new Array(N).fill(false).map(() => new Array(M).fill(false))
425+
426+
let isFirst = false //是否可到达第一边界
427+
let isSecond = false //是否可到达第二边界
428+
429+
// 深搜,将(x, y)可到达的所有节点做标记
430+
dfs(graph, visited, x, y)
431+
432+
// 判断能否到第一边界左边
433+
for (let i = 0; i < N; i++) {
434+
if (visited[i][0]) {
435+
isFirst = true
436+
break
437+
}
438+
}
439+
440+
// 判断能否到第一边界上边
441+
for (let j = 0; j < M; j++) {
442+
if (visited[0][j]) {
443+
isFirst = true
444+
break
445+
}
446+
}
447+
448+
// 判断能否到第二边界右边
449+
for (let i = 0; i < N; i++) {
450+
if (visited[i][M - 1]) {
451+
isSecond = true
452+
break
453+
}
454+
}
455+
456+
// 判断能否到第二边界下边
457+
for (let j = 0; j < M; j++) {
458+
if (visited[N - 1][j]) {
459+
isSecond = true
460+
break
461+
}
462+
}
463+
464+
return isFirst && isSecond
465+
}
466+
467+
(async function () {
468+
469+
// 读取输入,初始化地图
470+
await initGraph()
471+
472+
// 遍历地图,判断是否能到达第一组边界和第二组边界
473+
for (let i = 0; i < N; i++) {
474+
for (let j = 0; j < M; j++) {
475+
if (isResult(i, j)) console.log(i + ' ' + j);
476+
}
477+
}
478+
})()
479+
```
480+
481+
482+
483+
#### 广搜-解法一
484+
485+
```java
486+
const r1 = require('readline').createInterface({ input: process.stdin });
487+
// 创建readline接口
488+
let iter = r1[Symbol.asyncIterator]();
489+
// 创建异步迭代器
490+
const readline = async () => (await iter.next()).value;
491+
492+
let graph // 地图
493+
let N, M // 地图大小
494+
const dir = [[0, 1], [1, 0], [0, -1], [-1, 0]] //方向
495+
496+
497+
// 读取输入,初始化地图
498+
const initGraph = async () => {
499+
let line = await readline();
500+
[N, M] = line.split(' ').map(Number);
501+
graph = new Array(N).fill(0).map(() => new Array(M).fill(0))
502+
503+
for (let i = 0; i < N; i++) {
504+
line = await readline()
505+
line = line.split(' ').map(Number)
506+
for (let j = 0; j < M; j++) {
507+
graph[i][j] = line[j]
508+
}
509+
}
510+
}
511+
512+
513+
/**
514+
* @description: 从(x,y)开始广度优先遍历地图
515+
* @param {*} graph 地图
516+
* @param {*} visited 可访问节点
517+
* @param {*} x 开始搜索节点的下标
518+
* @param {*} y 开始搜索节点的下标
519+
* @return {*}
520+
*/
521+
const bfs = (graph, visited, x, y) => {
522+
let queue = []
523+
queue.push([x, y])
524+
visited[x][y] = true
525+
526+
while (queue.length) {
527+
const [xx, yy] = queue.shift()
528+
for (let i = 0; i < 4; i++) {
529+
let nextx = xx + dir[i][0]
530+
let nexty = yy + dir[i][1]
531+
if (nextx < 0 || nextx >= N || nexty < 0 || nexty >= M) continue //越界, 跳过
532+
533+
// 可访问或者不能流过, 跳过 (注意这里是graph[xx][yy] < graph[nextx][nexty], 不是graph[x][y] < graph[nextx][nexty])
534+
if (visited[nextx][nexty] || graph[xx][yy] < graph[nextx][nexty]) continue
535+
536+
queue.push([nextx, nexty])
537+
visited[nextx][nexty] = true
538+
539+
}
540+
}
541+
}
542+
543+
544+
/**
545+
* @description: 判断地图上的(x, y)是否可以到达第一组边界和第二组边界
546+
* @param {*} x 坐标
547+
* @param {*} y 坐标
548+
* @return {*} true可以到达,false不可以到达
549+
*/
550+
const isResult = (x, y) => {
551+
let visited = new Array(N).fill(false).map(() => new Array(M).fill(false))
552+
553+
let isFirst = false //是否可到达第一边界
554+
let isSecond = false //是否可到达第二边界
555+
556+
// 深搜,将(x, y)可到达的所有节点做标记
557+
bfs(graph, visited, x, y)
558+
559+
// console.log(visited);
560+
561+
// 判断能否到第一边界左边
562+
for (let i = 0; i < N; i++) {
563+
if (visited[i][0]) {
564+
isFirst = true
565+
break
566+
}
567+
}
568+
569+
// 判断能否到第一边界上边
570+
for (let j = 0; j < M; j++) {
571+
if (visited[0][j]) {
572+
isFirst = true
573+
break
574+
}
575+
}
576+
577+
// 判断能否到第二边界右边
578+
for (let i = 0; i < N; i++) {
579+
if (visited[i][M - 1]) {
580+
isSecond = true
581+
break
582+
}
583+
}
584+
585+
// 判断能否到第二边界下边
586+
for (let j = 0; j < M; j++) {
587+
if (visited[N - 1][j]) {
588+
isSecond = true
589+
break
590+
}
591+
}
592+
593+
return isFirst && isSecond
594+
}
595+
596+
(async function () {
597+
598+
// 读取输入,初始化地图
599+
await initGraph()
600+
601+
// 遍历地图,判断是否能到达第一组边界和第二组边界
602+
for (let i = 0; i < N; i++) {
603+
for (let j = 0; j < M; j++) {
604+
if (isResult(i, j)) console.log(i + ' ' + j);
605+
}
606+
}
607+
})()
608+
```
609+
610+
611+
612+
#### 广搜-解法二
613+
614+
从第一边界和第二边界开始向高处流, 标记可以流到的位置, 两个边界都能到达的位置就是所求结果
615+
616+
```javascript
617+
const r1 = require('readline').createInterface({ input: process.stdin });
618+
// 创建readline接口
619+
let iter = r1[Symbol.asyncIterator]();
620+
// 创建异步迭代器
621+
const readline = async () => (await iter.next()).value;
622+
623+
let graph // 地图
624+
let N, M // 地图大小
625+
const dir = [[0, 1], [1, 0], [0, -1], [-1, 0]] //方向
626+
627+
628+
// 读取输入,初始化地图
629+
const initGraph = async () => {
630+
let line = await readline();
631+
[N, M] = line.split(' ').map(Number);
632+
graph = new Array(N).fill(0).map(() => new Array(M).fill(0))
633+
634+
for (let i = 0; i < N; i++) {
635+
line = await readline()
636+
line = line.split(' ').map(Number)
637+
for (let j = 0; j < M; j++) {
638+
graph[i][j] = line[j]
639+
}
640+
}
641+
}
642+
643+
644+
/**
645+
* @description: 从(x,y)开始广度优先遍历地图
646+
* @param {*} graph 地图
647+
* @param {*} visited 可访问节点
648+
* @param {*} x 开始搜索节点的下标
649+
* @param {*} y 开始搜索节点的下标
650+
* @return {*}
651+
*/
652+
const bfs = (graph, visited, x, y) => {
653+
if(visited[x][y]) return
654+
655+
let queue = []
656+
queue.push([x, y])
657+
visited[x][y] = true
658+
659+
while (queue.length) {
660+
const [xx, yy] = queue.shift()
661+
for (let i = 0; i < 4; i++) {
662+
let nextx = xx + dir[i][0]
663+
let nexty = yy + dir[i][1]
664+
if (nextx < 0 || nextx >= N || nexty < 0 || nexty >= M) continue //越界, 跳过
665+
666+
// 可访问或者不能流过, 跳过 (注意因为是从边界往高处流, 所以这里是graph[xx][yy] >= graph[nextx][nexty], 还要注意不是graph[xx][yy] >= graph[nextx][nexty])
667+
if (visited[nextx][nexty] || graph[xx][yy] >= graph[nextx][nexty]) continue
668+
669+
queue.push([nextx, nexty])
670+
visited[nextx][nexty] = true
671+
}
672+
}
673+
}
674+
675+
(async function () {
676+
677+
// 读取输入,初始化地图
678+
await initGraph()
679+
680+
// 记录第一边界可到达的节点
681+
let firstBorder = new Array(N).fill(false).map(() => new Array(M).fill(false))
682+
683+
// 记录第二边界可到达的节点
684+
let secondBorder = new Array(N).fill(false).map(() => new Array(M).fill(false))
685+
686+
// 第一边界左边和第二边界右边
687+
for (let i = 0; i < N; i++) {
688+
bfs(graph, firstBorder, i, 0)
689+
bfs(graph, secondBorder, i, M - 1)
690+
}
691+
692+
// 第一边界上边和第二边界下边
693+
for (let j = 0; j < M; j++) {
694+
bfs(graph, firstBorder, 0, j)
695+
bfs(graph, secondBorder, N - 1, j)
696+
}
697+
698+
// 遍历地图,判断是否能到达第一组边界和第二组边界
699+
for (let i = 0; i < N; i++) {
700+
for (let j = 0; j < M; j++) {
701+
if (firstBorder[i][j] && secondBorder[i][j]) console.log(i + ' ' + j);
702+
}
703+
}
704+
})()
705+
```
706+
707+
708+
365709
### TypeScript
366710

367711
### PhP

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /