水流问题[图搜索优化]

学习要点

  1. 图的搜索优化

题目链接

103. 水流问题

题目描述

解法:时间超限。但是解法是正确的

cpp 复制代码
#include <bits/stdc++.h>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;

int dir[4][2] = {0, 1, 1, 0, -1, 0, 0, -1};
bool first_line = false;
bool second_kine = false;
void dfs(vector<vector<int>> &grid,vector<vector<bool>>& visits, int x, int y) {
    visits[x][y] = true;
  // 要注意环的问题
    if(x == 0 || y == 0)
    {
        first_line = true;
    }
    if(x == grid.size() - 1 || y == grid[0].size() - 1)
    {
        second_kine = true;
    }
    if(first_line == true && second_kine == true)
    {
        return;
    }

    // queue<pair<int,int>> que_equ;
  for (int i = 0; i < 4; i++) {
    int next_x = x + dir[i][0];
    int next_y = y + dir[i][1];
    // 越界
    if (next_x < 0 || next_y < 0 || next_x >= grid.size() ||
        next_y >= grid[0].size())
    {
        continue;
    }
    // 不可走
    if(grid[x][y] < grid[next_x][next_y])
    {
        continue;
    }
    // 已经走过此路,也许还未走完
    if(visits[next_x][next_y])
    {
        continue;
    }
    if(grid[x][y] >= grid[next_x][next_y])
    {
        dfs(grid,visits,next_x,next_y);
    }
    
  }
}

int main() {
  int n, m;
  cin >> n >> m;
  vector<vector<int>> grid(n, vector<int>(m, 0));
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      cin >> grid[i][j];
    //   cout << grid[i][j];
    }
  }

  vector<vector<bool>> visits(n,vector<bool>(m,false));
  vector<vector<bool>> tmp_visits(n,vector<bool>(m,false));
  vector<pair<int,int>> ret_v;
  for(int i = 0;i<n;i++)
  {
    for(int j = 0; j<m; j++)
    {
        // 回位
        visits = tmp_visits; 
        first_line = false;
        second_kine = false;
        dfs(grid,visits,i,j);
        if(first_line == true && second_kine == true)
        {
            ret_v.push_back({i,j});
        }
    }
  }
  for(auto& i_pair: ret_v)
  {
    cout << i_pair.first << ' ' << i_pair.second << endl;
  }
}

解法:时间还是超限,快一点了

cpp 复制代码
#include <bits/stdc++.h>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;

int dir[4][2] = {0, 1, 1, 0, -1, 0, 0, -1};
bool first_line = false;
bool second_kine = false;
void dfs(vector<vector<int>> &grid,vector<vector<bool>>& visits, vector<vector<bool>>& mem_v, int x, int y) {

    if(mem_v[x][y] == true)
    {
        first_line = true;second_kine = true;
        return;
    }

    visits[x][y] = true;
  // 要注意环的问题
    if(x == 0 || y == 0)
    {
        first_line = true;
    }
    if(x == grid.size() - 1 || y == grid[0].size() - 1)
    {
        second_kine = true;
    }
    if(first_line == true && second_kine == true)
    {
        return;
    }

    // queue<pair<int,int>> que_equ;
  for (int i = 0; i < 4; i++) {
    int next_x = x + dir[i][0];
    int next_y = y + dir[i][1];
    // 越界
    if (next_x < 0 || next_y < 0 || next_x >= grid.size() ||
        next_y >= grid[0].size())
    {
        continue;
    }
    // 不可走
    if(grid[x][y] < grid[next_x][next_y])
    {
        continue;
    }
    // 已经走过此路,也许还未走完
    if(visits[next_x][next_y])
    {
        continue;
    }
    if(grid[x][y] >= grid[next_x][next_y])
    {
        dfs(grid,visits,mem_v,next_x,next_y);
        if(first_line == true && second_kine == true)
        {
            return;
        }
    }
    
  }
}


int main() {
  int n, m;
  cin >> n >> m;
  vector<vector<int>> grid(n, vector<int>(m, 0));
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      cin >> grid[i][j];
    //   cout << grid[i][j];
    }
  }
    vector<vector<bool>> mem_v(n,vector<bool>(m,false));
  vector<vector<bool>> visits(n,vector<bool>(m,false));
  vector<vector<bool>> tmp_visits(n,vector<bool>(m,false));
  vector<pair<int,int>> ret_v;
  for(int i = 0;i<n;i++)
  {
    for(int j = 0; j<m; j++)
    {
        if(i>0 && j>0 && grid[i][j] >= grid[i-1][j] && mem_v[i-1][j] == true)
        {
           ret_v.push_back({i,j});
            mem_v[i][j] = true;
            continue; 
        }
        if(i>0 && j>0 && grid[i][j] >= grid[i][j-1] && mem_v[i][j-1] == true)
        {
           ret_v.push_back({i,j});
            mem_v[i][j] = true;
            continue; 
        }


        // 回位
        visits = tmp_visits;
        first_line = false;
        second_kine = false;
        dfs(grid,visits,mem_v,i,j);
        if(first_line == true && second_kine == true)
        {
            ret_v.push_back({i,j});
            mem_v[i][j] = true;
        }
    }
  }
  for(auto& i_pair: ret_v)
  {
    cout << i_pair.first << ' ' << i_pair.second << endl;
  }
}

解法:逆向

cpp 复制代码
#include <iostream>
#include <vector>
using namespace std;
int n, m;
int dir[4][2] = {-1, 0, 0, -1, 1, 0, 0, 1};

void dfs(vector<vector<int>>& grid,vector<vector<bool>>& visits,int x, int y)
{
    visits[x][y] = true;
    for(int i = 0;i<4;i++)
    {
        int next_x = x + dir[i][0];
        int next_y = y + dir[i][1];
        if(next_x < 0 || next_y < 0 || next_x >= grid.size() || next_y >= grid[0].size())
        {
            continue;
        }
        if(grid[x][y] > grid[next_x][next_y])
        {
            continue;
        }
        if(visits[next_x][next_y] == true)
        {
            continue;
        }
        dfs(grid,visits,next_x,next_y);
    }
}

int main() {

    cin >> n >> m;
    vector<vector<int>> grid(n, vector<int>(m, 0));

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cin >> grid[i][j];
        }
    }

    vector<vector<bool>> firstBorder(n, vector<bool>(m, false));
    vector<vector<bool>> secondBorder(n, vector<bool>(m, false));

    for(int i = 0; i<n; i++)
    {
        if(firstBorder[i][0] == true)
            continue;
        dfs(grid,firstBorder,i,0);
    }
    for(int i = 0; i<m;i++)
    {
        if(firstBorder[0][i] == true)
            continue;
        dfs(grid,firstBorder,0,i);
    }

    for(int i = 0; i<m; i++)
    {
        if(secondBorder[n-1][i] == true)
            continue;
        dfs(grid,secondBorder,n-1,i);
    }
    for(int i = 0; i<n; i++)
    {
        if(secondBorder[i][m-1] == true)
            continue;
        dfs(grid,secondBorder,i,m-1);
    }

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            // 如果这个节点,从第一组边界和第二组边界出发都遍历过,就是结果
            if (firstBorder[i][j] && secondBorder[i][j]) cout << i << " " << j << endl;;
        }
    }

}
相关推荐
不会就选b4 小时前
算法日常・每日刷题--<贪心>25
数据结构·算法
千里码aicood7 小时前
基于CART算法的图书分类系统设计与实现
数据库·算法·分类
做cv的小昊8 小时前
【World Model】π0.5:a Vision-Language-Action Model with Open-World Generalization
人工智能·算法·机器学习·大模型·多模态·vla·世界模型
لا معنى له8 小时前
World-In-World: World Models in a Closed-Loop World
算法
Discipline102910 小时前
尼泊尔河流流量:天气驱动的预测与高流量风险
人工智能·算法
XuCoder10 小时前
改一个数,右边全得重算,这题怎么扛住两万次查询
算法
小羊没烦恼!11 小时前
在Scrum中实施敏捷建模
java·开发语言·windows·算法·c#
weixin_3077791311 小时前
基于睿擎工业开发平台的预训练视觉模型轻量化适配与低代码部署优化
开发语言·算法
hold?fish:palm11 小时前
45 二叉树的右视图
开发语言·c++·算法