1. 程式人生 > 實用技巧 >洛谷P1373 小a和小uim之大逃離

洛谷P1373 小a和小uim之大逃離

題目連結:https://www.luogu.com.cn/problem/P1373

題意(不想寫了,從某題解裡抄了一份):

兩個人綁在一起走,但是每次吸收的人交換,可以向右向下走,求二者魔瓶內體積相等的方案數目

考慮狀態 dp[i][j][p][0/1],表示走到(i,j)結束,a減去uim的差值為p,最後走的人是a/uim的方案數。首先初始化 dp[i][j][a[i][j]][0]=1; 最終答案為Σdp[i][j][0][1]。有轉移方程(此時已經令k=k+1):

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

(a走最後一步,差值變大了,從p-a[i][j]-->p。但是p-a[i][j]可能<0,所以找到等價的正數)

dp[i][j][p][1]+=( dp[i-1][j][(p+a[i][j])%k][0]+dp[i][j-1][(p+a[i][j])%k][0] ) (uim走最後一步,差值變小)

#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int mod=1e9+7;
const int maxn=800+10;

int a[maxn][maxn];
int dp[maxn][maxn][20][2]; 
int n,m,i,j,k,p,q;

int main(){
	std::ios::sync_with_stdio(false);
	cin>>n>>m>>k; k++; 
	memset(dp,0,sizeof(dp));
	for (i=1;i<=n;i++)
	  for (j=1;j<=m;j++){
	  	cin>>a[i][j];
	  	dp[i][j][a[i][j]][0]=1; //*
	  }
	for (i=1;i<=n;i++)
	  for (j=1;j<=m;j++)
	    for (p=0;p<k;p++){
	      int t1=(p-a[i][j]+k)%k; int t2=(p+a[i][j])%k; //*
	      dp[i][j][p][0]=(dp[i][j][p][0]+dp[i-1][j][t1][1]+dp[i][j-1][t1][1])%mod;
	      dp[i][j][p][1]=(dp[i][j][p][1]+dp[i-1][j][t2][0]+dp[i][j-1][t2][0])%mod;
		}
	ll ans=0;
	for (i=1;i<=n;i++)
	  for (j=1;j<=m;j++)
	    ans=(ans+dp[i][j][0][1])%mod;
	cout<<ans<<endl;
	return 0;
}