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

    洛谷 P1373 小a和uim之大逃离

    思路

    吐槽

    吐槽:话说不应该是他俩都得die嘛qwq

    咋做

    一道(DP)好题.

    我们用(f[i][j][q][p])来表示:走到第(i)行第(j)列魔液差距值为(q)且当前为(p)走的方案数((pin {0, 1} p=0)表示目前为小(a)走,(p=1)表示目前为(uim)走)

    初始条件:(f[i][j][a[i][j]][0]=1)表示小(a)从每个点开始取,差距值为(a[i][j])的方案数为(1)

    那么我们可以想出转移方程:

    [f[i][j][p][0]+=f[i-1][j][p-a[i][j]][1]+f[i][j-1][p-a[i][j]][1] ]

    这个式子表示目前在第(i)行第(j)列,差距值为(p),当前小(a)走的方案数,因为只能往右走或往下走,且上一步一定是(uim)走的,所以可以从第(i-1)行第(j)列、第(i)行第(j-1)列转移过来,差距值增大

    [f[i][j][p][1]+=f[i-1][j][p+a[i][j]][0]+f[i][j-1][p-a[i][j]][0] ]

    同理,这个式子表示目前在第(i)行第(j)列,差距值为(p),当前(uim)走的方案数,上一步一定是小(a)走的,所以可以从第(i-1)行第(j)列、第(i)行第(j-1)列转移过来,差距值减小

    我们容易想出,最后的答案就是(sum_{i = 1}^{n}sum_{j = 1}^{m}f[i][j][0][1])最后一维是(1)是因为最后一步只能由(uim)

    空间复杂度(n*m*k*2)刚好可以,时间复杂度(O(n*m*k))可以过

    注意!

    1. 因为魔液值到达(k+1)之后就会清(0),所以在过程中要随时对(k+1)取模
    2. 空间开好!!不要开太大!因为最后一维只用(0、1),所以开(2)的数组就好了就行了,开(3)(MLE)
    3. 码风丑陋,谨慎阅读(qwq)

    代码

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int B = 20;
    const int A = 800 + 7;
    const int mod = 1e9 + 7;
    const int inf = 0x3f3f3f3f;
    
    inline int read() {
    	char c = getchar(); int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    	return x * f;
    }
    
    int n, m, k, a[A][A], f[A][A][B][2];
    
    int main() {
    	n = read(), m = read(), k = read() + 1;
    	for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) a[i][j] = read(), f[i][j][a[i][j] % k][0] = 1;
    	for(int i = 1; i <= n; i++)
    		for(int j = 1; j <= m; j++)
    			for(int p = 0; p <= k; p++) {
    				f[i][j][p][0] = (f[i][j][p][0] + f[i - 1][j][(p - a[i][j] + k) % k][1] + f[i][j - 1][(p - a[i][j] + k) % k][1]) % mod;
    				f[i][j][p][1] = (f[i][j][p][1] + f[i - 1][j][(p + a[i][j] + k) % k][0] + f[i][j - 1][(p + a[i][j] + k) % k][0]) % mod;
    			}
    	int ans = 0;
    	for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) ans += f[i][j][0][1], ans %= mod;
    	cout << ans << '
    ';
    	return 0;
    }
    
  • 相关阅读:
    不要再浪费时间阅读文献技巧本
    Reporting Services 中的分页方式Report Builder 3.0
    国外实时数据库比较
    转VS2010 C++下编译调试MongoDB源码 代震军
    C#中异步和多线程的区别
    Python seems amazing!
    嵌入式(armcc)自动调用函数
    MSSQL2008 日志文件收缩
    萝卜地...分享;
    Apache配置多个站点;
  • 原文地址:https://www.cnblogs.com/loceaner/p/12141671.html
Copyright © 2011-2022 走看看