【每日一题Day243】LC1595连通两组点的最小成本 | 状态压缩dp

简介: 【每日一题Day243】LC1595连通两组点的最小成本 | 状态压缩dp

连通两组点的最小成本【LC1595】

给你两组点,其中第一组中有 size1 个点,第二组中有 size2 个点,且 size1 >= size2

任意两点间的连接成本 cost 由大小为 size1 x size2 矩阵给出,其中 cost[i][j] 是第一组中的点 i 和第二组中的点 j 的连接成本。**如果两个组中的每个点都与另一组中的一个或多个点连接,则称这两组点是连通的。**换言之,第一组中的每个点必须至少与第二组中的一个点连接,且第二组中的每个点必须至少与第一组中的一个点连接。

返回连通两组点所需的最小成本。

猛练状态压缩dp

dfs+回溯

  • 思路
    每个点都需要跟另一个组的至少一个点连接,计算最小成本。那么我们可以枚举第一组第i  个点与第2组哪个点连接。【先只保证第一组跟第二组中一个点连接,如果第二组有点没有连接,再将其和最小成本的点连接】。记录第二组点的连接状态,使用状态压缩dp解决。


实现

class Solution {
    int n, m;
    int[][] memo;
    int[] minCost;
    List<List<Integer>> cost;
    public int connectTwoGroups(List<List<Integer>> cost) {
        this.n = cost.size();
        this.m = cost.get(0).size();
        this.memo = new int[n][1 << m];
        this.minCost = new int[m];
        this.cost = cost;
        Arrays.fill(minCost, Integer.MAX_VALUE);
        for (int i = 0; i < n; i++){
            Arrays.fill(memo[i], -1);
        }
        for (List<Integer> c : cost){
            for (int i = 0; i < m; i++){
                minCost[i] = Math.min(minCost[i], c.get(i));
            }
        }
        return dfs(n - 1, 0);
    }
    public int dfs(int i, int mask){
        if (i < 0){// 寻找第二组未连接的点,将其与第一组中最小成本的点连接
            int res = 0;
            for (int j = 0; j < m; j++){
                if (((mask >> j) & 1) == 0){
                    res += minCost[j];
                }
            }
            return res;
        }
        if (memo[i][mask] != -1) return memo[i][mask];
        int res = Integer.MAX_VALUE;
        // 枚举第一组第i个点与第2组哪个点连接【先只保证第一组跟第二组中一个点连接,如果第二组有点没有连接,再将其和最小成本的点连接】
        for (int j = 0; j < m; j++){
            res = Math.min(res, dfs(i - 1, mask | (1 << j)) + cost.get(i).get(j)) ;
        }
        return memo[i][mask] = res;
    }
}

image.png

class Solution {
    public int connectTwoGroups(List<List<Integer>> cost) {
        int n = cost.size(), m = cost.get(0).size();
        var minCost = new int[m];
        Arrays.fill(minCost, Integer.MAX_VALUE);
        for (int j = 0; j < m; j++)
            for (var c : cost)
                minCost[j] = Math.min(minCost[j], c.get(j));
        var f = new int[n + 1][1 << m];
        for (int j = 0; j < 1 << m; j++)
            for (int k = 0; k < m; k++)
                if ((j >> k & 1) == 1) // 第二组的点 k 未连接
                    f[0][j] += minCost[k]; // 去第一组找个成本最小的点连接
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < 1 << m; j++) {
                int res = Integer.MAX_VALUE;
                for (int k = 0; k < m; k++) // 第一组的点 i 与第二组的点 k
                    res = Math.min(res, f[i][j & ~(1 << k)] + cost.get(i).get(k));
                f[i + 1][j] = res;
            }
        }
        return f[n][(1 << m) - 1];
    }
}
作者:灵茶山艾府
链接:https://leetcode.cn/problems/minimum-cost-to-connect-two-groups-of-points/solutions/2314687/jiao-ni-yi-bu-bu-si-kao-dong-tai-gui-hua-djxq/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

image.png

目录
相关文章
|
6月前
【每日一题Day168】LC2427公因子的数目 | 模拟
【每日一题Day168】LC2427公因子的数目 | 模拟
38 1
|
6月前
【每日一题Day144】LC1617统计子树中城市之间最大距离 | 树形dp
【每日一题Day144】LC1617统计子树中城市之间最大距离 | 树形dp
31 0
|
6月前
【每日一题Day342】LC2578最小和分割 | 贪心
【每日一题Day342】LC2578最小和分割 | 贪心
44 0
|
6月前
|
人工智能 BI
【每日一题Day354】LC2316统计无向图中无法互相到达点对数 | 并查集
【每日一题Day354】LC2316统计无向图中无法互相到达点对数 | 并查集
52 0
|
1月前
|
算法 决策智能
基于prim算法求出网络最小生成树实现网络社团划分和规划
该程序使用MATLAB 2022a版实现路线规划,通过排序节点权值并运用Prim算法生成最小生成树完成网络规划。程序基于TSP问题,采用遗传算法与粒子群优化算法进行路径优化。遗传算法通过编码、选择、交叉及变异操作迭代寻优;粒子群优化算法则通过模拟鸟群觅食行为,更新粒子速度和位置以寻找最优解。
|
6月前
|
算法 测试技术 C#
【图论】【分类讨论】LeetCode3017按距离统计房屋对数目
【图论】【分类讨论】LeetCode3017按距离统计房屋对数目
|
6月前
【每日一题Day167】LC1000合并石头的最低成本 | 区间dp
【每日一题Day167】LC1000合并石头的最低成本 | 区间dp
55 1
【每日一题Day167】LC1000合并石头的最低成本 | 区间dp
|
6月前
leetcode-1200:最小绝对差
leetcode-1200:最小绝对差
40 1
|
6月前
【每日一题Day257】LC2178拆分成最多数目的正偶数之和 | 贪心
【每日一题Day257】LC2178拆分成最多数目的正偶数之和 | 贪心
33 2
|
6月前
【每日一题Day241】LC1254统计封闭岛屿的数目 | dfs
【每日一题Day241】LC1254统计封闭岛屿的数目 | dfs
45 1