ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【数学(矩阵加速)】石头游戏

2022-02-03 21:34:32  阅读:154  来源: 互联网

标签:ch 游戏 int res rep 矩阵 石头 id Mat


这题题面并不是很严密啊。。应该说明当石子在走出棋盘边界判定为移除,不然有可能会被理解为不做行动

分析

操作次数很大,直接模拟行不通。

我们想办法将棋盘上所有格子的一次操作转化为矩阵上的变换来解决。

考虑将棋盘上的格子转化为编号,也就是 \(i\) 行 \(j\) 列的格子编号为 \((i-1)m + j\)。我们建立一个 \(n\times m + 1\) 行 \(1\)​ 列的矩阵,其中最后一行值为 \(1\),其余为 \(0\)。

\[\begin{pmatrix} 0 \\0 \\ \vdots \\ 1 \end{pmatrix} \]

接下来考虑如何将三种操作对应到矩阵上的操作中:

下面的步骤是构造变换的矩阵,也就是考虑左乘的矩阵的构造。(记矩阵为 \(op\))

  • 对于第一个操作,假设 \((i, j)\)​ 格子元素 \(+k\)​,记该格编号为 \(id\),那么 \(op\) 第 \(id\) 行 \(id\) 列应为 \(1\),\(id\) 行 \(nm+1\) 列为 \(k\)。
  • 第二个操作,以向南走为例,也就是将 \((i, j)\) (记编号为 \(pre\))的石子移动到 \((i+1, j)\)(记编号为 \(cur\)),那么 \(op\) 的 \(cur\) 行 \(pre\) 列为 \(1\),其余为 \(0\)。
  • 第三个操作就是将 \(id\) 行全部设为 \(0\)。

实现

// Problem: 石头游戏
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/208/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

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

#define debug(x) cerr << #x << ": " << (x) << endl
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define dwn(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define int long long

inline void read(int &x){
    int s=0; x=1;
    char ch=getchar();
    while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
    while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
    x*=s;
}

struct Mat{
    int n, m;
    vector<vector<int>> w;

    Mat(){}
    Mat(int _n, int _m){
        n=_n, m=_m;
        w.resize(n+1, vector<int>(m+1, 0));
    }
    
    void init(int _n, int _m){
    	n=_n, m=_m;
        w.resize(n+1, vector<int>(m+1, 0));
    }

    void I(){
    	assert(n==m);
        rep(i,1,n) rep(j,1,n) w[i][j]=(i==j);
    }

    Mat operator * (const Mat &o)const{
        assert(m==o.n);
        Mat res(n, o.m);

        rep(i,1,n) rep(j,1,o.m){
            int &t=res.w[i][j];
            rep(k,1,o.n) t+=w[i][k]*o.w[k][j];
        }

        return res;
    }

    Mat fpow(int p){
        Mat res(n, m);
        Mat x=*this;
        res.I();
        for(; p; p>>=1, x=x*x) if(p&1) res=res*x;
        return res;
    }
    
    void solve(){
    	int res=0;
    	rep(i,1,n) rep(j,1,m) res=max(res, w[i][j]);
    	cout<<res<<endl;
    }
    
    void dbg(){
    	rep(i,1,n){
    		rep(j,1,m) cerr<<w[i][j]<<' ';
    		cerr<<endl;
    	}
    	cerr<<endl;
    }
};

const int N=10;

string ac[15];
int n, m, t, act;
int g[N][N];
int id[N][N];

signed main(){
	cin>>n>>m>>t>>act;
	int tot=0;
	rep(i,1,n) rep(j,1,m){
		char ch; cin>>ch;
		g[i][j]=ch-'0'+1;
		id[i][j]=++tot;
	}
	
	rep(i,1,act){
		cin>>ac[i];
		string tmp=ac[i];
		while(ac[i].size()!=60) ac[i]+=tmp;
		ac[i]=' '+ac[i];
	}
	
	int nm=n*m;
	Mat op[65];
	rep(i,1,60) op[i].init(nm+1, nm+1), op[i].w[nm+1][nm+1]=1;
	
	rep(k,1,60){
		rep(i,1,n) rep(j,1,m){
			int num=id[i][j];
			char type=ac[g[i][j]][k];
			if(isdigit(type)){
				op[k].w[num][num]=1;
				op[k].w[num][nm+1]=type-'0';
			}
			else if(type!='D'){
				int pre=num, cur=0;
				if(type=='N' && i-1) cur=id[i-1][j];
				if(type=='W' && j-1) cur=id[i][j-1];
				if(type=='S' && i<n) cur=id[i+1][j];
				if(type=='E' && j<m) cur=id[i][j+1];
				if(cur) op[k].w[cur][pre]=1;
			}
		}
	}
	
	
	Mat OP(nm+1, nm+1);
	OP.I();
	rep(i,1,60) OP=op[i]*OP;
	OP=OP.fpow(t/60);
	
	Mat res(nm+1, 1); res.w[nm+1][1]=1;
	res=OP*res;
	rep(i,1,t%60) res=op[i]*res;
	
	res.solve();
	
	return 0;
}

标签:ch,游戏,int,res,rep,矩阵,石头,id,Mat
来源: https://www.cnblogs.com/Tenshi/p/15862045.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有