算法竞赛入门经典 习题6-5

UVa1600

Patrol Robot

在长宽分别为mn的矩形区域中,有些格子存在障碍物,机器人可以连续穿过k个障碍物,求从矩形左上角到右下角的最短路径长度。

最短路径长度可以使用广搜求解。这道题不同的地方在于机器人可以连续穿过k个障碍物,所以在广搜扩展时还应该记录机器人还能连续穿过多少个障碍物。

然后uDebug上有几个测试用例过不了,感觉应该是记录格子是否访问过的逻辑有错误。想了一下,正确的逻辑应该是记录机器人到达这个格子时还能连续穿过障碍物的数量,并使该值尽可能的大。

#include <iostream>
#include <array>
#include <deque>
#include <vector>

using namespace std;

struct Node
{
	int i, j;
	int k;
	int step;
	Node(int i, int j, int k, int step) : i(i), j(j), k(k), step(step) {}
};

class Solution
{
public:
	Solution(const vector<vector<char>> &grid, int m, int n, int k) : length(-1)
	{
		vector<vector<int>> visited(grid.size(), vector<int>(grid[0].size(), -1));
		const vector<array<int, 2>> directions = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };
		deque<Node> deq;
		deq.emplace_back(0, 0, k, 0);
		visited[0][0] = k;
		while (!deq.empty()) {
			Node curr = deq.front();
			deq.pop_front();
			if (curr.i == m - 1 && curr.j == n - 1) {
				length = curr.step;
				break;
			}
			for (const array<int, 2> &direction : directions)
			{
				Node next{ curr.i + direction[0], curr.j + direction[1], curr.k, curr.step + 1 };
				if (0 <= next.i && next.i < m && 0 <= next.j && next.j < n) {
					if (grid[next.i][next.j] == '0') {
						next.k = k;
					}
					else {
						next.k--;
						if (next.k < 0) continue;
					}
					if (visited[next.i][next.j] == -1 || visited[next.i][next.j] < next.k) {
						visited[next.i][next.j] = next.k;
						deq.push_back(next);
					}
				}
			}
		}
	}
	int FindShortestPathLength()
	{
		return length;
	}
private:
	int length;
};

int main()
{
	int cases = 0;
	cin >> cases;
	for (int c = 0; c < cases; c++)
	{
		int m, n, k;
		cin >> m >> n >> k;
		vector<vector<char>> grid(m, vector<char>(n, false));
		for (int i = 0; i < m; i++)
		{
			for (int j = 0; j < n; j++)
			{
				cin >> grid[i][j];
			}
		}
		Solution solution(grid, m, n, k);
		cout << solution.FindShortestPathLength() << endl;
	}
	return 0;
}
/*
3
2 5
0
0 1 0 0 0
0 0 0 1 0
4 6
1
0 1 1 0 0 0
0 0 1 0 1 1
0 1 1 1 1 0
0 1 1 1 0 0
2 2
0
0 1
1 0
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值