[説明]トウモロコシ畑

圧力シリーズIIのように。

トピックリンク

タイトル効果:与えられた\(N * m個\)位置のいくつかを置くことができるマトリックス、一部はできません。グリッドの規定は、左を入れて、右のそれを置くことはできません。どのように多くのグリッドプログラムを置くことを求めました。

考慮\(N、Mの\)は圧力の形状であるように、小さいです。

圧力のような表現を考えてみましょう、私たちは各ラインに置く\(01 \)バイナリに押し込ま行列を、それはラインのステータスを示します。

だから我々は明らかに、圧力ラインを終えた後、\(N \)数は、各ラインのステータスを示します。すなわち、状態の総数である\(N-2 ^ \)

また、ので、それは右に置くと、それを処理するために、その後、最初のそのような法的地位をままにすることはできません。

考慮されていき\(DP \)

各行(圧縮された状態)を介して、各状態のために、ステータスに対応することができるものを列挙し、その次の行の状態が対応することができます。私たちは、正規のプログラムブール配列であなたの経験の前に置くことができます。

だから我々は最初の合法的な状態を選択する必要があります。第二に、この状態は、タイトルに植えられた地域の地図を与えることはできません。我々は使用することができます\(J&MP [i]を == jは\)を法的かどうかを判断します。

それでは次の行の状態を列挙。明らかに、最大2行下に隣接することはできません\(1 \)を、\ (J&K \)ができます。

そして、それは、累積状態に愛されています。

トピックが行わ。左右の判決なお、これらのことができます。

$ I&(I << 1)== 0 $ \(&& \) \(I&(I >> 1)== 0 \)

優先順位、習慣の括弧に注意してください。

\(コード:\)

#include<iostream>
using namespace std;
int n,m,a[20][20],mp[20];
int dp[20][5000],Ans;
bool state[5000];
const int Hws=100000000;
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
            scanf("%d",&a[i][j]);
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
            mp[i]=(mp[i]<<1)+a[i][j];
    for(int i=0;i<(1<<m);++i)if(((i&(i<<1))==0)&&((i&(i>>1)))==0)state[i]=1;
    dp[0][0]=1;
    for(int i=1;i<=n;++i){
        for(int j=0;j<(1<<m);++j)
            if(state[j]&&((j&mp[i])==j)){
                for(int k=0;k<(1<<m);++k)
                    if((k&j)==0){
                        dp[i][j]+=dp[i-1][k];
                        dp[i][j]%=Hws;
                    }
            }
    }
    for(int i=0;i<(1<<m);++i)Ans+=dp[n][i],Ans%=Hws;
    printf("%d\n",Ans);
    return 0;
}

おすすめ

転載: www.cnblogs.com/h-lka/p/11402173.html