zoukankan      html  css  js  c++  java
  • luogu1373 小a和uim之大逃离

    题目大意

      地面上出现了一个n*m的巨幅矩阵,矩阵的每个格子上有一坨0~k不等量的魔液。怪物各给了小a和uim一个魔瓶,说道,你们可以从矩阵的任一个格子开始,每次向右或向下走一步,从任一个格子结束。开始时小a用魔瓶吸收地面上的魔液,下一步由uim吸收,如此交替下去,并且要求最后一步必须由uim吸收。魔瓶只有k的容量,也就是说,如果装了k+1那么魔瓶会被清空成零,如果装了k+2就只剩下1,依次类推。问使两个人内的魔瓶内的魔液一样多的走法有多少种。

    题解

      我们很容易想到动规。用f(i, j, t, k, p)表示在位置(i, j),小a瓶子里有t个魔液,uim瓶子里有k个魔液,p表示当前轮到小a还是uim。一开始我想枚举每一个起始点然后动规,这样的时间复杂度是$O(n^2 m^2 k)$的,这种转移的过程让我在潜意识里认为这道题就应该用Bfs解决,以至于随后想到可以将所有出发点一起整时就是n*m个Bfs同时做,时间复杂度$O(n^2m^2)$。请你想想,这究竟是动规还是暴力呀?

      正确做法是:t和k可以转化为小a和uim瓶子里的液体的差d,这就降了一维;随后我们列出递归式来,根据递归式老老实实刷表即可。

      一些卡常数:要mod K,请(x + k) % k即可,不要(x % k + k) % k,这就慢了;同时,也不要为了取模单独写一个函数,函数调用费时间。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <ctime>
    using namespace std;
    
    const int MAX_ROW = 810, MAX_COL = 810, MAX_K = 20;
    const long long P = 1000000007;
    int TotRow, TotCol, K;
    int A[MAX_ROW][MAX_COL];
    
    long long DP()
    {
    	static int F[MAX_ROW][MAX_COL][MAX_K][2];
    	K++;
    	for (int row = 1; row <= TotRow; row++)
    		for (int col = 1; col <= TotCol; col++)
    			F[row][col][A[row][col]][0] = 1;
    	for (int row = 1; row <= TotRow; row++)
    		for (int col = 1; col <= TotCol; col++)
    			for (int t = 0; t < K; t++)
    			{
    				//当前是小a,下一个是uim
    				F[row + 1][col][(t - A[row + 1][col] + K) % K][1] += F[row][col][t][0];
    				F[row + 1][col][(t - A[row + 1][col] + K) % K][1] %= P;
    				F[row][col + 1][(t - A[row][col + 1] + K) % K][1] += F[row][col][t][0];
    				F[row][col + 1][(t - A[row][col + 1] + K) % K][1] %= P;
    				//当前是uim,下一个是小a
    				F[row + 1][col][(t + A[row + 1][col] + K) % K][0] += F[row][col][t][1];
    				F[row + 1][col][(t + A[row + 1][col] + K) % K][0] %= P;
    				F[row][col + 1][(t + A[row][col + 1] + K) % K][0] += F[row][col][t][1];
    				F[row][col + 1][(t + A[row][col + 1] + K) % K][0] %= P;
    			}
    	long long ans = 0;
    	for (int row = 1; row <= TotRow; row++)
    		for (int col = 1; col <= TotCol; col++)
    			ans = (ans + F[row][col][0][1]) % P;
    	return ans;
    }
    
    int main()
    {
    	scanf("%d%d%d", &TotRow, &TotCol, &K);
    	for (int i = 1; i <= TotRow; i++)
    		for (int j = 1; j <= TotCol; j++)
    			scanf("%d", &A[i][j]);
    	printf("%lld
    ", DP());
    	return 0;
    }
    

      

  • 相关阅读:
    定义Java类的数组的问题
    Ubuntu下将vim配置为Python IDE(转)
    Python数据结构-序列
    Python数据结构-元祖
    Python数据结构-字典
    Python数据结构-序表
    Python的控制结构(转)
    Python面向对象编程
    训练样本集的制作
    matlab读取指定路径下的图像
  • 原文地址:https://www.cnblogs.com/headboy2002/p/9529723.html
Copyright © 2011-2022 走看看