• AcWing 206. 石头游戏 矩阵乘法|矩阵快速幂


    AcWing 206. 石头游戏

    石头游戏在一个 n 行 m 列 (1≤n,m≤8) 的网格上进行,每个格子对应一种操作序列,操作序列至多有10种,分别用0~9这10个数字指明。

    操作序列是一个长度不超过6且循环执行、每秒执行一个字符的字符串。

    每秒钟,所有格子同时执行各自操作序列里的下一个字符。

    序列中的每个字符是以下格式之一:

    1、数字0~9:表示拿0~9个石头到该格子。
    2、NWSE:表示把这个格子内所有的石头推到相邻的格子,N表示上方,W表示左方,S表示下方,E表示右方。
    3、D:表示拿走这个格子的所有石头。

    给定每种操作序列对应的字符串,以及网格中每个格子对应的操作序列,求石头游戏进行了 t 秒之后,石头最多的格子里有多少个石头。

    在游戏开始时,网格是空的。

    输入格式

    第一行4个整数n, m, t, act。

    接下来n行,每行m个字符,表示每个格子对应的操作序列。

    最后act行,每行一个字符串,表示从0开始的每个操作序列。

    输出格式

    一个整数:游戏进行了t秒之后,所有方格中石头最多的格子有多少个石头。

    输入样例:

    1 6 10 3
    011112
    1E
    E
    0
    

    输出样例:

    3
    

    样例解释

    样例中给出了三组操作序列,第一个格子执行编号为0的操作序列”1E”,第二至五个格子执行编号为1的操作序列”E”,第六个格子执行编号为2的操作序列”0”。

    这是另一个类似于传送带的结构,左边的设备0间隔地产生石头并向东传送。

    设备1向右传送,直到设备2。

    10秒后,总共产生了5个石头,2个在传送带上,3个在最右边。

    题解:我们可以把网格看成一维向量,下标从1开始,num(i,j) = (i-1)*m+j;

       我们可以定义一个状态矩阵f,下标从0~n*m,其中f[num(i,j)]记录格子(i,j)中石头个数。

          操作序列长度不超过6,1~6的最小公倍数为60,所以经过60s后所有序列都会处于重新开始的位置。每60s一个循环,我们只需记录第一个60s。

       对于1~60之间的每一秒k,所有格子操作可以构成一个状态矩阵,矩阵行列下标都是0~n*m,构造方法如下:

    1. 若网格(i,j)第k秒的操作字符为“N”,且i>1,则令Ak[num(i,j),num(i-1,j)] = 1,表示把石子推到上面的格子里。“W”、“S”、“E”类似。
    2. 若网格(i,j)第k秒的操作字符为数字x,则令Ak[0,num(i,j)] = x,Ak[num(i,j),num(i,j)] = 1。
    3. 令Ak[0,0] = 1。 (保证f[0]始终为1)
    4. 其他部分赋值为0。

       最后求出f中的最大值。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define maxn 70
    #define mod 1000000007
    #define ll long long 
    int n,m,t,act;
    struct Matrix
    {
        long long ma[maxn][maxn];
        Matrix() {
            memset(ma,0, sizeof(ma));
        }
    }f,e[maxn],d;
    Matrix mul(Matrix A,Matrix B)
    {
        Matrix C;
        for(int i=0;i<maxn;i++)
            for(int j=0;j<maxn;j++)
                for(int k=0;k<maxn;k++)
                    C.ma[i][j] += (A.ma[i][k]*B.ma[k][j]);
        return C;
    }
    Matrix cel(Matrix A,Matrix B) {
        ll w[70]={0};
        for(int j=0;j<=n*m;j++)
            for(int k=0;k<=n*m;k++)
                w[j]+=A.ma[1][k]*B.ma[k][j];
        memcpy(A.ma[1],w,sizeof(w));
        return A;
    }
    Matrix pow_mod(Matrix A,long long t)
    {
        Matrix B = d;
        while(t) {
            if(t&1) A = cel(A,B);  //可直接mul(f,e[i]);
            B=mul(B,B);
            t>>=1;
        }
        return A;
    }
    char s[10][10],cz[maxn][10];
    int len[maxn];
    int num(int i,int j) {return (i-1)*m+j;}
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&t,&act);
        for (int i = 1; i <= n; i++) scanf("%s",s[i]+1);
        for (int i = 0; i < act; i++) scanf("%s",cz[i]),len[i] = strlen(cz[i]);
        for (int k = 1; k <= 60; k++) {
            e[k].ma[0][0] = 1;
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= m; j++) {
                    int x = s[i][j] - '0', y = (k-1)%len[x];
                    if (cz[x][y] >= '0' && cz[x][y] <= '9') {
                        e[k].ma[0][num(i,j)] = cz[x][y]-'0';
                        e[k].ma[num(i,j)][num(i,j)] = 1;
                    } else if (cz[x][y] == 'N' && i-1>0) e[k].ma[num(i,j)][num(i-1,j)] = 1;
                    else if (cz[x][y] == 'W' && j-1>0) e[k].ma[num(i,j)][num(i,j-1)] = 1;
                    else if (cz[x][y] == 'S' && i+1<=n) e[k].ma[num(i,j)][num(i+1,j)] = 1;
                    else if (cz[x][y] == 'E' && j+1<=m) e[k].ma[num(i,j)][num(i,j+1)] = 1;
                }
            }
            if (k == 1) d = e[1];
            else d = mul(d,e[k]);
        }
        ll ans = 0;
        f.ma[1][0] = 1;
        f = pow_mod(f,t/60);
        int z = t%60;
        for (int i = 1; i <= z; i++) f = cel(f,e[i]);  //可直接mul(f,e[i]);
        for (int i = 0; i <= n*m; i++) ans = max(ans,f.ma[1][i]);
        printf("%lld
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    PL/SQL 导入excel表格到oracle数据表
    浏览器进不去网站解决方案
    Tomcat安装后启动一闪而过
    数据库系统Informix为例,介绍改善用户查询计划的方法。
    使用 PREPARE 的几个注意点
    mysqld服务器如何查看使用变量的值
    sessions 表的架构过程
    Apache和mysql的安装设置
    使用SimpleXML应该注意的问题有哪些?
    php phpeclipse + xampp 配置安装过程
  • 原文地址:https://www.cnblogs.com/l999q/p/11309480.html
Copyright © 2020-2023  润新知