• 大逃离


    【题目描述】

    地面上出现了一个n*m的矩阵,矩阵的每个格子上有不等量(0~k)的魔液。

    小A和小B各有一个魔瓶,他们可以从矩阵的任一个格子开始,每次向右或向下走一步,从任一个格子结束。开始时小A用魔瓶吸收地面上的魔液,下一步由小B吸收,如此交替下去,并且要求最后一步必须由小B吸收。魔瓶只有k的容量,也就是说,如果装了k+1那么魔瓶会被清空成零,如果装了k+2就只剩下1,依次类推。

    现在询问要想使他们俩的魔瓶中魔液一样多有多少种方法。

    【输入描述】

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

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

    【输出描述】

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

    【输入样例】

    2 2 3

    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。

    源代码:
    
    #include<cstdio>
    #define INF 1000000007
    int i[801][801],f[801][801][16][2]; //可得好生看着点数据范围。
    int n,m,k;
    int main()
    {
        scanf("%d%d%d",&n,&m,&k);
        for (int a=0;a<n;a++)
          for (int b=0;b<m;b++) //注意读入范围。
          {
            scanf("%d",&i[a][b]);
            f[a][b][i[a][b]][0]=1; //初始化赋值,可能从任意一个格子出发。
          }
        k++; //改变一下值,瓶子方便清零。
        for (int a=0;a<n;a++)
          for (int b=0;b<m;b++)
            for (int c=0;c<k;c++) //再循环k就和0重复啦。
            {
                int &Ans1=f[a][b][c][0]; //偷懒的好办法。
                int &Ans2=f[a][b][c][1];
                if (a) //范围而已,同理于下。
                {
                    Ans1=(Ans1+f[a-1][b][(c-i[a][b]+k)%k][1])%INF;
                    Ans2=(Ans2+f[a-1][b][(c+i[a][b])%k][0])%INF;
                }
                if (b)
                {
                    Ans1=(Ans1+f[a][b-1][(c-i[a][b]+k)%k][1])%INF;
                    Ans2=(Ans2+f[a][b-1][(c+i[a][b])%k][0])%INF;
                }
            }
        int Ans=0;
        for (int a=0;a<n;a++)
          for (int b=0;b<m;b++)
            Ans=(Ans+f[a][b][0][1])%INF; //符合条件的方案数之和。
        printf("%d",Ans);
        return 0;
    }
    
    /*
        第一眼就想**DP,然而并没有多少时间留给我。
        类似于棋盘DP,设f[i][j][k][l]为走到(i,j),小A与小B相差为k时的方案数,l=0表示小A最后走,l=1表示小B最后走。
    */
  • 相关阅读:
    file_zilla 通过key连接远程服务器
    git 恢复丢失的文件
    花括号中的json数据--->转为数组array
    3种日志类型,微信付款反馈-->写入txt日志
    清空数据库中所有表--连表删除
    冒泡排序, 使用最低票价.---双重循环,一重移动次数.二重移动
    navicat 连接远程mysql
    付款前.检查状态.防止重复付款,需要ajax设置为同步,等待ajax返回结果再使用
    反射
    设计模式六大原则
  • 原文地址:https://www.cnblogs.com/Ackermann/p/5813130.html
Copyright © 2020-2023  润新知