*点击

[SCOI2005] 互不侵犯

题目

Description

在 N×N 的棋盘里面放 K 个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共 8 个格子。

Input

只有一行,包含两个数 N,K

Output

所得的方案数

Sample Input

3 2

Sample Output

16

思路

一道状压$dp$题;

因为要求国王数量,所以要多开一维数组记录国王总数;

用$dp[i][j][k]$表示第$i$行的状态$k$,并且到第$i$行为止一共放了$j$国王;

把不符合的国王状态去掉即可;

状态转移方程就为:  $dp[i][j+sum][k]+=dp[i-1][j][l]$

$sum$为当前行的国王数量;

 


 

代码

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll _=10;
ll n,m;
ll a[_][_],dp[_][_*_][1<<9];
int main()
{
    scanf("%lld%lld",&n,&m);
    dp[0][0][0]=1;
    for(ll i=1;i<=n;i++)
    for(ll k=0;k<=(1<<n)-1;k++)
    {
        if(k&(k>>1)) continue;//相邻不能放
        ll sum=0;
        for(ll j=1;j<=n;j++)
        if(k&(1<<(j-1)))
            sum++;//记录当前行国王数量
        for(ll l=0;l<=(1<<n)-1;l++)
        {
            if(k&l||k&(l<<1)||k&(l>>1))//保证两行的国王互不攻击
                continue;
            for(ll j=0;j<=m-sum;j++)//枚举到上一行的所有国王数量
                dp[i][j+sum][k]+=dp[i-1][j][l];
        }
    }
    ll ans=0;
    for(ll i=0;i<=(1<<n)-1;i++)
        ans+=dp[n][m][i];
    printf("%lld",ans);
    return 0;
}

 

 

 

 

 

posted @ 2024-12-16 23:26  木偶人-怪咖  阅读(5)  评论(0编辑  收藏  举报
*访客位置3D地图 *目录