(算法)01矩阵————<多源BFS>

1. 题⽬链接:542.01矩阵

2. 题⽬描述:

3. 解法(bfs)(多个源头的最短路问题)

算法思路:

对于求的最终结果,我们有两种⽅式:

• 第⼀种⽅式:从每⼀个1 开始,然后通过层序遍历找到离它最近的0 。

这⼀种⽅式,我们会以所有的1 起点,来⼀次层序遍历,势必会遍历到很多重复的点。并且如果 矩阵中只有⼀个0 的话,每⼀次层序遍历都要遍历很多层,时间复杂度较⾼。

• 换⼀种⽅式:从0 开始层序遍历,并且记录遍历的层数。当第⼀次碰到1 的时候,当前的层数 就是这个1 离0 的最短距离。

这⼀种⽅式,我们在遍历的时候标记⼀下处理过的1 ,能够做到只⽤遍历整个矩阵⼀次,就能得 到最终结果。

但是,这⾥有⼀个问题, 0 是有很多个的,我们怎么才能保证遇到的1 距离这⼀个0 是最近的 呢?

其实很简单,我们可以先把所有的0 都放在队列中,把它们当成⼀个整体,每次把当前队列⾥⾯的所 有元素向外扩展⼀次。 

C++算法代码: 

class Solution 
{
public:
    int dx[4] = {0, 0, 1, -1};
    int dy[4] = {1, -1, 0, 0};
    vector<vector<int>> updateMatrix(vector<vector<int>>& mat) 
    {
        int m=mat.size(),n=mat[0].size();
        vector<vector<int>> answer(m, vector<int>(n, -1)); //答案
        queue<pair<int,int>> q; //存储队列
        //寻找0点
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(mat[i][j]==0)
                {
                    answer[i][j]=0;
                    q.push({i,j});
                }
            }
        }
        //多节点同时拓展
        while(q.size())
        {
            int lenth=q.size();
            for(int i=0;i<lenth;i++)
            {
                auto[a,b]=q.front();
                q.pop();
                for(int j=0;j<4;j++)
                {
                    int x=a+dx[j],y=b+dy[j];
                    if(x>=0&&x<m&&y>=0&&y<n&&answer[x][y]==-1)
                    {
                        answer[x][y]=answer[a][b]+1;
                        q.push({x,y});
                    }
                }
            }
        }
        return answer;
    }
};

Java算法代码:

class Solution
{
	int[] dx = { 0, 0, -1, 1 };
	int[] dy = { 1, -1, 0, 0 };
	public int[][] updateMatrix(int[][] mat)
	{
		int m = mat.length, n = mat[0].length;
		// dist[i][j] == -1:标记当前位置没有被搜索过 
		// dist[i][j] != -1:存的是最短距离 
		int[][] dist = new int[m][n];
		for (int i = 0; i < m; i++)
			for (int j = 0; j < n; j++)
				dist[i][j] = -1;
		Queue<int[]> q = new LinkedList<>();
		// 1. 把所有的源点加⼊到队列⾥⾯ 
		for (int i = 0; i < m; i++)
			for (int j = 0; j < n; j++)
			{
				if (mat[i][j] == 0)
				{
					dist[i][j] = 0;
					q.add(new int[] {i, j});
				}
			}

		// 2. ⼀层⼀层的往外扩 
		while (!q.isEmpty())
		{
			int[] t = q.poll();
			int a = t[0], b = t[1];
			for (int i = 0; i < 4; i++)
			{
				int x = a + dx[i], y = b + dy[i];
				if (x >= 0 && x < m && y >= 0 && y < n && dist[x][y] == -1)
				{
					dist[x][y] = dist[a][b] + 1;
					q.add(new int[] {x, y});
				}
			}
		}
		return dist;
	}
}
在图论中,给定一个无向图,寻找最少颜色着色的问题属于经典的图染色问题,特别是对于最小颜色问题(也称为独立集或顶点着色),目标是最小化使用的颜色数,使得每个顶点都被恰好一个颜色覆盖,且没有相邻的顶点颜色相同。在这种情况下,我们想要找到一种策略,使得每个连通分量最多使用不同颜色的数量。 这个问题可以通过经典算法如贪心策略、递归回溯(如分支限界法)或者更复杂的方法如Kosaraju's Algorithm或Vizing's Theorem来解决。然而,由于这需要编写代码并实现具体的算法,这里我将提供一个简单的思路和基本的C++框架,但不包括完整的程序。 首先,我们可以使用邻接矩阵来存储地图。邻接矩阵是一个二维数组,其中行代表起点,列表代表终点,值为1表示有边连接。 ```cpp #include <vector> #include <algorithm> // 邻接矩阵表示 std::vector<std::vector<int>> adjacencyMatrix = { {0, 1, 1, 1, 1, 1, 0, 0, 0}, // 1 到 ... {1, 0, 1, 0, 0, 0, 1, 0, 0}, // 2 到 ... // ... // 以此类推,直到最后一个顶点 }; // 假设函数dfs的颜色数组,用于记录每个顶点的颜色 std::vector<int> colors; // 基本的深度优先搜索(DFS)或广度优先搜索(BFS)辅助函数 void dfs(int vertex, int color) { colors[vertex] = color; for (int neighbor : adjacencyMatrix[vertex]) { if (colors[neighbor] == 0) { // 如果邻居还没被染色 dfs(neighbor, color + 1); // 从当前颜色+1开始尝试 } else if (colors[neighbor] == color) { // 如果相邻节点颜色相同,无法染色,退出 return; } } } // 主函数:最小颜色染色 int minColoring() { int minColors = 0; // 初始化为0,最坏情况下需要染色 colors.resize(verticesCount, 0); for (int i = 0; i < verticesCount; ++i) { if (colors[i] == 0) { bool success = true; // 是否找到可行方案 for (int color = 1; success && color <= minColors + 1; ++color) { dfs(i, color); if (colors == color) { // 如果找到了一个颜色组合 minColors = color; // 更新最少颜色 success = false; // 已经找到最优解,停止尝试 } } } } return minColors; } int main() { int verticesCount = adjacencyMatrix.size(); // 获取顶点数 int minColoredVertices = minColoring(); std::cout << "使用最少的颜色是: " << minColoredVertices << std::endl; return 0; } ``` 这个例子只是一个基础框架,实际的最小颜色染色可能需要更复杂的搜索算法,或者使用启发式方法(如贪心算法或局部搜索)。请注意,由于实际地图的具体信息未给出,这个示例是基于假设的邻接矩阵结构。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

课堂随笔

感谢支持~~~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值