using
System;
using
System.Collections.Generic;
class
Program
{
static
int
ShortestPathLessThanK(List<List<
int
>> mat,
int
K, List<
int
> src, List<
int
> dest)
{
int
N = mat.Count;
int
M = mat[0].Count;
int
[][] dist =
new
int
[N][];
for
(
int
i = 0; i < N; i++)
{
dist[i] =
new
int
[M];
for
(
int
j = 0; j < M; j++)
{
dist[i][j] =
int
.MaxValue;
}
}
dist[src[0]][src[1]] = 0;
var
pq =
new
PriorityQueue<
int
[]>(
(a, b) => a[0].CompareTo(b[0])
);
pq.Enqueue(
new
int
[] { 0, src[0], src[1], mat[src[0]][src[1]] });
int
[][] dir = {
new
int
[] { -1, 0 },
new
int
[] { 1, 0 },
new
int
[] { 0, 1 },
new
int
[] { 0, -1 } };
while
(pq.Count > 0)
{
int
[] curr = pq.Dequeue();
int
curr_dist = curr[0];
int
curr_i = curr[1];
int
curr_j = curr[2];
int
curr_val = curr[3];
if
(curr_i == dest[0] && curr_j == dest[1])
{
return
curr_dist;
}
foreach
(
var
d
in
dir)
{
int
i = curr_i + d[0];
int
j = curr_j + d[1];
if
(i < 0 || i >= N || j < 0 || j >= M)
{
continue
;
}
int
neighbor_val = mat[i][j];
if
(Math.Abs(neighbor_val - curr_val) <= K)
{
int
neighbor_dist = curr_dist + 1;
if
(neighbor_dist < dist[i][j])
{
dist[i][j] = neighbor_dist;
pq.Enqueue(
new
int
[] { neighbor_dist, i, j, neighbor_val });
}
}
}
}
return
-1;
}
static
void
Main(
string
[] args)
{
List<List<
int
>> mat =
new
List<List<
int
>>
{
new
List<
int
> { -1, 0, 4, 3 },
new
List<
int
> { 6, 5, 7, 8 },
new
List<
int
> { 2, 1, 2, 0 }
};
int
k = 4;
List<
int
> src =
new
List<
int
> { 0, 0 };
List<
int
> dest =
new
List<
int
> { 2, 3 };
Console.WriteLine(ShortestPathLessThanK(mat, k, src, dest));
}
}
class
PriorityQueue<T>
{
private
List<T> data;
private
Comparison<T> comparison;
public
PriorityQueue(Comparison<T> comparison)
{
this
.comparison = comparison;
this
.data =
new
List<T>();
}
public
void
Enqueue(T item)
{
data.Add(item);
int
childIndex = data.Count - 1;
while
(childIndex > 0)
{
int
parentIndex = (childIndex - 1) / 2;
if
(comparison(data[childIndex], data[parentIndex]) >= 0)
break
;
T tmp = data[childIndex];
data[childIndex] = data[parentIndex];
data[parentIndex] = tmp;
childIndex = parentIndex;
}
}
public
T Dequeue()
{
int
lastIndex = data.Count - 1;
T frontItem = data[0];
data[0] = data[lastIndex];
data.RemoveAt(lastIndex);
--lastIndex;
int
parentIndex = 0;
while
(
true
)
{
int
leftChildIndex = parentIndex * 2 + 1;
if
(leftChildIndex > lastIndex)
break
;
int
rightChildIndex = leftChildIndex + 1;
if
(rightChildIndex <= lastIndex && comparison(data[rightChildIndex], data[leftChildIndex]) < 0)
leftChildIndex = rightChildIndex;
if
(comparison(data[parentIndex], data[leftChildIndex]) <= 0)
break
;
T tmp = data[parentIndex];
data[parentIndex] = data[leftChildIndex];
data[leftChildIndex] = tmp;
parentIndex = leftChildIndex;
}
return
frontItem;
}
public
int
Count
{
get
{
return
data.Count; }
}
}