【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;
}
posted @ 2018-10-19 21:40  Patrickpwq  阅读(75)  评论(0编辑  收藏  举报