[bzoj1087][SCOI2005]互不侵犯King【dp】

【题目描述】
  http://www.lydsy.com/JudgeOnline/problem.php?id=1087
【题解】
  状压dp不解释
  

/* --------------
    user Vanisher
    problem bzoj-1087
----------------*/
# include <bits/stdc++.h>
# define    ll      long long
# define    inf     0x3f3f3f3f
# define    N       11
using namespace std;
ll read(){
    ll tmp=0, fh=1; char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
    while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
    return tmp*fh;
}
ll f[N][N*N][1<<N],cnt[1<<N],n,m,ans,f1[N],f2[N];
bool mp[1<<N][1<<N];
bool check(ll i1, ll i2){
    for (ll i=1; i<=n; i++)
        f1[i]=(((1<<(i-1))&i1)!=0),
        f2[i]=(((1<<(i-1))&i2)!=0);
    for (ll i=1; i<=n; i++)
        if (f1[i]){
            if (f2[i]!=0||f2[i-1]!=0||f2[i+1]!=0)
                return 0;
        }
    for (ll i=2; i<=n; i++)
        if (f1[i]&&f1[i-1]||f2[i]&&f2[i-1])
            return 0;
    return 1;
}
int main(){
    n=read(), m=read();
    f[0][0][0]=1;
    for (ll i=1; i<(1<<n); i++)
        cnt[i]=cnt[i/2]+i%2;
    for (ll i=0; i<(1<<n); i++)
        for (ll j=0; j<(1<<n); j++)
            mp[i][j]=check(i,j);
    for (ll i=1; i<=n; i++){
        for (ll k=0; k<(1<<n); k++){
            ll j=cnt[k];
            for (ll t=j; t<=m; t++){
                for (ll p=0; p<(1<<n); p++){
                    if (mp[p][k]==1)
                        f[i][t][k]=f[i][t][k]+f[i-1][t-j][p];
                }
            }   
        }
    }
    for (ll i=0; i<(1<<n); i++)
        ans=ans+f[n][m][i];
    printf("%lld\n",ans);
    return 0;
}
posted @ 2018-03-06 19:07  Vanisher  阅读(94)  评论(0编辑  收藏  举报