【算法】Minimum Cost to Connect Two Groups of Points 连通两组点的最小成本 动态规划

文章目录

  • Minimum Cost to Connect Two Groups of Points 连通两组点的最小成本 动态规划
    • 问题描述:
    • 分析
    • 代码
    • Tag

Minimum Cost to Connect Two Groups of Points 连通两组点的最小成本 动态规划

问题描述:

size1,size2范围[1,12] ,size1>=size2 , c o s t [ i ] [ j ] cost[i][j] cost[i][j] 范围[0,100]

分析

d f s ( i , b i t m a s k S e t ) = min ⁡ d f s ( i − 1 , b i t m a s k S e t ∖ b i t k ) + c o s t [ i ] [ b i t k ] dfs(i,bitmaskSet) = \min{dfs(i-1,bitmaskSet\setminus bitk)+ cost[i][bitk]} dfs(i,bitmaskSet)=mindfs(i1,bitmaskSetbitk)+cost[i][bitk]

d f s ( − 1 , b i t m a s k S e t ) = Σ m i n c o s t [ b i t k ] , b i t k ∈ b i t m a s k S e t dfs(-1,bitmaskSet) = \Sigma mincost[bitk] ,bitk \in bitmaskSet dfs(1,bitmaskSet)=Σmincost[bitk],bitkbitmaskSet

之前是暴力递归+记忆化,现在要改为自底向上的动态规划。所以构建动态规划的状态转移方程f[][]其意义与dfs相同,则对应的转移方程为
f [ i ] [ b i t m a s k S e t ] = min ⁡ ( f [ i − 1 ] [ b i t m a s k S e t ∖ i t k ] + c o s t [ i ] [ b i t k ] ) f[i][bitmaskSet] = \min{} (f[i-1][bitmaskSet\setminus itk]+cost[i][bitk]) f[i][bitmaskSet]=min(f[i1][bitmaskSetitk]+cost[i][bitk])
根据之前的递归的i是可以小于0的,但是这里就会发生越界。最简单的方法就是整体偏移。
f [ i + 1 ] [ b i t m a s k S e t ] = m i n ( f [ i ] [ b i t m a s k S e t ∖ b i t k ] + c o s t [ i ] [ b i t k ] ) f[i+1][bitmaskSet] = min (f[i][bitmaskSet\setminus bitk]+cost[i][bitk]) f[i+1][bitmaskSet]=min(f[i][bitmaskSetbitk]+cost[i][bitk])
而且当i==0的时候,处于边界,表示所有节点都已经完成连接,此时还有bitmaskSet的元素需要连接。
所以需要枚举 2 n − 1 2^n-1 2n1个组合,来对 f [ 0 ] [ b i t m a s k s e t ] f[0][bitmaskset] f[0][bitmaskset]进行初始化。

代码

class Solution {
    public int connectTwoGroups(List<List<Integer>> cost) {
        int m = cost.size(), n = cost.get(0).size();
        int[] mincost = new int[n];
        Arrays.fill(mincost, Integer.MAX_VALUE);
        for (int j = 0; j < n; j++){
            for (var c : cost){
                mincost[j] = Math.min(mincost[j], c.get(j));
            }
        } 
        int[][] f = new int[m + 1][1 << n];
        for (int bitmaskset = 1; bitmaskset < 1 << n; bitmaskset++){
            for (int k = 0; k < n; k++){
                if ((bitmaskset >> k & 1) == 1){
                    // 第二组的点 k 未连接
                    f[0][bitmaskset] += mincost[k]; // 去第一组找个成本最小的点连接
                } 
            }                
        }        
        for (int i = 0; i < m; i++) {
            for (int bitmaskset = 0; bitmaskset < 1 << n; bitmaskset++) {
                int res = Integer.MAX_VALUE;
                for (int k = 0; k < n; k++) // 第一组的点 i 与第二组的点 k
                    res = Math.min(res, f[i][bitmaskset & ~(1 << k)] + cost.get(i).get(k));
                f[i + 1][bitmaskset] = res;
            }
        }
        return f[m][(1 << n) - 1];
    }
}
 

时间复杂度O(mn2^n)

空间复杂度O(m2^n)

代码模板来源于灵神大佬,结构清晰,逻辑完整。

Tag

Bit Manipulation Bitmask Dynamic Programming

你可能感兴趣的:(数据结构与算法,算法,动态规划)