👉 “Offer 驾到,掘友接招!我正在参与2022春招打卡活动点击查看 活动详情。
1595. 连通两组点的最小成本
给你两组点,其中第一组中有 size1 个点,第二组中有 size2 个点,且 size1 >= size2 。
任意两点间的连接成本 cost 由大小为 size1 x size2 矩阵给出,其中 cost[i][j] 是第一组中的点 i 和第二组中的点 j 的连接成本。如果两个组中的每个点都与另一组中的一个或多个点连接,则称这两组点是连通的。换言之,第一组中的每个点必须至少与第二组中的一个点连接,且第二组中的每个点必须至少与第一组中的一个点连接。
返回连通两组点所需的最小成本。
状态定义:
f[i][j] :表示左侧已经连通了前i个点,右侧点连接状态为j的最小代价是多少
状态转移:
-
枚举左侧第i个点,连接右侧哪些点
- 左侧的第i个点,连接右侧的若干个未连接的点
- 左侧的第i个点,连接右侧的一个已经连接的点
枚举子集:
/*
101 5
100 4
1 1
*/
#include<bits/stdc++.h>
using namespace std;
int main(){
int S = 5;
for(int sub = S; sub ; sub = (sub - 1) & S){
cout << sub << endl;
}
return 0;
}
code
class Solution {
public:
int f[13][1 << 12];
int connectTwoGroups(vector<vector<int>>& cost) {
memset(f, -1, sizeof f);
int m = cost.size(), n = cost[0].size();
f[0][0] = 0;
int state = (1 << n) - 1;
for(int i = 1; i <= m; i++){
for(int j = 0; j < (1 << n); j++){
if(f[i - 1][j] == -1) continue;
//枚举子集,找未连接的点
int rs = (~j) & state;
for(int sub = rs; sub; sub = (sub - 1) & rs){
int cur = 0;
for(int k = 0; k < n; k++) if(sub & (1 << k)) cur += cost[i - 1][k];
int nxt = j | sub;
int val = f[i - 1][j] + cur;
if(f[i][nxt] == -1 or f[i][nxt] > val){
f[i][nxt] = val;
}
}
//找已经连接的点
for(int k = 0; k < n; k++){
int nxt = j | (1 << k), val = f[i - 1][j] + cost[i - 1][k];
if(f[i][nxt] == -1 or f[i][nxt] > val) f[i][nxt] = val;
}
}
}
return f[m][state];
}
};