a_lc_连通两组点的最小成本(状压+枚举两种连法)

任意两点间的连接成本 cost 由大小为 size1 x size2 矩阵给出,其中 cost[i][j] 是第一组中的点 i 和第二组中的点 j 的连接成本
第一组中的每个点必须至少与第二组中的一个点连接,且第二组中的每个点必须至少与第一组中的一个点连接。
1 <= size1, size2 <= 12

我当时的做法的case通过数量是45/83,可能是没有考虑完或者边界问题(没时间改),参考别人的状态压缩dp,对于第一组的每个点i:

  • 第一种连法:直接连接第二组的每个点
  • 第二种连法:连接第二组没有连接到的点

题目还是很良心的,不用自己通过对比size1, size2来确定哪一维用作状态压缩

const int inf=0x3f3f3f3f;
class Solution {
public:
    int connectTwoGroups(vector<vector<int>>& cost) {
        int n=cost.size(), m=cost[0].size(), tot=1<<m, f[n+1][tot];
        memset(f, inf, sizeof f); f[0][0]=0;

        for (int i=1; i<=n; i++)
        for (int st=0; st<tot; st++) {
            //连接第二组中任意一个点
            if (f[i-1][st]!=inf) {
                for (int j=0; j<m; j++) {
                    int nx=st|(1<<j);
                    f[i][nx]=min(f[i][nx], f[i-1][st]+cost[i-1][j]);
                }
            }
            int other_st=(tot-1)^st;    //第二组点中没有被连接到的所有点的状态集合
            for (int subset=other_st; subset; subset=other_st&(subset-1)) { //去掉other_set的最低位的1
                int sum=0;
                for (int j=0; j<m; j++) if (subset&(1<<j)) {
                    sum+=cost[i-1][j];
                }
                int nx=st|subset;
                f[i][nx]=min(f[i][nx], f[i-1][st]+sum);   //这里一开始我写成了 f[i][subset]=...,这是错的,下一个状态没累加上初始状态
            }
        }
        return f[n][tot-1];
    }
};

复杂度分析

  • Time\(O(nm2^m)\)
  • Space\(O()\)
posted @ 2020-09-21 09:15  童年の波鞋  阅读(213)  评论(0编辑  收藏  举报