• [luogu1373]小a和uim之大逃离_动态规划


    auim之大逃离

        题目大意:有一个n*m的矩阵。每个格子上有一坨0~k不等量的权值。有两个人,每个人任选一个格子作为出发点,并只能向下或向右走。求最后两个人所得到的权值mod k相等的方案数。

        注释:$1le n,mle 800$,$1le k le 15$。

          想法:dp。

            状态:dp[i][j][k][0/1]表示在点 (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])

               uim取,差值就变小了

              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])
              小A取
              dp[i][j][h][0]+=(dp[i][j-1][(h+a[i][j])%k][1])
              初始化:dp[i][j][a[i][j]][0]=1;
              一开始小A可以从任意点开始

        最后,附上丑陋的代码... ...

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define mod 1000000007 
    #define N 805
    #define K 20  
    using namespace std;
    typedef long long ll;
    int a[N][N];
    int dp[N][N][K][2];
    int n,m,k;
    // void right()
    // {
    // 	for(int i=1;i<=n;i++)
    // 	{
    // 		for(int j=1;j<=m;j++)
    // 		{
    // 			cout << i << " , " << j << " : " ;
    // 			for(int h=0;h<k;h++)
    // 			{
    // 				cout << dp[i][j][h][1] << " " ;
    // 			}
    // 			cout << endl ;
    // 		}
    // 	}
    // }
    int main()
    {
    	cin >> n >> m >> k ; k ++ ;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=m;j++)
    		{
    			scanf("%d",&a[i][j]);
    		}
    	}
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=m;j++)
    		{
    			dp[i][j][a[i][j]%k][0]=1;
    		}
    	}
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=m;j++)
    		{
    			for(int h=0;h<=k;h++)
    			{
    				dp[i][j][h][0]=(dp[i][j][h][0]+dp[i-1][j][(h-a[i][j]+k)%k][1])%mod;
    				dp[i][j][h][0]=(dp[i][j][h][0]+dp[i][j-1][(h-a[i][j]+k)%k][1])%mod;
    				dp[i][j][h][1]=(dp[i][j][h][1]+dp[i-1][j][(h+a[i][j])%k][0])%mod;
    				dp[i][j][h][1]=(dp[i][j][h][1]+dp[i][j-1][(h+a[i][j])%k][0])%mod;
    			}
    		}
    	}
    	ll ans=0;
    	// right();
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=m;j++)
    		{
    			ans=(ans+dp[i][j][0][1])%mod;
    		}
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    

        小结:注意dp时的最后一维是0还是1,考虑转移的时候容易gg

  • 相关阅读:
    [LeetCode 220.] 存在重复元素 III
    C++ 构造函数 & 析构函数
    [LeetCode 891.] 子序列宽度之和【hard】
    [LeetCode 447.] Number of Boomerangs
    HJ93 数组分组
    HJ77 火车进站
    [LeetCode 338.] 比特位计数
    线段树
    大数量问题的一般解决方法
    字典树
  • 原文地址:https://www.cnblogs.com/ShuraK/p/9023011.html
Copyright © 2020-2023  润新知