bzoj2973 入门oj4798 石头游戏

我们人为地搞出来一个全能神,每次调用他他可以给一个节点 \(1\) 个石头。
这样,当前的状态就可以由上一秒的状态搞过来,这就像是一个递推。用矩阵加速。

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long ll;
int n, m, t, act, len[15], wdt[105], hmn;
char ss[15][15];
ll ans;
struct MATRIX{
	ll num[105][105];
	MATRIX operator*(const MATRIX &x)const{
		MATRIX re;
		for(int i=0; i<=n*m; i++)
			for(int j=0; j<=n*m; j++){
				re.num[i][j] = 0;
				for(int k=0; k<=n*m; k++)
					re.num[i][j] += num[i][k] * x.num[k][j];
			}
		return re;
	}
}yuan, zhu[65], dark, dan;
int getNum(int x, int y){
	return (x-1)*m+y;
}
void build(int x){
	for(int i=0; i<=n*m; i++){
		if(i==0)	zhu[x].num[0][i] = 1;
		else{
			int xx=(i-1)/m+1;
			int yy=i-(xx-1)*m;
			int pos=(x-1)%len[wdt[i]];
			char ch=ss[wdt[i]][pos];
			if(ch>='0' && ch<='9')	zhu[x].num[0][i] = ch - '0', zhu[x].num[i][i] = 1;
			else if(ch=='D')	;
			else if(ch=='N' && xx>1)
				zhu[x].num[i][getNum(xx-1,yy)] = 1;
			else if(ch=='S' && xx<n)
				zhu[x].num[i][getNum(xx+1,yy)] = 1;
			else if(ch=='W' && yy>1)
				zhu[x].num[i][getNum(xx,yy-1)] = 1;
			else if(ch=='E' && yy<m)
				zhu[x].num[i][getNum(xx,yy+1)] = 1;
		}
	}
}
MATRIX ksm(MATRIX a, int b){
	MATRIX re=dan;
	while(b){
		if(b&1)	re = re * a;
		a = a * a;
		b >>= 1;
	}
	return re;
}
int main(){
	yuan.num[0][0] = 1;
	cin>>n>>m>>t>>act;
	for(int i=0; i<=n*m; i++)
		dan.num[i][i] = 1;
	dark = dan;
	for(int i=1; i<=n; i++)
		for(int j=1; j<=m; j++)
			scanf("%1d", &wdt[getNum(i,j)]);
	for(int i=0; i<act; i++){
		scanf("%s", ss[i]);
		len[i] = strlen(ss[i]);
	}
	for(int i=1; i<=60; i++){
		build(i);
		dark = dark*zhu[i];
	}
	hmn = t / 60;
	t = t - hmn * 60;
	MATRIX qwq=ksm(dark, hmn);
	for(int i=1; i<=t; i++)
		qwq = qwq * zhu[i];
	qwq = yuan*qwq;
	for(int i=1; i<=n*m; i++)
		ans = max(ans, qwq.num[0][i]);
	cout<<ans<<endl;
	return 0;
}
posted @ 2018-03-06 20:40  poorpool  阅读(266)  评论(0编辑  收藏  举报