質問の意味:
操作の最小数を見つけ、すべての位置$ 1 $をカバーするために、$ $行列にM $ 01 $ N \回を考えます。一回の操作で、エンドカバーに$ C $連続カラム、連続被覆又は横$ R $行までであることができます。
$ 1 \ル\、N \; M、\; R、\、C \ \; $ 15
分析:
小さいデータ範囲は、列挙を考えます。
列挙ではなく、盲目的に、この列挙は$ O(2 ^ {2N}であるので、カラムを上書きする、行を覆って )$ 、そしてTが$であろう$。
列挙上書き行、操作後の溶液を得るために計算さ貪欲コラムカバー片は、完成されている考えます。
合計時間複雑さの$ O(N ^ 3 \回2 ^ N)$。
実装:
#include <iostreamの> する#include <cstdioを> する#include <cmath> の#include <CStringの> する#include <アルゴリズム> の#define ILインライン 使用 名前空間STDを、 CONSTの INT N = 15 。 INTのN、M、R、C。 INTの BOD [N + 3 ] [N + 3 ]。 INT CLM [N + 3 ]。 int型 TBOD [N + 3 ] [N + 3 ]。 INT tclm [N + 3 ]。 INT メイン(){ scanf関数("%D%D \ n "、&N、&M) のmemset(BOD、0、はsizeof BOD) のための(int型 I = 0 iがN <; Iは++ ){ チャーCH; のための(INT J = 0 ; J < M; J ++ ){ scanf関数(" %のC "、&CH); BOD [I] [J] = CH == ' X ' ; } のscanf(" の\ n " ); } のscanf(" %D%D \ nは"、&R&C)。 memset(CLM、0、はsizeofのCLM)。 以下のために(int型 i = 0 ; iがmを<; I ++ ) のための(INT J = 0 ; J <N; J ++ ) CLM [i]を + = BOD [j] [i]は、 memcpy(TBOD、BOD、はsizeof BOD)。 memcpy(tclm、CLM、はsizeofのCLM)。 INT ANS =分(N / R + 1、M / C + 1 )。 用(INT S = 0 ; S <(1 << N); S ++ ){ int型CNT = 0 ; 以下のために(int型 i = 0 ; iがn <; iは++ ) 場合(S >> I&1 ){ CNT ++ 。 以下のために(INT J = 0 ; J <R J ++ ) のための(INT K = 0 ; M <K、Kは++ ) 場合(BODは[iがjは+] [K] == 1 ){ BOD [iが jは+] [K ] = 0 ; CLM [K] - 。 } } のために(int型 I = 0 ; iが<M; iが++ ) 場合(CLM [i]が> 0 ){ CNT ++ 。 用(INT J = 0 ; J <C; J ++ ) CLM [iが jは+] = 0 ; } のmemcpy(BOD、TBOD、はsizeofのTBOD)。 memcpy(CLM、tclm、はsizeof tclm)。 ANS = 分(ANS、CNT)。 } のprintf(" %dの" 、ANS)。 リターン 0 ; }
要約:
検索をプルーニングを検討するだけでなく、検索バーの構造の最適化を検討してください。