1. タイトル
1. トピックの説明
0 から始まりsize の インデックス を持つ
m x n
バイナリ行列 が与えられ、 選択する必要があるさまざまな列の数を 表すmatrix
整数も与えられます 。numSelect
matrix
行内のすべてが
1
選択した列でカバーされている場合、その行は カバーされているとみなされます 。形式的には
s = {c1, c2, ...., cnumSelect}
、 列のセットを選択したとします 。行列内の特定の行についてrow
、次の条件が満たされる場合、この行は セットのs
対象であるとみなされます。
- ( )
matrix[row][col] == 1
を 満たす 、 存在する 、またはmatrix[row][col]
0 <= col <= n - 1
col
s
row
に 値を 持つセルはありません。1
numSelect
セットでカバーされる行数を最大にする列をマトリックスから選択する必要があります 。
numSelect
一連の列 でカバーできる最大行数 を 表す整数を返します 。
2. インターフェースの説明
class Solution {
public:
int maximumRows(vector<vector<int>>& matrix, int numSelect) {
}
};
3. 元のタイトルのリンク
2. 問題解決レポート
1. アイデア分析
データ量が 1 ~ 12 であるため、指数解法を使用する必要があることがわかります。
次に、ブルート フォース バックトラッキングを検討することもできます。行列に m 行、n 列があり、n 列から numselect 列を選択すると仮定します。オプションの組み合わせはいくつかあることは明らかです。そのたびに、カバーされる行の数を計算する必要があります。 m * n 回かかる このようにすると、時間計算量は O(2 ^ n * m * n) となり、時間計算量は 1e5 ~ 1e6 程度になります。これは可能なはずですが、実際には行数を最適化できます。それぞれの計算でカバーされます。
これは 01 行列なので、n ビット 2 進整数を使用して行のステータス ビットを表すことができます。また、n ビット 2 進整数を使用して現在選択されている列番号 cur を表すこともできます。その場合、 bit | cur = curこれはカバーリングであることを意味します。
2. 複雑さ
時間計算量:空間計算量: O(m)
3. コードの詳細説明
class Solution {
public:
int bits[12] , m , n , ret;
int maximumRows(vector<vector<int>>& matrix, int numSelect) {
memset(bits , 0 , sizeof(bits));
m = matrix.size() , n = matrix[0].size() , ret = 0;
for(int i = 0 ; i < m ; i++)
for(int j = 0 ; j < n ; j++)
if(matrix[i][j])
bits[i] |= (1 << j);
function<void(int , int)> dfs = [&](int x , int cur)
{
if(x == n || __builtin_popcount(cur) == numSelect)
return;
cur |= (1 << x);
int cnt = 0;
for(int i = 0 ; i < m ; i++)
cnt += ((bits[i] | cur) == cur);
ret = max(ret , cnt);
dfs(x + 1 , cur);
cur ^= (1 << x);
dfs(x + 1 , cur);
};
dfs(0 , 0);
return ret;
}
};