给定一个大小为N x M的矩阵,由整数1、2、3和4 组成。
每个值代表该单元格的可能移动:
1 -> move left
2 -> move right
3 -> move up
4 -> move down.
任务是找到矩阵中所需的最小可能变化,以便存在从(0, 0)到(N-1, M-1)的路径。
例子:
Input : mat[][] = {{2, 2, 4},
{1, 1, 1},
{3, 3, 2}};
Output : 1
Change the value of mat[1][2] to 4. So the sequence of moves will be
(0, 0) -> (0, 1) -> (0, 2) -> (1, 2) -> (2, 2)
Input : mat[][] = {{2, 2, 1},
{4, 2, 3},
{4, 3, 2}}
Output : 2
先决条件:
1. Djikstra 算法
2.0-1 BFS
方法一
- 让我们将二维矩阵的每个单元格视为加权图的一个节点,每个节点最多可以有四个连接的节点(可能有四个方向)。每条边的权重为:
- weight(U, V) = 0,如果节点U的运动方向指向V,否则
- 重量(U,V)= 1
- 现在,这基本上简化为最短路径问题,可以使用 Djikstra 算法计算
下面是上述方法的实现:
C++
// CPP program to find minimum possible
// changes required in the matrix
#include
using namespace std;
// Function to find next possible node
int nextNode(int x, int y, int dir, int N, int M)
{
if (dir == 1)
y--;
else if (dir == 2)
y++;
else if (dir == 3)
x--;
else
x++;
// If node is out of matrix
if (!(x >= 0 && x < N && y >= 0 && y < M))
return -1;
else
return (x * N + y);
}
// Prints shortest paths from src
// to all other vertices
int dijkstra(vector >* adj,
int src, int dest, int N, int M)
{
// Create a set to store vertices
// that are bein preprocessed
set > setds;
// Create a vector for distances
// and initialize all distances
// as infinite (large value)
vector dist(N * M, INT_MAX);
// Insert source itself in Set
// and initialize its distance as 0
setds.insert(make_pair(0, src));
dist[src] = 0;
/* Looping till all shortest
distance are finalized
then setds will become empty */
while (!setds.empty()) {
// The first vertex in Set
// is the minimum distance
// vertex, extract it from set.
pair tmp = *(setds.begin());
setds.erase(setds.begin());
// vertex label is stored in second
// of pair (it has to be done this
// way to keep the vertices sorted
// distance (distance must be
// first item in pair)
int u = tmp.second;
// 'i' is used to get all adjacent
// vertices of a vertex
vector >::iterator i;
for (i = adj[u].begin();
i != adj[u].end(); ++i) {
// Get vertex label and weight
// of current adjacent of u.
int v = (*i).first;
int weight = (*i).second;
// If there is shorter path from u to v
if (dist[v] > dist[u] + weight) {
// If distance of v is not
// INF then it must be
// in our set, so removing it
// and inserting again with
// updated less distance.
// Note : We extract only
// those vertices from Set
// for which distance is
// finalized. So for them,
// we would never reach here
if (dist[v] != INT_MAX)
setds.erase(setds.find(
{ dist[v], v }));
// Updating distance of v
dist[v] = dist[u] + weight;
setds.insert(make_pair(dist[v], v));
}
}
}
// Return the distance
return dist[dest];
}
// Function to find minimum possible
// changes required in the matrix
int MinModifications(vector >& mat)
{
int N = mat.size(), M = mat[0].size();
// Converting given matrix to a graph
vector > adj[N * M];
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
// Each cell is a node,
// with label i*N + j
for (int dir = 1; dir <= 4; dir++) {
// Label of node if we
// move in direction dir
int nextNodeLabel
= nextNode(i, j, dir, N, M);
// If invalid(out of matrix)
if (nextNodeLabel == -1)
continue;
// If direction is same as mat[i][j]
if (dir == mat[i][j])
adj[i * N + j].push_back(
{ nextNodeLabel, 0 });
else
adj[i * N + j].push_back(
{ nextNodeLabel, 1 });
}
}
}
// Applying djikstra's algorithm
return dijkstra(adj, 0,
(N - 1) * N + M - 1, N, M);
}
// Driver code
int main()
{
vector > mat = { { 2, 2, 1 },
{ 4, 2, 3 },
{ 4, 3, 2 } };
// Function call
cout << MinModifications(mat);
return 0;
}
C++
// C++ program to find minimum
// possible changes required
// in the matrix
#include
using namespace std;
// Function to find next possible node
int nextNode(int x, int y, int dir,
int N, int M)
{
if (dir == 1)
y--;
else if (dir == 2)
y++;
else if (dir == 3)
x--;
else
x++;
// If node is out of matrix
if (!(x >= 0 && x < N && y >= 0 && y < M))
return -1;
else
return (x * N + y);
}
// Prints shortest distance
// from given source to
// every other vertex
int zeroOneBFS(vector >* adj,
int src, int dest, int N, int M)
{
// Initialize distances
// from given source
int dist[N * M];
for (int i = 0; i < N * M; i++)
dist[i] = INT_MAX;
// Double ended queue to do BFS.
deque Q;
dist[src] = 0;
Q.push_back(src);
while (!Q.empty()) {
int v = Q.front();
Q.pop_front();
for (auto i : adj[v]) {
// Checking for the optimal distance
if (dist[i.first] > dist[v]
+ i.second) {
dist[i.first] = dist[v]
+ i.second;
// Put 0 weight edges to front
// and 1 weight edges to back
// so that vertices are processed
// in increasing order of weights.
if (i.second == 0)
Q.push_front(i.first);
else
Q.push_back(i.first);
}
}
}
// Shortest distance to
// reach destination
return dist[dest];
}
// Function to find minimum possible
// changes required in the matrix
int MinModifications(vector >& mat)
{
int N = mat.size(), M = mat[0].size();
// Converting given matrix to a graph
vector > adj[N * M];
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
// Each cell is a node
// with label i*N + j
for (int dir = 1; dir <= 4; dir++) {
// Label of node if we
// move in direction dir
int nextNodeLabel = nextNode(i, j,
dir, N, M);
// If invalid(out of matrix)
if (nextNodeLabel == -1)
continue;
// If direction is same as mat[i][j]
if (dir == mat[i][j])
adj[i * N + j].push_back(
{ nextNodeLabel, 0 });
else
adj[i * N + j].push_back(
{ nextNodeLabel, 1 });
}
}
}
// Applying djikstra's algorithm
return zeroOneBFS(adj, 0,
(N - 1) * N + M - 1, N, M);
}
// Driver code
int main()
{
vector > mat = { { 2, 2, 1 },
{ 4, 2, 3 },
{ 4, 3, 2 } };
// Function call
cout << MinModifications(mat);
return 0;
}
Python3
# Python3 program to find minimum
# possible changes required
# in the matrix
from collections import deque
# Function to find next possible node
def nextNode(x, y, dir, N, M):
if (dir == 1):
y -= 1
elif (dir == 2):
y += 1
elif (dir == 3):
x -= 1
else:
x += 1
# If node is out of matrix
if (not (x >= 0 and x < N and y >= 0 and y < M)):
return -1
else:
return (x * N + y)
# Prints shortest distance
# from given source to
# every other vertex
def zeroOneBFS(adj, src, dest, N, M):
# Initialize distances
# from given source
dist = [10**8] *(N * M)
# Double ended queue to do BFS.
Q = deque()
dist[src] = 0
Q.append(src)
while (len(Q) > 0):
v = Q.popleft()
for i in adj[v]:
# print(i)
# Checking for the optimal distance
if (dist[i[0]] > dist[v] + i[1]):
dist[i[0]] = dist[v] + i[1]
# Put 0 weight edges to front
# and 1 weight edges to back
# so that vertices are processed
# in increasing order of weights.
if (i[1] == 0):
Q.appendleft(i[0])
else:
Q.append(i[0])
# Shortest distance to
# reach destination
return dist[dest]
# Function to find minimum possible
# changes required in the matrix
def MinModifications(mat):
N, M = len(mat), len(mat[0])
# Converting given matrix to a graph
adj = [[] for i in range(N * M)]
for i in range(N):
for j in range(M):
# Each cell is a node
# with label i*N + j
for dir in range(1, 5):
# Label of node if we
# move in direction dir
nextNodeLabel = nextNode(i, j, dir, N, M)
# If invalid(out of matrix)
if (nextNodeLabel == -1):
continue
# If direction is same as mat[i][j]
if (dir == mat[i][j]):
adj[i * N + j].append([nextNodeLabel, 0])
else:
adj[i * N + j].append([nextNodeLabel, 1])
# Applying djikstra's algorithm
return zeroOneBFS(adj, 0, (N - 1) * N + M - 1, N, M)
# Driver code
if __name__ == '__main__':
mat = [ [ 2, 2, 1 ],
[ 4, 2, 3 ],
[ 4, 3, 2 ] ]
# Function call
print (MinModifications(mat))
# This code is contributed by mohit kumar 29.
Javascript
输出:
2
时间复杂度:
方法二
这里,边权重为 0,只有 1,即它是一个 0-1 图。可以使用 0-1 BFS 找到此类图中的最短路径。
下面是上述方法的实现:
C++
// C++ program to find minimum
// possible changes required
// in the matrix
#include
using namespace std;
// Function to find next possible node
int nextNode(int x, int y, int dir,
int N, int M)
{
if (dir == 1)
y--;
else if (dir == 2)
y++;
else if (dir == 3)
x--;
else
x++;
// If node is out of matrix
if (!(x >= 0 && x < N && y >= 0 && y < M))
return -1;
else
return (x * N + y);
}
// Prints shortest distance
// from given source to
// every other vertex
int zeroOneBFS(vector >* adj,
int src, int dest, int N, int M)
{
// Initialize distances
// from given source
int dist[N * M];
for (int i = 0; i < N * M; i++)
dist[i] = INT_MAX;
// Double ended queue to do BFS.
deque Q;
dist[src] = 0;
Q.push_back(src);
while (!Q.empty()) {
int v = Q.front();
Q.pop_front();
for (auto i : adj[v]) {
// Checking for the optimal distance
if (dist[i.first] > dist[v]
+ i.second) {
dist[i.first] = dist[v]
+ i.second;
// Put 0 weight edges to front
// and 1 weight edges to back
// so that vertices are processed
// in increasing order of weights.
if (i.second == 0)
Q.push_front(i.first);
else
Q.push_back(i.first);
}
}
}
// Shortest distance to
// reach destination
return dist[dest];
}
// Function to find minimum possible
// changes required in the matrix
int MinModifications(vector >& mat)
{
int N = mat.size(), M = mat[0].size();
// Converting given matrix to a graph
vector > adj[N * M];
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
// Each cell is a node
// with label i*N + j
for (int dir = 1; dir <= 4; dir++) {
// Label of node if we
// move in direction dir
int nextNodeLabel = nextNode(i, j,
dir, N, M);
// If invalid(out of matrix)
if (nextNodeLabel == -1)
continue;
// If direction is same as mat[i][j]
if (dir == mat[i][j])
adj[i * N + j].push_back(
{ nextNodeLabel, 0 });
else
adj[i * N + j].push_back(
{ nextNodeLabel, 1 });
}
}
}
// Applying djikstra's algorithm
return zeroOneBFS(adj, 0,
(N - 1) * N + M - 1, N, M);
}
// Driver code
int main()
{
vector > mat = { { 2, 2, 1 },
{ 4, 2, 3 },
{ 4, 3, 2 } };
// Function call
cout << MinModifications(mat);
return 0;
}
蟒蛇3
# Python3 program to find minimum
# possible changes required
# in the matrix
from collections import deque
# Function to find next possible node
def nextNode(x, y, dir, N, M):
if (dir == 1):
y -= 1
elif (dir == 2):
y += 1
elif (dir == 3):
x -= 1
else:
x += 1
# If node is out of matrix
if (not (x >= 0 and x < N and y >= 0 and y < M)):
return -1
else:
return (x * N + y)
# Prints shortest distance
# from given source to
# every other vertex
def zeroOneBFS(adj, src, dest, N, M):
# Initialize distances
# from given source
dist = [10**8] *(N * M)
# Double ended queue to do BFS.
Q = deque()
dist[src] = 0
Q.append(src)
while (len(Q) > 0):
v = Q.popleft()
for i in adj[v]:
# print(i)
# Checking for the optimal distance
if (dist[i[0]] > dist[v] + i[1]):
dist[i[0]] = dist[v] + i[1]
# Put 0 weight edges to front
# and 1 weight edges to back
# so that vertices are processed
# in increasing order of weights.
if (i[1] == 0):
Q.appendleft(i[0])
else:
Q.append(i[0])
# Shortest distance to
# reach destination
return dist[dest]
# Function to find minimum possible
# changes required in the matrix
def MinModifications(mat):
N, M = len(mat), len(mat[0])
# Converting given matrix to a graph
adj = [[] for i in range(N * M)]
for i in range(N):
for j in range(M):
# Each cell is a node
# with label i*N + j
for dir in range(1, 5):
# Label of node if we
# move in direction dir
nextNodeLabel = nextNode(i, j, dir, N, M)
# If invalid(out of matrix)
if (nextNodeLabel == -1):
continue
# If direction is same as mat[i][j]
if (dir == mat[i][j]):
adj[i * N + j].append([nextNodeLabel, 0])
else:
adj[i * N + j].append([nextNodeLabel, 1])
# Applying djikstra's algorithm
return zeroOneBFS(adj, 0, (N - 1) * N + M - 1, N, M)
# Driver code
if __name__ == '__main__':
mat = [ [ 2, 2, 1 ],
[ 4, 2, 3 ],
[ 4, 3, 2 ] ]
# Function call
print (MinModifications(mat))
# This code is contributed by mohit kumar 29.
Javascript
输出:
2
时间复杂度:
辅助空间: O(N * M)