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. C# POST 表单发送文件

    表单提交协议规定:要先将 HTTP 要求的 Content-Type 设为 multipart/form-data,而且要设定一个 boundary 参数,这个参数是由应用程序自行产生,它会用来识别每 ...

  2. oracle使用日期

    当使用日期是,需要注意如果有超过5位小数加到日期上, 这个日期会进到下一天! 例如: 1. SELECT TO_DATE(‘01-JAN-93’+.99999) FROM DUAL; Returns: ...

  3. js后端返回一个时间戳,用原生怎么对时间进行格式化?

    function fn(time) { var date = new Date(time); var len = time.toString().length; // 时间戳不足13位则在后面加零 i ...

  4. [C++] 自动关闭右下角弹窗

    最近腾讯.迅雷等各种客户端,都越发喜欢在屏幕的右下角弹框了. 有骨气的人当然可以把这些软件卸载了事,但是这些客户端在某些情况下却又还是有用的.怎么办呢? 作为码农,自己实现一个自动关闭右下角弹窗的程序 ...

  5. [转]ECMAScript 2016,2017 和 2018 中所有新功能的示例

    很难追踪 JavaScript(ECMAScript)中的新功能. 想找到有用的代码示例更加困难. 因此,在本文中,我将介绍 TC39 已完成 ES2016,ES2017 和 ES2018(最终草案) ...

  6. CF1055F Tree and XOR

    CF1055F Tree and XOR 就是选择两个数找第k大对儿 第k大?二分+trie上验证 O(nlognlogn) 直接按位贪心 维护可能的决策点(a,b)表示可能答案的对儿在a和b的子树中 ...

  7. 解决 npm run dev b报错 “'webpack-dev-server' 不是内部或外部命令,也不是可运行的程序 或批处理文件。”

    摘自:https://www.cnblogs.com/laraLee/p/9174383.html 前提: 电脑已经安装了nodeJS和npm,  项目是直接下载的zip包. 在项目目录下运行“npm ...

  8. linux 每-CPU 的变量

    每-CPU 变量是一个有趣的 2.6 内核的特性. 当你创建一个每-CPU 变量, 系统中每个处理 器获得它自己的这个变量拷贝. 这个可能象一个想做的奇怪的事情, 但是它有自己的优点. 存取每-CPU ...

  9. Latex 公式速查

    本文记录了一些常用的数学公式对应的 Latex 字符,用于快速查找需要的字符 所有的在 Latex 使用的字符公式,都需要放在\(和\),$ 和 $,\begin{math} 和\end{math}之 ...

  10. [wireshark] ip filter

    查ip 时,使用 ip==10.224.37.18 发现无效 使用 ip.dst, 查到了 Match destination: ip.dst == x.x.x.x Match source: ip. ...