1. 程式人生 > >洛谷OJ 1373 小a和uim之大逃離 DP

洛谷OJ 1373 小a和uim之大逃離 DP

方法 blog brush cnblogs 計算 memset end namespace cpp

https://www.luogu.org/problem/show?pid=1373

題意:n*m地圖,n,m<=800,起點,終點任意,兩個人每次輪流取出點中的數並膜K,問走奇數次 兩人取值相同的方法數?
只關心兩人取的值是否相等,則記錄差值即可
起點和終點任意 則設狀態dp[i][j][k][p] 到達點(i,j)差值為k 並且由p取數的方法數
不用枚舉起點,暴力把所有狀態的方案都計算出來即可,復雜度為O(n*m*k)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int N=805;
int dp[N][N][16][2],n,m,k,a[N][N];
int main()
{
	while(cin>>n>>m>>k)
	{
		ll ans=0;
		memset(dp,0,sizeof(dp));
		for(int i=1;i<=n;i++)
			for(int j=1;j<=m;j++)
				scanf("%d",&a[i][j]),dp[i][j][a[i][j]][0]=1;
		k++;// 
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				for(int l=0;l<k;l++)
				{
					//eg:設a得分為s,b得分為t,a-b的差=l-> s-(t+a[i][j]) =l 上局為s-t=l+a[i][j] 
					
					dp[i][j][l][1]=(dp[i][j][l][1]+dp[i-1][j][(l+a[i][j])%k][0]+dp[i][j-1][(l+a[i][j])%k][0])%mod;
					
					//eg:a-b  s+a[i][j]-t=l  s-t=l-a[i][j]
					int pre=(l-a[i][j]+k)%k;
					dp[i][j][l][0]=(dp[i][j][l][0]+dp[i-1][j][pre][1]+dp[i][j-1][pre][1])%mod;
				}
			}
		}
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				ans=(ans+dp[i][j][0][1])%mod;
			}
		}
		cout<<ans<<endl;
	}
	return 0;	
}

  

洛谷OJ 1373 小a和uim之大逃離 DP