欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 名人名企 > 费用流,LeetCode 2850. 将石头分散到网格图的最少移动次数

费用流,LeetCode 2850. 将石头分散到网格图的最少移动次数

2024/10/26 0:29:38 来源:https://blog.csdn.net/EQUINOX1/article/details/140571894  浏览:    关键词:费用流,LeetCode 2850. 将石头分散到网格图的最少移动次数

一、题目

1、题目描述

给你一个大小为 3 * 3 ,下标从 0 开始的二维整数矩阵 grid ,分别表示每一个格子里石头的数目。网格图中总共恰好有 9 个石头,一个格子里可能会有 多个 石头。

每一次操作中,你可以将一个石头从它当前所在格子移动到一个至少有一条公共边的相邻格子。

请你返回每个格子恰好有一个石头的 最少移动次数 。

2、接口描述

cpp
 ​
class Solution {
public:int minimumMoves(vector<vector<int>>& grid) {}
};

3、原题链接

2850. 将石头分散到网格图的最少移动次数


二、解题报告

1、思路分析

网络流建图就完了,考虑怎么建

首先虚拟源汇点s、t

对于石头数目c大于1的格子,从源点向其连容量为 c - 1, 费用为0的边

从该格子向所有石头数目为0的格子连容量为1,费用为曼哈顿距离的边

对于所有权值为0的格子,向汇点连容量为1,费用为0的边

跑最小费用最大流就行了

2、复杂度

时间复杂度: EK算法理论时间复杂度上限为O(NM^2)空间复杂度:O(N + M)

3、代码详解

cpp
 
constexpr int N = 15, inf = 1e9;
struct edge {int v, c, w, nxt;
} adj[N * 12];int s, t;
int head[N], idx;
int q[N], dst[N], incf[N], pre[N];
bool vis[N];void init() {memset(head, -1, sizeof head);idx = 0;s = 0, t = 10;
}void addedge(int u, int v, int c, int w) {adj[idx] = { v, c, w, head[u] }, head[u] = idx ++;
}void add(int u, int v, int c, int w) {addedge(u, v, c, w), addedge(v, u, 0, -w);
}bool spfa() {memset(incf, 0, sizeof incf);memset(dst, 0x3f, sizeof dst);int f = 0, b = 0;dst[q[b ++] = s] = 0, vis[s] = true, incf[s] = inf;while (b - f) {int u = q[f ++];f %= N;vis[u] = false;for (int i = head[u]; ~i; i = adj[i].nxt) {int v = adj[i].v;if (adj[i].c && dst[v] > dst[u] + adj[i].w) {dst[v] = dst[u] + adj[i].w;incf[v] = std::min(incf[u], adj[i].c);pre[v] = i;if (vis[v]) continue;vis[q[b ++] = v] = true;b %= N;}}}return incf[t];
}void update(int& f, int& c) {for (int v = t; v != s; ) {int i = pre[v];adj[i].c -= incf[t];adj[i ^ 1].c += incf[t];v = adj[i ^ 1].v;}c += dst[t] * incf[t];f += incf[t];
}int EK() {int f = 0, c = 0;while(spfa())update(f, c); return c;
}int getp(int x, int y) {return x * 3 + y + 1;
}class Solution {
public:int minimumMoves(vector<vector<int>>& grid) {init();for (int i = 0; i < 3; ++ i) for (int j = 0; j < 3; ++ j) {if (grid[i][j] > 1) {add(s, getp(i, j), grid[i][j] - 1, 0);for (int ii = 0; ii < 3; ++ ii) for (int jj = 0; jj < 3; ++ jj) if (!grid[ii][jj])add(getp(i, j), getp(ii, jj), 1, abs(i - ii) + abs(j - jj));}else if(grid[i][j] == 0)add(getp(i, j), t, 1, 0);}return EK();}
};

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com