[BZOJ 1087] 互不侵犯KING

Link:

BZOJ 1087 传送门

Solution:

思路基本上和 POJ 1185 炮兵阵地 完全相同

都是先对每一行的可能状态进行预处理,只不过一个记录最大值一个记录方案数

 

不过再一次写的时候还是犯了几个**错误调了一会……

1、对$k$的枚举要从0开始!

$dp$时很多时候为0的状态都有初始值,一定要考虑边界的取舍

2、位运算的括号问题

一开始$!st[j]\& st[l]$没加括号……

位运算时还是多加一个括号保险吧……

 

Code:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int MAXN=1025;
ll dp[15][MAXN][100],res=0;
int n,m,st[MAXN],sum[MAXN],tot=0;

int cal(int x)
{
    int ret=0;
    for(;x;x>>=1) ret+=(x&1);
    return ret;
}

int main()
{
    scanf("%d%d",&n,&m);
    int MAX=(1<<n)-1;
    
    for(int i=0;i<=MAX;i++)
        if(!(i&(i<<1))) st[++tot]=i,sum[tot]=cal(i),dp[1][tot][sum[tot]]=1;
    
    for(int i=1;i<n;i++) for(int j=1;j<=tot;j++) for(int k=0;k<=m;k++)
        if(dp[i][j][k])
            for(int l=1;l<=tot;l++)
                if(!(st[j]&(st[l]<<1)) && !(st[j]&(st[l]>>1)) && !(st[j]&st[l]))
                    dp[i+1][l][k+sum[l]]+=dp[i][j][k];
    
    for(int i=1;i<=tot;i++)
        res+=dp[n][i][m];
    printf("%lld",res);
    return 0;
}

 

posted @ 2018-07-01 17:02  NewErA  阅读(158)  评论(0编辑  收藏  举报