bzoj4806 炮——DP

本文介绍了一种使用状态压缩动态规划(状压DP)解决炮兵布阵问题的方法,通过优化关注炮的数量而非位置,简化了问题复杂度。文章详细解释了状态转移方程,并提供了完整的代码实现。

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4806

看到这题首先会想到状压什么乱七八糟的,然而很难做;

其实,因为求的是方案数,所以并不需要关注炮摆放的位置,而只需要关注数量;

f[i][j][k] 表示第 i 行及以前共有 j 个有 0 炮的列和 k 个有 1 炮的列,就可以转移了。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
int const mod=999983,maxn=105;
ll n,m,f[maxn][maxn][maxn],ans;
ll C(ll x){return ((x-1)*x/2)%mod;}//不是(x+1) !!
int main()
{
    scanf("%d%d",&n,&m);
    f[0][m][0]=1;
    for(int i=1;i<=n;i++)
        for(int j=0;j<=m;j++)//0
            for(int k=0;k<=m-j;k++)//1
            {
                (f[i][j][k]+=f[i-1][j][k])%=mod;//放0个
                if(k>=0&&j<m)(f[i][j][k]+=f[i-1][j+1][k-1]*(j+1))%=mod;//0 -> 1   //别写成 if(k&&j<m) !!
                if(k<m)(f[i][j][k]+=f[i-1][j][k+1]*(k+1))%=mod;//1 -> 2
                if(j<m)(f[i][j][k]+=f[i-1][j+1][k]*(j+1)*k)%=mod;//0 1 -> 1 2 
                if(k-2>=0&&j+2<=m)(f[i][j][k]+=f[i-1][j+2][k-2]*C(j+2))%=mod;//0 0 -> 1 1
                if(k+2<=m)(f[i][j][k]+=f[i-1][j][k+2]*C(k+2))%=mod;//1 1 -> 2 2
            }
    for(int j=0;j<=m;j++)
        for(int k=0;k<=m;k++)
            (ans+=f[n][j][k])%=mod;
    printf("%lld",ans);
    return 0;
}

 

转载于:https://www.cnblogs.com/Zinn/p/9163646.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值