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;
}

转载于:https://www.cnblogs.com/poorpool/p/8516633.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值