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. laravel 授权使用gate门类

    第一:先注册 第二:使用方式三种 路由中:Route::group(['middleware'=>'can:system'],function() {}) 模板中:@can("syst ...

  2. C#的循环语句(一)

    循环:反复执行某段代码. 循环四要素:初始条件,循环条件,循环体,状态改变.for(初始条件;循环条件;状态改变) {循环体} for 格式: for(int i=1/*初始条件*/;0<=10 ...

  3. Python--day68--Django ORM的字段参数、元信息

    字段参数 null 用于表示某个字段可以为空. unique 如果设置为unique=True 则该字段在此表中必须是唯一的 . db_index 如果db_index=True 则代表着为此字段设置 ...

  4. 如何在SpringMVC项目中部署WebService服务并打包生成客户端

    场景 某SpringMVC项目原本为一个HTTP的WEB服务项目,之后想在该项目中添加WebService支持,使该项目同时提供HTTP服务和WebService服务.其中WebService服务通过 ...

  5. C# GUID ToString

    最近在看到小伙伴直接使用 Guid.ToString ,我告诉他需要使用 Guid.ToString("N") ,为什么需要使用 N ,因为默认的是 D 会出现连字符. Guid ...

  6. sublime text3神器插件

    (首先安装)Package Control  Package Control,就像 Linux 下的 apt-get 和 yum 一样,它是 Sublime Text 的包管理器 1.Emmet 是一 ...

  7. P1074 彩票摇奖

    题目描述 为了丰富人民群众的生活.支持某些社会公益事业,北塔市设置了一项彩票.该彩票的规则是: (1) 每张彩票上印有 7 个各不相同的号码,且这些号码的取指范围为 1~33. (2) 每次在兑奖前都 ...

  8. js三大框架出现的意义

    解决了原始html,css,js的UI与数据状态之间同步的难题,避免了大量的操作DOM代码. 使用了React,Angular和Vue,我们只需要定义一次 UI 界面,不再需要为每个操作编写特定的 U ...

  9. 手把手教你基于koa2,mongoose实现增删改查

    初始化项目 npm init -y 先安装一波乱七八糟的依赖插件(需要具备一定的koa2知识,至于mongoDB自行百度安装教程),模板引擎我使用的是art-template(据说是性能最好的,而且是 ...

  10. git 上传当前分支

    因为我现在的分支是的名很长,每次需要上次当前分支需要写很多代码,是不是有很简单方法上传当前分支. 如果要上传一个分支到仓库 origin 那么就需要使用下面的命令 git push origin 分支 ...