石头游戏
Marble
【问题描述】
石头游戏的规则是这样的。
石头游戏在一个 n 行 m 列的方格阵上进行。每个格子对应了一个编号在
0~9 之间的操作序列。
操作序列是一个长度不超过 6 且循环执行、每秒执行一个字符的字符串。
它包括:
数字 0~9:拿 0~9 个石头到该格子。
NWSE:把这个格子内所有的石头推到相邻的格子。
D:拿走这个格子的石头。
石头游戏的问题是:当这个石头游戏进行了 t 秒之后,所有方格中最多的格
子有多少个石头。
注意:所有格子的操作同时执行。
【 输入文件】 】
第一行三个整数n, m, t, act。
接下来n行,每行m个字符,表示每个格子对应的操作序列。
最后act行,每行一个字符串,表示从0开始的每个操作序列。
【 输出文件】 】
一个整数:游戏进行了 t 秒之后,所有方格中最多的格子有多少个石头。
【 样例输入】 】
1 6 10 3
011112
1E
E
0
【 样例输出】 】
3
【样例 解释 】
这是另一个类似于传送带的结构。左边的设备 0 间隔地产生石头并向东传
送。设备 1 向右传送,直到设备 2。10 秒后,总共产生了 5 个石头,2 个在传
送带上,3 个在最右边。
【 数据约定】 】
0≤n, m≤8。
1≤act≤10。
1≤t≤10 9 。
对于 30%的数据有 t≤10 5 。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <ctime>
using namespace std;
const int N=80;
struct Matrix
{
int r,c;
long long mat[N][N];
Matrix(int r_=0,int c_=0)
{
memset(mat,0,sizeof(mat));
r=r_;
c=c_;
}
friend Matrix operator*(Matrix a,Matrix b)
{
Matrix c(a.r,b.c);
for(int i=1; i<=a.r; i++)
for(int j=1; j<=b.c; j++)
for(int k=1; k<=a.c; k++)
c.mat[i][j]+=a.mat[i][k]*b.mat[k][j];
return c;
}
friend Matrix operator^(Matrix a,int k)
{
Matrix c(a.r,a.c);
for(int i=1; i<=a.r; i++)c.mat[i][i]=1;
for(; k; k>>=1,a=a*a)if(k&1)c=c*a;
return c;
}
};
char op[N][65],map[N][N];
int len[N],n,m,k,t;
int id[N][N],idx;
int main()
{
freopen("marble.in","r",stdin);
freopen("marble.out","w",stdout);
scanf("%d%d%d%d",&n,&m,&k,&t);
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
id[i][j]=++idx;
for(int i=1; i<=n; i++)
scanf("%s",map[i]+1);
for(int i=1; i<=t; i++)
{
scanf("%s",op[i]+1);
len[i]=strlen(op[i]+1);
for(int j=len[i]+1; j<=60; j++)
op[i][j]=op[i][(j-1)%len[i]+1];
}
Matrix A(n*m+10,n*m+10);
Matrix B(n*m+10,n*m+10);
for(int i=1; i<=n*m+10; i++)A.mat[i][i]=1;
Matrix C(n*m+10,1);
for(int i=0; i<=9; i++)C.mat[n*m+i+1][1]=i;
int powx=k/60,powy=k%60;
for(int tim=1; tim<=60; tim++)
{
Matrix tmp(n*m+10,n*m+10);
for(int i=1; i<=n*m+10; i++)
tmp.mat[i][i]=1;
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
{
int p=id[i][j];
char c=op[map[i][j]-'0'+1][tim];
if(c>='0'&&c<='9')
{
tmp.mat[p][n*m+c-47]+=1;
}
else if(c=='D')tmp.mat[p][p]=0;
else
{
tmp.mat[p][p]=0;
if(c=='N')tmp.mat[id[i-1][j]][p]+=1;
if(c=='S')tmp.mat[id[i+1][j]][p]+=1;
if(c=='W')tmp.mat[id[i][j-1]][p]+=1;
if(c=='E')tmp.mat[id[i][j+1]][p]+=1;
}
}
A=tmp*A;
if(powy==tim)
B=A;
}
A=A^powx;
C=A*C;
if(powy)C=B*C;
long long ans=0;
for(int i=1; i<=n*m; i++)
{
//printf("%lld ",C.mat[i][1]);
ans=max(ans,C.mat[i][1]);
}
printf("%lld\n",ans);
return 0;
}
本文介绍了一种基于矩阵快速幂的石头游戏算法实现方法,详细解释了如何通过构建矩阵运算来高效计算复杂游戏状态下石头的最大数量分布。适用于类似游戏场景的状态预测。
1591

被折叠的 条评论
为什么被折叠?



