HDU 2807 The Shortest Path

本文介绍了一种利用Floyd算法解决矩阵间有向边最短路径问题的方法。通过矩阵相乘判断两个节点间是否存在直接路径,并借助Floyd算法求得任意两点间的最短路径。

传送门

最短路。全源最短路,使用floyd

给你很多个矩阵,每个矩阵代表一个点,两点之间有一条有向边(A->C,权值为1)当且仅当A*B=C(矩阵运算),其中A,B,C代表不同的点。然后给很多个查询,每次问你从一个点到另一个点的最短路。

主要注意上述A,B,C指代不同的点。
矩阵相乘放在第二层循环得出结果,再和第三层枚举的每个矩阵比较。

话说刚刚看了一下别的题解,居然发现还有 快速矩阵比较 这种东西,能O(n)完成矩阵比较?。。太秀了

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <string>
using namespace std;

const int INF = 1e9;
const int MAX = 81;
int N, M, Q;
int mtx[MAX][MAX][MAX];
int d[MAX][MAX];                 // 邻接矩阵
int t[MAX][MAX];                 // 存储矩阵乘积的临时矩阵

void init()
{
	for (int i = 1; i <= N; i++)
	{
		for (int j = 1; j <= N; j++)
		{
			if (i != j) d[i][j] = INF;
			else d[i][j] = 0;                      // 使用邻接矩阵时这一步还是必要的,至少稳当
		}
	}
}

void mul(int a, int b)  // a*b=c
{
	int s;
	for (int i = 1; i <= M; i++)
	{
		for (int j = 1; j <= M; j++)
		{
			s = 0;
			for (int k = 1; k <= M; k++)
			{
				s += mtx[a][i][k] * mtx[b][k][j];
			}
			t[i][j] = s;
		}
	}
}

void floyd()
{
	for (int k = 1; k <= N; k++)
		for (int i = 1; i <= N; i++)
			for (int j = 1; j <= N; j++)
			{
				if(d[i][k] != INF && d[k][j] != INF && d[i][k] + d[k][j] < d[i][j])
				{
					d[i][j] = d[i][k] + d[k][j];
				}
			}
}

bool equal(int x)
{
	for (int i = 1; i <= M; i++)
	{
		for (int j = 1; j <= M; j++)
		{
			if (mtx[x][i][j] != t[i][j]) return false;
		}
	}
	return true;
}

int main()
{
	int a, b;
	for (; ~scanf("%d%d", &N, &M);)
	{
		if (!N && !M) break;
		init();
		for (int i = 1; i <= N; i++)
			for (int j = 1; j <= M; j++)
				for (int k = 1; k <= M; k++)
					scanf("%d", &mtx[i][j][k]);

		for (int i = 1; i <= N; i++)
		{
			for (int j = 1; j <= N; j++)
			{
				if (i == j) continue;            // 人家题目中说了A,B,C是三个城市,不能指代相同
				mul(i, j);                       // 把矩阵乘法放在第二层进行,不要放到第三层
				for (int k = 1; k <= N; k++)
				{
					if (k == i || d[i][k] == 1) continue;
					if (k == j) continue;        // 没加这个就 WA,看来里面有单位矩阵(A)
					                             // 按照题目规矩来,人家说了A,B,C是三个城市,这就意味着不能指代相同
					if (equal(k)) 
						d[i][k] = 1;
				}
			}
		}
		floyd();

		scanf("%d", &Q);
		for (; Q--;)
		{
			scanf("%d%d", &a, &b);
			if (d[a][b] == INF) printf("Sorry\n");
			else printf("%d\n", d[a][b]);
		}
	}

	return 0;
}
### HDU 1682 Problem Explanation and Solution HDU 1682 is titled "Find a way". This problem involves finding the shortest path in a grid with specific constraints. The grid contains obstacles, and the task is to determine the minimum number of steps required to reach the destination from the starting point while avoiding obstacles[^5]. #### Problem Description The input consists of multiple test cases. Each test case includes: - A grid size `N x M`. - A grid where each cell is either empty (denoted by '.') or blocked (denoted by '#'). - The starting position `(x1, y1)` and the destination position `(x2, y2)`. The goal is to find the shortest path from the start to the destination, moving only up, down, left, or right, and avoiding blocked cells. #### Approach This problem can be solved using **Breadth-First Search (BFS)**, which is ideal for finding the shortest path in an unweighted graph. BFS ensures that the first time a node is visited, it is reached via the shortest possible path from the source. Here is a step-by-step explanation of the algorithm: - Represent the grid as a 2D array. - Use a queue to store the current position and the number of steps taken to reach it. - Mark visited cells to avoid revisiting them. - Expand the search in all four directions (up, down, left, right) at each step. - If the destination is reached, output the number of steps. Otherwise, if no path exists, output -1. #### Implementation Below is a Python implementation of the solution: ```python from collections import deque def solve(): T = int(input()) # Number of test cases results = [] for _ in range(T): N, M = map(int, input().split()) # Grid dimensions grid = [input().strip() for _ in range(N)] x1, y1, x2, y2 = map(int, input().split()) # Start and end positions # Adjust for zero-based indexing x1 -= 1; y1 -= 1; x2 -= 1; y2 -= 1 # BFS Initialization queue = deque([(x1, y1, 0)]) # (current_x, current_y, steps) visited = [[False] * M for _ in range(N)] visited[x1][y1] = True # Directions: up, down, left, right directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] found = False while queue: cx, cy, steps = queue.popleft() if cx == x2 and cy == y2: results.append(steps) found = True break for dx, dy in directions: nx, ny = cx + dx, cy + dy if 0 <= nx < N and 0 <= ny < M and not visited[nx][ny] and grid[nx][ny] == '.': visited[nx][ny] = True queue.append((nx, ny, steps + 1)) if not found: results.append(-1) for result in results: print(result) # Example Input/Output # Input: # 1 # 3 3 # ... # .## # ... # 1 1 3 3 # Output: # 4 ``` #### Key Points - BFS guarantees the shortest path in an unweighted grid. - Visited cells are marked to prevent cycles and redundant computations. - The algorithm terminates early if the destination is reached.
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值