1. /*
  2. 构造单位矩阵(转移矩阵)
  3. 给定n*m网格,每个格子独立按照长度不超过6的操作串循环操作
  4. 对应的操作有
  5. 0-9:拿x个石头到这个格子
  6. nwse:把这个格子的石头推移到相邻格子
  7. d:清空该格石子
  8. 开始时网格是空的,问t秒后石头最多的格子里有多少个石子
  9.  
  10. t很大,并且每次操作后格子里的石头是线性变化的,所以用矩阵来加速递推
  11. 将n*m网格表示成为(i-1)*m+j的一维数组,那么这个数组对应的转移矩阵大小应该是(nm)^2
  12.  
  13. 然后由于每个格子的操作串最长只有6,并且1-6的最小公倍数是60,所以所有格子的操作60秒一个循环
  14. 那么求出每秒的转移矩阵,用Ai表示第i秒的转移矩阵,(1<=i<=60)
  15. 另A=mul(Ai),t=p*60+r,那么结果状态就是A^p*mul(A1,Ar);
  16.  
  17. 那么如何将操作对应到转移矩阵的构造上?
  18. 考虑转移矩阵的运行原理:可以将F'[j]=F[i]*A[i][j],即将原数组的F[i]*A[i][j]然后加到F'[j]上
  19. 0-9:凭空把x个石头转移到第i个格子上,令F[0]=1,A[0][num(i,j)]=x,如此即可完成状态转移
  20. nwse:距离n操作:把第i行的石头转移到第i-1行,即把num[i][j]的石头转移到num[i-1][j],那么令A[num[i][j]][num[i-1][j]]=1即可
  21. 保证要使F[0]=1,那么将A[0][0]设置为1
  22. A的其它数值都为0
  23. F数组就是[1,0,0,0,0,0,0,0,...0]
    矩阵快速幂加速计算
  24. */
  25. #include<bits/stdc++.h>
  26. using namespace std;
  27. #define P 65
  28. #define ll long long
  29. int n,m,t,q,i,j,k,x,y,N;
  30. int id[P][P],a[P][P],l[P];//
  31. char b[P][P];
  32. ll ans;
  33. struct mat{
  34. ll a[P][P];
  35. mat(){memset(a,,sizeof a);}
  36. mat operator*(mat b){//重载矩阵乘法
  37. mat c;
  38. for(int i=;i<n;i++)
  39. for(int j=;j<n;j++)
  40. for(int k=;k<n;k++)
  41. c.a[i][j]+=a[i][k]*b.a[k][j];
  42. return c;
  43. }
  44. }one,A[P],pre[P],B,C,D;
  45.  
  46. int main(){
  47. scanf("%d%d%d%d",&n,&m,&t,&q);
  48. char ch;
  49. for(int i=;i<=n;i++)//输入每个格子对应的操作序号
  50. for(int j=;j<=m;j++)
  51. cin>>ch,a[i][j]=ch-'',id[i][j]=++N;
  52. N++;
  53. for(int i=;i<q;i++){//输入q行不同的操作序列
  54. scanf("%s",b[i]+),l[i]=strlen(b[i]+);
  55. b[i][]=b[i][l[i]];//循环点处理一下
  56. }
  57. for(int i=;i<n;i++)one.a[i][i]=;//构造单位矩阵
  58. pre[]=one;
  59. char c;
  60. for(int i=;i<=;i++){//求出每个时间点对应的状态转移矩阵
  61. A[i].a[][]=;//对于第1个点
  62. for(int j=;j<=n;j++)
  63. for(int k=;k<=m;k++){
  64. //求出第[j,k]块的序号,就是a[j][k],在第i个时间点对应的操作c
  65. c=b[a[j][k]][i%l[a[j][k]]];
  66.  
  67. if(c>='' && c<=''){//数字
  68. A[i].a[id[j][k]][]=c-'';
  69. A[i].a[id[j][k]][id[j][k]]++;
  70. }
  71. if(c=='N'){//向各个方向转移
  72. x=j-,y=k;
  73. if(x>=)
  74. A[i].a[id[x][y]][id[j][k]]++;
  75. }
  76. if(c=='S'){
  77. x=j+,y=k;
  78. if(x<=n)
  79. A[i].a[id[x][y]][id[j][k]]++;
  80. }
  81. if(c=='W'){
  82. x=j,y=k-;
  83. if(y>=)
  84. A[i].a[id[x][y]][id[j][k]]++;
  85. }
  86. if(c=='E'){
  87. x=j,y=k+;
  88. if(y<=m)
  89. A[i].a[id[x][y]][id[j][k]]++;
  90. }
  91. }
  92. pre[i]=A[i]*pre[i-];//把所有时间点的矩阵乘起来
  93. }
  94.  
  95. B=pre[],C=one;
  96. for(k=t/;k;k>>=){//快速幂
  97. if(k&)C=C*B;
  98. B=B*B;
  99. }
  100. D.a[][]=,D=pre[t%]*C*D;//把余下时间的矩阵呈上去
  101. for(int i=;i<N;i++)//由于F数组只有第0项为1,那么直接求D[i][0]的最大值即可!
  102. if(ans<D.a[i][])
  103. ans=D.a[i][];
  104. printf("%lld",ans);
  105. }

bzoj2973转移矩阵构造法!的更多相关文章

  1. Uva 120 - Stacks of Flapjacks(构造法)

    UVA - 120  Stacks of Flapjacks Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld &a ...

  2. 利用子集构造法实现NFA到DFA的转换

    概述 NFA非有穷自动机,即当前状态识别某个转换条件后到达的后继状态不唯一,这种自动机不便机械实现,而DFA是确定有限状态的自动机,它的状态转换的条件是确定的,且状态数目往往少于NFA,所以DFA能够 ...

  3. [Luogu4724][模板]三维凸包(增量构造法)

    1.向量点积同二维,x1y1+x2y2+x3y3.向量叉积是行列式形式,(y1z2-z1y2,z1x2-x1z2,x1y2-y1x2). 2.增量构造法: 1)首先定义,一个平面由三个点唯一确定.一个 ...

  4. POJ 3295 Tautology (构造法)

    Tautology Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7716   Accepted: 2935 Descrip ...

  5. 牛客网 牛客小白月赛2 A.数字方阵-反魔方阵,梁邱构造法

    天坑未补... 水一波博客,再不写博客就咸成鱼干了,只写题不写题解,过一段时间就忘了自己学过什么了. 最近重点就是把开学以来写的题补出来,没学的就滚去学会啊(= =),填一下坑... 从这篇博客开始, ...

  6. 紫书 习题 8-24 UVa 10366 (构造法)

    又是一道非常复杂的构造法-- #include<cstdio> #include<algorithm> #define REP(i, a, b) for(int i = (a) ...

  7. 紫书 例题8-17 UVa 1609 (构造法)(详细注释)

    这道题用构造法, 就是自己依据题目想出一种可以得到解的方法, 没有什么规律可言, 只能根据题目本身来思考. 这道题的构造法比较复杂, 不知道刘汝佳是怎么想出来的, 我想的话肯定想不到. 具体思路紫书上 ...

  8. LeetCode42题,单调栈、构造法、two pointers,这道Hard题的解法这么多?

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是LeetCode专题的第23篇文章. 今天来看一道很有意思的题,它的难度是Hard,并且有许多种解法. 首先我们来看题面,说是我们有若 ...

  9. 【译】N 皇后问题 – 构造法原理与证明 时间复杂度O(1)

    [原] E.J.Hoffman; J.C.Loessi; R.C.Moore The Johns Hopkins University Applied Physics Laboratory *[译]* ...

随机推荐

  1. lua 的元表与元方法

    1. 元表与元方法, 相当于C++的函数重载 参考链接: https://blog.csdn.net/yueya_shanhua/article/details/52233228

  2. 源码学习之mybatis

    1.先看看俩种调用方式 public static void main(String[] args) { SqlSessionFactory sqlSessionFactory; SqlSession ...

  3. Javascript入门(二)变量、获取元素、操作元素

    一.变量 Javascript 有五种基本数据类型 number.String.boolean.undefined.null 一种复合类型:object 二.使用getElementById方法获取元 ...

  4. AngularJS--及其他js框架对比

    ----和 **类似?? Angular 2.谷歌的 React   Facebook的 Vue.js. Ember.js. https://github.com/angular/angular.js ...

  5. JAVA配置文件/反射操作

    配置文件 1. 在src目录下新建一个file, 命名为XXX.properties 2.编写配置文件: 3. import java.util.ResourceBundle; 4. 使用如下代码读取 ...

  6. [转] Understanding Convolutional Neural Networks for NLP

    http://www.wildml.com/2015/11/understanding-convolutional-neural-networks-for-nlp/ 讲CNN以及其在NLP的应用,非常 ...

  7. mlock实现原理及应用【转】

    转自:https://blog.csdn.net/yiyeguzhou100/article/details/78085857 https://wenku.baidu.com/view/e25b4af ...

  8. MYSQL在centos上主从配置

    主从配置理论传送门:http://blog.csdn.net/hguisu/article/details/7325124 具体配置方案: 一:MYSQL主从配置   1.1 部署环境 主(maste ...

  9. 打造一个上传图片到图床利器的插件(Mac版 开源)

    写markdown博客如何将截图快速上传到图床--记一个工具插件的实现(windows版 开源)(2017-05-31 20:23) 打造一个上传图片到图床利器的插件 鉴于写博客截图手动上传到图床的步 ...

  10. datepicker 属性设置 以及方法和事件

    DatePicker支持鼠标点选日期,同时还可以通过键盘控制选择: page up/down - 上一月.下一月 ctrl+page up/down - 上一年.下一年 ctrl+home - 当前月 ...