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

    原题链接

    题目背景

    小a和uim来到雨林中探险。突然一阵北风吹来,一片乌云从北部天边急涌过来,还伴着一道道闪电,一阵阵雷声。刹那间,狂风大作,乌云布满了天空,紧接着豆大的雨点从天空中打落下来,只见前方出现了一个披头散发、青面獠牙的怪物,低沉着声音说:“呵呵,既然你们来到这,只能活下来一个!”。小a和他的小伙伴都惊呆了!

    题目描述

    瞬间,地面上出现了一个n*m的巨幅矩阵,矩阵的每个格子上有一坨0~k不等量的魔液。怪物各给了小a和uim一个魔瓶,说道,你们可以从矩阵的任一个格子开始,每次向右或向下走一步,从任一个格子结束。开始时小a用魔瓶吸收地面上的魔液,下一步由uim吸收,如此交替下去,并且要求最后一步必须由uim吸收。魔瓶只有k的容量,也就是说,如果装了k+1那么魔瓶会被清空成零,如果装了k+2就只剩下1,依次类推。怪物还说道,最后谁的魔瓶装的魔液多,谁就能活下来。小a和uim感情深厚,情同手足,怎能忍心让小伙伴离自己而去呢?沉默片刻,小a灵机一动,如果他俩的魔瓶中魔液一样多,不就都能活下来了吗?小a和他的小伙伴都笑呆了!

    现在他想知道他们都能活下来有多少种方法。

    输入输出格式

    输入格式:

    第一行,三个空格隔开的整数n,m,k

    接下来n行,m列,表示矩阵每一个的魔液量。同一行的数字用空格隔开。

    输出格式:

    一个整数,表示方法数。由于可能很大,输出对1 000 000 007取余后的结果。

    输入输出样例

    输入样例#1: 复制
    2 2 3
    1 1
    1 1
    
    输出样例#1: 复制
    4
    

    说明

    【样例解释】

    样例解释:四种方案是:(1,1)->(1,2),(1,1)->(2,1),(1,2)->(2,2),(2,1)->(2,2)。

    【数据范围】

    对于20%的数据,n,m<=10,k<=2

    对于50%的数据,n,m<=100,k<=5

    对于100%的数据,n,m<=800,1<=k<=15

    题解

    看到这个题面很快就能想到动态规划,也不难想出五维dp的做法:

    设计$f_{i,j,k,l,p}$表示方案数

    $i,j$表示当前位置为$(i,j)$($i,jin[1,800]$)

    $k,l$分别表示小a和uim的魔夜量($k,lin[0,15]$注意此处包括$15$,因为实际的模数是$k+1$)

    $p$表示当前的轮次,$p=0$则轮到小a走,$p=1$则轮到uim走

    最终答案是$Sigma_{i=1}^{n}{Sigma_{j=1}^{m}{Sigma_{l=0}^{k-1}{f_{i,j,l,l,1}}}}$

    但很显然,这样设计状态会爆空间,必须减少一维。观察以上式子,会发现答案中两个l显得莫名其妙。因为我们只关心两人的魔力是否相等并不关心它们的具体数值。故我们将这两维状态变成一个$k=k-l$。显然,这在经历模数后不能表示准确的状态,因为信息量有所减少,但$k eq0$时,两人魔力一定不相等,否则必然相等,且每次叠加后差仍然是正确的,所以这种方法必然有效。

    故可设计状态为:

    设计$f_{i,j,k,l,p}$表示方案数

    $i,j$表示当前位置为$(i,j)$($i,jin[1,800]$)

    $k$表示小a和uim的魔夜量之差($kin[0,15]$注意此处包括$15$,因为实际的模数是$k+1$)

    $p$表示当前的轮次,$p=0$则轮到小a走,$p=1$则轮到uim走

    最终答案是$Sigma_{i=1}^{n}{Sigma_{j=1}^{m}{f_{i,j,0,1}}}$

    有初始化

    for(int i=1;i<=N;i++)
        for(int j=1;j<=M;j++){
            scanf("%d",a[i]+j);
            f[i][j][modk(a[i][j])][0]=1;
        }

    有状态转移方程

    for(int i=1;i<=N;i++)
        for(int j=1;j<=M;j++){
            for(int k=0;k<K;k++){
                /*0:a 1:uim  k->a*/
                if(i>1){/*from above*/
                    add(f[i][j][k][0],f[i-1][j][modk(k-a[i][j])][1]);
                    add(f[i][j][k][1],f[i-1][j][modk(k+a[i][j])][0]);
                }
                if(j>1){/*from backward*/
                    add(f[i][j][k][0],f[i][j-1][modk(k-a[i][j])][1]);
                    add(f[i][j][k][1],f[i][j-1][modk(k+a[i][j])][0]);
                }
            }
            add(ans,f[i][j][0][1]);
        }

    最终程序就很简单了

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int MOD=1e9+7,MAXN=805,MAXK=16;
     4 int N,M,K,a[MAXN][MAXN];
     5 int f[MAXN][MAXN][MAXK][2],ans;
     6 inline int modk(int x){/*MOD into 0~k-1*/
     7     return (x+K)%K;
     8 }
     9 inline void add(int &x,int y){
    10     x=(x+y)%MOD;
    11 }
    12 int main(){
    13 //    freopen("1.in","r",stdin);
    14 //    freopen("2.out","w",stdout);
    15     scanf("%d%d%d",&N,&M,&K);
    16     K++;
    17     for(int i=1;i<=N;i++)
    18         for(int j=1;j<=M;j++){
    19             scanf("%d",a[i]+j);
    20             f[i][j][modk(a[i][j])][0]=1;
    21         }
    22 
    23     for(int i=1;i<=N;i++)
    24         for(int j=1;j<=M;j++){
    25             for(int k=0;k<K;k++){
    26                 /*0:a 1:uim  k->a*/
    27                 if(i>1){/*from above*/
    28                     add(f[i][j][k][0],f[i-1][j][modk(k-a[i][j])][1]);
    29                     add(f[i][j][k][1],f[i-1][j][modk(k+a[i][j])][0]);
    30                 }
    31                 if(j>1){/*from backward*/
    32                     add(f[i][j][k][0],f[i][j-1][modk(k-a[i][j])][1]);
    33                     add(f[i][j][k][1],f[i][j-1][modk(k+a[i][j])][0]);
    34                 }
    35             }
    36             add(ans,f[i][j][0][1]);
    37         }
    38 
    39     printf("%d",ans);
    40     return 0;
    41 }
    View Code
  • 相关阅读:
    因子和阶乘
    周期串
    字符串~键盘错位
    6174问题
    HDU_1015——撬锁,5循环
    HDU_1372——骑士移动,二维空间BFS
    HDU_1372——骑士移动,BFS非模版
    HDU_2001——计算两点之间的距离
    HDU_2212
    HDU_1999——不可摸数
  • 原文地址:https://www.cnblogs.com/guoshaoyang/p/11114213.html
Copyright © 2011-2022 走看看