【LUOGU P1373】小a和uim之大逃离(递推dp)

传送门QWQ

dp[i][j][h][l] 表示在点 (i,j),差值为h,小A还是uim取液体的方案数(0:小A 1:uim)

转移方程:

dp[i][j][h][1]+=(dp[i-1][j][(h-a[i][j]+k)%k][0])

dp[i][j][h][1]+=(dp[i][j-1][(h-a[i][j]+k)%k][0]

dp[i][j][h][0]+=(dp[i-1][j][(h+a[i][j])%k][1])

dp[i][j][h][0]+=(dp[i][j-1][(h+a[i][j])%k][1])

初始化:dp[i][j][a[i][j]][0]=1; 一开始小A可以从任意点开始

我一开始一直在纠结A吸毒液和B吸毒液的区别 一直想不通为什么一个是+a[i][j],一个是-a[i][j],其实很简单,因为两个人是A取一次 B再取一次的 A吸毒液 相当于给整体的差值加了k B吸毒液 相当于给整体的差值减了k

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define N 805
#define mod 1000000007
using namespace std;
int n,m,K,a[N][N],dp[N][N][18][2];  //0:小A 1:uim 
typedef long long ll;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);cout.tie(NULL);
    
    cin>>n>>m>>K;
    K++;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>a[i][j]; 
            dp[i][j][a[i][j]][0]=1;
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            for(int k=0;k<=K-1;k++)
            {
            
                dp[i][j][k][0]=(dp[i][j][k][0]+dp[i-1][j][(k-a[i][j]+K)%K][1])%mod;
                dp[i][j][k][0]=(dp[i][j][k][0]+dp[i][j-1][(k-a[i][j]+K)%K][1])%mod;
                
                dp[i][j][k][1]=(dp[i][j][k][1]+dp[i-1][j][(k+a[i][j])%K][0])%mod;
                dp[i][j][k][1]=(dp[i][j][k][1]+dp[i][j-1][(k+a[i][j])%K][0])%mod;
            }
        }
    }
    ll ans=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            ans=(ans+ll(dp[i][j][0][1]))%mod;
        }
    cout<<ans<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值