1087 bzoj(圧力DPなど)

ポータル

質問の意味:

あなたを与える\(N * N \)グリッドを、最初の場合は\(私は\)片に正方形、8つの方向ユニコムポーンを配置することができない、置か尋ねる(k個\)を\のプログラムのいくつかの部分を。

分析:

明らかにすることができます(DP \)を\、およびので\(N \)が非常に小さいので、我々は、使用される圧縮方法を述べることができます。セット\(DP [I] [状態 ] [K] \) 現在のセクションのための\(Iは、\)のステータスライン\(状態\)に置かれたとき\(K \)プログラムの個数。

現在明らかに最初からi行目の状態、することができます\(I-1 \)から転送されたステータス行がありますが、中国聯通は、8個を持つことができない会いたいので、我々は圧力好きなので\(状態[I]を\) そして\(状態[J] \) 限り満足\(状態[I] \&(状態[I] << 1)\)、\ (状態[J] \&(状態[J] << 1) \)、\ (状態[I] \&(状態[J] << 1)\)、\ (状態[I] \&(状態[J] >> 1)\)、\ (状態[I] \ &状態[J] \)よりも大きい\(0 \)ことができます。最終的に状態遷移方程式がある:\(DP [I] [州[I] [ 'ビット(状態[I])+ K] + = DP [I-1] ['ビット(状態[J])] [K] \ )

合計時間の複雑さがある:\(\ mathcal {O}(2 ^ {N-2} * K *)\)

コード:

#include <bits/stdc++.h>
#define maxn 10
using namespace std;
long long dp[maxn][1<<maxn][maxn*maxn];
int getbit(int x){
    int res=0;
    while(x){
        if(x&1) res++;
        x>>=1;
    }
    return res;
}
int main()
{
    int n,k;
    memset(dp,0,sizeof(dp));
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){
        int all=1<<n;
        for(int j=0;j<all;j++){
            if(j&(j<<1)) continue;
            if(i==1){
                if(getbit(j)<=k) dp[i][j][getbit(j)]++;
                continue;
            }
            for(int kk=0;kk<all;kk++){
                if(kk&(kk<<1)) continue;
                if((j&kk)||(j&(kk<<1))||(j&(kk>>1))) continue;
                for(int ll=0;ll<=k;ll++){
                    dp[i][j][getbit(j)+ll]+=dp[i-1][kk][ll];
                }
            }
        }
    }
    long long res=0;
    int all=1<<n;
    for(int i=0;i<all;i++){
        res+=dp[n][i][k];
    }
    printf("%lld\n",res);
    return 0;
}

おすすめ

転載: www.cnblogs.com/Chen-Jr/p/11289702.html