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,, sizeof(ma));
}
}f,e[maxn],d;
Matrix mul(Matrix A,Matrix B)
{
Matrix C;
for(int i=;i<maxn;i++)
for(int j=;j<maxn;j++)
for(int k=;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[]={};
for(int j=;j<=n*m;j++)
for(int k=;k<=n*m;k++)
w[j]+=A.ma[][k]*B.ma[k][j];
memcpy(A.ma[],w,sizeof(w));
return A;
}
Matrix pow_mod(Matrix A,long long t)
{
Matrix B = d;
while(t) {
if(t&) A = cel(A,B); //可直接mul(f,e[i]);
B=mul(B,B);
t>>=;
}
return A;
}
char s[][],cz[maxn][];
int len[maxn];
int num(int i,int j) {return (i-)*m+j;}
int main()
{
scanf("%d%d%d%d",&n,&m,&t,&act);
for (int i = ; i <= n; i++) scanf("%s",s[i]+);
for (int i = ; i < act; i++) scanf("%s",cz[i]),len[i] = strlen(cz[i]);
for (int k = ; k <= ; k++) {
e[k].ma[][] = ;
for (int i = ; i <= n; i++) {
for (int j = ; j <= m; j++) {
int x = s[i][j] - '', y = (k-)%len[x];
if (cz[x][y] >= '' && cz[x][y] <= '') {
e[k].ma[][num(i,j)] = cz[x][y]-'';
e[k].ma[num(i,j)][num(i,j)] = ;
} else if (cz[x][y] == 'N' && i->) e[k].ma[num(i,j)][num(i-,j)] = ;
else if (cz[x][y] == 'W' && j->) e[k].ma[num(i,j)][num(i,j-)] = ;
else if (cz[x][y] == 'S' && i+<=n) e[k].ma[num(i,j)][num(i+,j)] = ;
else if (cz[x][y] == 'E' && j+<=m) e[k].ma[num(i,j)][num(i,j+)] = ;
}
}
if (k == ) d = e[];
else d = mul(d,e[k]);
}
ll ans = ;
f.ma[][] = ;
f = pow_mod(f,t/);
int z = t%;
for (int i = ; i <= z; i++) f = cel(f,e[i]); //可直接mul(f,e[i]);
for (int i = ; i <= n*m; i++) ans = max(ans,f.ma[][i]);
printf("%lld\n",ans);
return ;
}

AcWing 206. 石头游戏 矩阵乘法|矩阵快速幂的更多相关文章

  1. Luogu 3390 【模板】矩阵快速幂 (矩阵乘法,快速幂)

    Luogu 3390 [模板]矩阵快速幂 (矩阵乘法,快速幂) Description 给定n*n的矩阵A,求A^k Input 第一行,n,k 第2至n+1行,每行n个数,第i+1行第j个数表示矩阵 ...

  2. Luogu T7152 细胞(递推,矩阵乘法,快速幂)

    Luogu T7152 细胞(递推,矩阵乘法,快速幂) Description 小 X 在上完生物课后对细胞的分裂产生了浓厚的兴趣.于是他决定做实验并 观察细胞分裂的规律. 他选取了一种特别的细胞,每 ...

  3. bzoj 3240: [Noi2013]矩阵游戏 矩阵乘法+十进制快速幂+常数优化

    3240: [Noi2013]矩阵游戏 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 613  Solved: 256[Submit][Status] ...

  4. poj3613:Cow Relays(倍增优化+矩阵乘法floyd+快速幂)

    Cow Relays Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7825   Accepted: 3068 Descri ...

  5. HDU4965 Fast Matrix Calculation —— 矩阵乘法、快速幂

    题目链接:https://vjudge.net/problem/HDU-4965 Fast Matrix Calculation Time Limit: 2000/1000 MS (Java/Othe ...

  6. BZOJ_1009_[HNOI2008]_GT考试_(动态规划+kmp+矩阵乘法优化+快速幂)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1009 字符串全部由0~9组成,给出一个串s,求一个长度为n的串,不包含s的种类有多少. 分析 ...

  7. bzoj 3240 矩阵乘法+十进制快速幂

    首先,构造出从f[][i]->f[][i+1]的转移矩阵a,和从f[i][m]->f[i+1][1]的转移矩阵b, 那么从f[1][1]转移到f[n][m]就是init*(a^(m-1)* ...

  8. 【HDOJ5950】Recursive sequence(矩阵乘法,快速幂)

    题意:f[1]=a,f[2]=b,f[i]=2f[i-2]+f[i-1]+i^4(i>=3),多组询问求f[n]对2147493647取模 N,a,b < 2^31 思路:重点在于i^4的 ...

  9. 数学--数论--HDU 4675 GCD of Sequence(莫比乌斯反演+卢卡斯定理求组合数+乘法逆元+快速幂取模)

    先放知识点: 莫比乌斯反演 卢卡斯定理求组合数 乘法逆元 快速幂取模 GCD of Sequence Alice is playing a game with Bob. Alice shows N i ...

随机推荐

  1. oracle merge into 新增或者修改

    merge into sn_balance b1 using(select 'admin' as userid,1 as type1 from dual) b2 on(b1.userid=b2.use ...

  2. Python:pip 和pip3的区别

    前言 装完python3后发现库里面既有pip也有pip3,不知道它们的区别,因此特意去了解了一下. 解释 先搜索了一下看到了如下的解释, 安装了python3之后,库里面既会有pip3也会有pip ...

  3. TabHost选项卡的实现(一):使用TabActivity实现

    一. TabHost的基本开发流程 TabHost是一种非常实用的组件,可以很方便的在窗口上防止多个标签页,每个标签页相当于获得了一个外部容器相同大小的组件摆放区域. 我们熟悉的手机电话系统" ...

  4. 洛谷P5019 铺设道路 题解 模拟/贪心基础题

    题目链接:https://www.luogu.org/problemnew/show/P5019 这道题目是一道模拟题,但是它有一点贪心的思想. 我们假设当前最大的深度是 \(d\) ,那么我们需要把 ...

  5. 困扰的问题终于解决了-docker时区不正确的问题修改记

    前一阵子有一台服务器,mysql的时间比北京时间晚了8个小时.我知道是时区的问题,但是不知道为什么弄成这样,宿主机没有问题,后来一看mysql的docker,时区是错的. mybatis-plus打印 ...

  6. webmagic笔记

    在class Spider中有run函数,调用了 processRequest(requestFinal)完成对页面的下载和处理.在这个函数里面先调用downloader.download(reque ...

  7. Roslyn NameSyntax 的 ToString 和 ToFullString 的区别

    本文告诉大家经常使用的 NameSyntax 拿到值的 ToString 和 ToFullString 方法的区别 从代码可以看到 NameSyntax 的 ToString 和 ToFullStri ...

  8. java 面试题之交通灯管理系统

    需求: 交通灯管理系统的项目需求 Ø 异步随机生成按照各个路线行驶的车辆. 例如: 由南向而来去往北向的车辆 ---- 直行车辆 由西向而来去往南向的车辆 ---- 右转车辆 由东向而来去往南向的车辆 ...

  9. P1052 国王放置问题

    题目描述 在n*m的棋盘上放置k个国王,要求k个国王互相不攻击,有多少种不同的放置方法.假设国王放置在第(x,y)格,国王的攻击的区域是:(x-1,y-1), (x-1,y),(x-1,y+1),(x ...

  10. 基于ElementUI封装Excel数据导入组件

    由于前端项目使用的是Vue-cli3.0 + TypeScript的架构,所以该组件也是基于ts语法封装的,组件的完整代码如下: <template> <div id="m ...