# 牛客1024B 石头游戏

## 题目描述

$NWSE$：表示把这个格子内所有的石头推到相邻的格子，$N$表示上方，$W$表示左方，$S$表示下方，$E$表示右方。
$D$：表示拿走这个格子的所有石头。

1 6 10 3
011112
1E
E
0

3

## 题解

• 当操作$s[i]$为数字，$c[pos][0,(i,j)]=s[i]$$c[pos][(i,j),(i,j)]=1$
• 当操作$s[i]=S,E,W,N$时，设移动后的位置为$(x,y)$$c[pos][(i,j),(x,y)]=1$
• 当操作$s[i]=D$时，$c[pos][(i,j),(i,j)]=0$

$C=\prod _{i=1}^{60} c_i$$r=T \mod 60$，那么答案即为$f*C*\prod _{i=1}^r c_r$

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 110;

ll T;
int n, m, lim, len[N], act, now[10][10];
char s[10][10], t[10][10];

struct mat {
ll a[65][65];
mat() {memset(a, 0, sizeof(a));}
mat operator * (mat &x) {
mat ans;
for(int i = 0; i <= lim; ++i)
for(int j = 0; j <= lim; ++j)
for(int k = 0; k <= lim; ++k)
ans.a[i][j] += a[i][k] * x.a[k][j];
return ans;
}
mat Pow(ll t, mat a) {
mat ans; ans.a[0][0] = 1;
while(t) {
if(t & 1) ans = ans * a;
a = a * a; t >>= 1;
}
return ans;
}
}c[61], C;

int idx(int x, int y) {return (x - 1) * m + y;}

void print(mat x, bool flag) {
puts("#####################");
if(flag) {
for(int i = 0; i <= lim; ++i) printf("%lld ", x.a[0][i]);
puts("");
return;
}
for(int i = 0; i <= lim; ++i) {
printf("%d: ", i);
for(int j = 0; j <= lim; ++j) {
printf("%lld ", x.a[i][j]);
}
puts("");
}
puts("#####################");
}

int main() {
scanf("%d%d%lld%d", &n, &m, &T, &act);
lim = n * m;
for(int i = 1; i <= n; ++i) {
scanf("%s", t[i] + 1);
for(int j = 1; j <= m; ++j) t[i][j] -= '0', ++t[i][j];
}
for(int i = 1; i <= act; ++i) {
scanf("%s", s[i] + 1);
len[i] = strlen(s[i] + 1);
}
for(int pos = 1; pos <= 60; ++pos) {
c[pos].a[0][0] = 1;
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= m; ++j) {
//              putchar(s[t[i][j]][now[i][j]]);
now[i][j] = (now[i][j] % len[t[i][j]]) + 1;
if(s[t[i][j]][now[i][j]] >= '0' && s[t[i][j]][now[i][j]] <= '9') {
c[pos].a[0][idx(i, j)] = s[t[i][j]][now[i][j]] - '0';
c[pos].a[idx(i, j)][idx(i, j)] = 1;
} else {
if(s[t[i][j]][now[i][j]] == 'D') c[pos].a[idx(i, j)][idx(i, j)] = 0;
if(i > 1 && s[t[i][j]][now[i][j]] == 'N')
c[pos].a[idx(i, j)][idx(i - 1, j)] = 1;
if(i < n && s[t[i][j]][now[i][j]] == 'S')
c[pos].a[idx(i, j)][idx(i + 1, j)] = 1;
if(j > 1 && s[t[i][j]][now[i][j]] == 'W')
c[pos].a[idx(i, j)][idx(i, j - 1)] = 1;
if(j < m && s[t[i][j]][now[i][j]] == 'E')
c[pos].a[idx(i, j)][idx(i, j + 1)] = 1;
}
}
}
//        puts("");
}
C = c[1];
for(int pos = 2; pos <= 60; ++pos) C = C * c[pos];
C = C.Pow(T / 60, C);
for(int pos = 1; pos <= T % 60; ++pos) {
//    	printf("Round # %d\n", pos);
C = C * c[pos];
//		print(c[pos], 0);
//		printf("The test # %d\n", pos);
//		print(C, 1);
}
ll ans = 0;
for(int i = 1; i <= lim; ++i) ans = max(ans, C.a[0][i]);
printf("%lld\n", ans);
return 0;
}

posted @ 2019-09-05 19:22  henry_y  阅读(...)  评论(...编辑  收藏