C ++
 Computer >> コンピューター >  >> プログラミング >> C ++

C++でバイナリ行列をゼロ行列に変換するためのフリップの最小数


mxnのバイナリ行列マットがあるとします。 1つのステップで、1つのセルを選択し、そのビットとその4つの隣接セルすべて(存在する場合)を反転できます。マットをゼロ行列に変換するために必要な最小ステップ数を見つける必要があります。解決策がない場合は、-1を返します。

したがって、指定された入力が[[0,0]、[0,1]]のような場合、変更は-

のようになります。

C++でバイナリ行列をゼロ行列に変換するためのフリップの最小数

したがって、3つのステップが必要で、出力は3になります。

これを解決するには、次の手順に従います-

  • n:=行数、m:=列数、x:=0
  • iを初期化する場合:=0、i
  • jを初期化する場合:=0、j
  • jを初期化する場合:=0、j
  • x:=x+左シフトマット[i][j]値(i * m)+ j)回数
  • 2 ^(n * m)個のセルで配列dpを定義し、これに-1を入力します
  • dp [x]:=0
  • 1つのキューを定義するq
  • xをqに挿入
  • (qは空ではありません)、実行します-
  • current:=qの最初の要素、qから要素を削除
  • 電流が0と同じ場合、-
    • return dp [current]
  • iを初期化する場合:=0、i
  • jを初期化する場合:=0、j
  • temp:=current
  • temp:=temp XOR 2 ^(i * m)+ j)
  • kを初期化する場合:=0、k <4の場合、更新(kを1つ増やす)、実行-
    • ni:=i + dir [k] [0]
    • nj:=j + dir [k] [1]
    • ni<0またはnj<0またはni>=nまたはnj>=mの場合、-
      • 次の部分を無視し、次の反復にスキップします
      • temp:=temp XOR 2 ^(ni * m)+ nj)
  • dp [temp]が-1と同じ場合、-
    • dp [temp]:=dp [current] + 1
    • 温度をqに挿入
  • 戻り値-1
  • 理解を深めるために、次の実装を見てみましょう-

    #include <bits/stdc++.h>
    using namespace std;
    int dir[4][2] = {{1, 0}, {-1, 0}, {0, -1}, {0, 1}};
    class Solution {
    public:
       int minFlips(vector<vector<int>>& mat) {
          int n = mat.size();
          int m = mat[0].size();
          int x = 0;
          for(int i = 0; i < n; i++){
             for(int j = 0; j < m; j++){
                x += (mat[i][j] << ((i * m) + j));
             }
          }
          vector < int > dp(1 << (n*m), -1);
          dp[x] = 0;
          queue <int> q;
          q.push(x);
          while(!q.empty()){
             int current = q.front();
             q.pop();
             if(current == 0)return dp[current];
             for(int i = 0; i < n; i++){
                for(int j = 0; j < m; j++){
                   int temp = current;
                   temp ^= (1 << ((i *m) + j));
                   for(int k = 0; k < 4; k++){
                      int ni = i + dir[k][0];
                      int nj = j + dir[k][1];
                      if(ni < 0 || nj < 0 || ni >= n || nj >= m)continue;
                      temp ^= (1 << ((ni *m) + nj));
                   }
                   if(dp[temp] == -1){
                      dp[temp] = dp[current] + 1;
                      q.push(temp);
                   }
                }
             }
          }
          return -1;
       }
    };
    main(){
       Solution ob;
       vector<vector<int>> v = {{0,0},{0,1}};
       cout << (ob.minFlips(v));
    }

    入力

    {{0,0},{0,1}}

    出力

    3

    1. C++でバイナリ行列をゼロ行列に変換する演算の数をカウントするプログラム

      バイナリ行列があるとします。ここで、1つのセルを取得し、そのセルとそのすべての隣接セル(上、下、左、右)を反転する操作について考えてみます。行列に0のみが含まれるように、必要な操作の最小数を見つける必要があります。解決策がない場合は、-1を返します。 したがって、入力が次のような場合 0 0 1 0 その場合、出力は3になります。 これを解決するには、次の手順に従います- サイズの配列ディレクトリを定義します:4 x 2:={{1、0}、{0、1}、{-1、0}、{0、-1}} const int inf =10 ^ 6 関数getP

    2. C++での二分木の最小の深さ

      二分木があるとしましょう。その木の最小の深さを見つけなければなりません。最小の深さは、ルートノードから最も近いリーフノードまでの最短パスに沿ったノードの数です。 したがって、入力が次のような場合 その場合、出力は2になります これを解決するには、次の手順に従います- ツリーノードの配列aaを定義する aaの最後にルートを挿入します ツリーノードの別の配列akを定義します レベル:=0 ルートがnullの場合、- 0を返す aaのサイズが0に等しくない場合は、-を実行します。 配列akをクリアします (レベルを1上げます)