题目分析:

就当是一次记录吧,2013年绍兴市市赛的一题,重现赛当时我想递推可能是矩阵快速幂吧,但是这个递推公式真没推出来(赛后猛如虎系列),这题和第一题有联系又有区别,第一题的递推很简单,dp[i][j] = dp[i-1][j] + dp[i][j-1],但是第二题有两个问题:1.H的范围扩大到1000000000,二维数组无法存储(空间过大)2.普通递推的话递推的次数太多(w*h,时间过大),简单来说必须改变一下思维,否则一定爆内存且超时,之前的递推公式也用不了了

这里先放一张我的手稿(丑图警告)

这里需要通过仔细的观察,将上图处于同一斜线的位置归为同一层(或者说这些在同一斜线上的点的横坐标与纵坐标的和是相同的),还记得上面提到的两个难题吗,现在来解决空间过大无法存储二维数组的问题,此时我们观察,对于图中的某一点(i,j)来说,到达它的行走方案一定是到达(i-1,j)和到达(i,j-1)的方案的和,就斜线上每个位置来说,就等于它左边的与上面的格子的数的和,而且这里每条斜线上的点仅仅用于下一斜线上的点的计算(这里就很像背包问题的二维化一维的思想)我们可以将二维数组转化成一维数组,dp[j]代表第i条斜线的从右上往左下的第j个点的可达方案数,由于w<=30,所以斜线的长度最长也只有31(有一个0点需要辅助计算)

此时空间的问题就解决了,我们接下来需要做的就是通过条斜线上的点点,推出下一条斜线上的点的种数,且我们很容易发现(就斜线上某一个点来说,dp[j] = dp[j] + dp[j-1],这里要注意,此时dp[j]代表的是第i条斜线的从右上往左下第j个点,而此时只有一个一维数组在存放,所以前面的等式,前一个dp[j]代表的是第i条斜线的dp[j]的值,而等式后面的dp[j]与dp[j-1]代表的是第i-1条斜线的这两个点的走法),此时我们将第一条斜线的数据抽象成一个1XW的矩阵,它乘上一个WXW的矩阵就会得到一个代表第二条斜线的矩阵

且根据我们的推理,我们的递推公式是dp[j] = dp[j] + dp[j-1],最后一条斜线所抽象的第w个点就是到达W*H的位置所有的行走方案的总数,而对于出现的障碍点,我们可以对它们根据横纵坐标之和进行排序(横纵之和就是斜线的编号,初始点1,1所以斜线编号我定义为2),然后对于当前的斜线求和下一个障碍点所在的斜线编号值差,矩阵快速幂求出当前障碍点的所有dp[j]的种数,而对于障碍点,dp[j] = 0,这样从下一条斜线开始就会受到影响,对于其他的障碍点也是相同的处理,如果同一条斜线有多个障碍点就将dp[j]都 = 0,此时的j就是障碍点的横坐标,最后求一次到达第(w+h)条斜线的举证快速幂

代码:

 #include<iostream>
#include<algorithm>
#include<cmath>
using namespace std; int w, h, d;
const long long mod = 1e9 + ;
struct mat{
long long m[][];
};
struct Node{
long long x, y;
long long sum;
}danger[]; bool cmp(Node a, Node b){
return a.sum < b.sum;
} mat operator * (mat a, mat b){
mat ret;
for(int i = ; i <= w; i++){
for(int j = ; j <= w; j++){
long long temp = ;
for(int k = ; k <= w; k++){
if(a.m[i][k] && b.m[k][j]){
temp += a.m[i][k] * b.m[k][j];
temp %= mod;
}
}
ret.m[i][j] = temp;
}
}
return ret;
} mat pow_mat(mat res, mat a, int n){
while(n){
if(n&) res = res * a;
a = a * a;
n >>= ;
}
return res;
} int main(){
while(scanf("%d%d%d", &w, &h, &d) != EOF){
for(int i = ; i < d; i++){
scanf("%d%d", &danger[i].x, &danger[i].y);
danger[i].sum = danger[i].x + danger[i].y;
}
sort(danger, danger+d, cmp);
mat x; //构造一个幂矩阵
for(int i = ; i <= w; i++){
for(int j = ; j <= w; j++){
x.m[i][j] = ;
}
}
for(int i = ; i <= w-; i++){
for(int j = i; j < i+; j++){
x.m[i][j] = ;
}
}
x.m[w][w] = ;
mat res;
for(int i = ; i <= w; i++){
for(int j = ; j <= w; j++){
res.m[i][j] = ;
}
}
res.m[][] = ; //默认横纵坐标和为2开始,即(1,1)点
int cen = ; //这里定义的层数为点的横纵坐标之和
for(int i = ; i < d; i++){
if(danger[i].sum > cen){ //当前的危险点层数大于已经完成计算的层数
res = pow_mat(res, x, danger[i].sum - cen);
cen = danger[i].sum;
res.m[][danger[i].x] = ;
}else if(danger[i].sum == cen){ //当前的危险点的层数等于已经完成的计算的层数则直接更新危险点为0种
res.m[][danger[i].x] = ;
}
}
if(h+w > cen) res = pow_mat(res, x, h+w - cen); //最后将剩余的层数直接求完
printf("%d\n", res.m[][w]);
}
return ;
}

HLOJ1361 Walking on the Grid II 矩阵快速幂的更多相关文章

  1. Final Destination II -- 矩阵快速幂模板题

    求f[n]=f[n-1]+f[n-2]+f[n-3] 我们知道 f[n] f[n-1] f[n-2]         f[n-1]  f[n-2]  f[n-3]         1    1    ...

  2. #1560 : H国的身份证号码II(dp+矩阵快速幂)

    #1560 : H国的身份证号码II 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 H国的身份证号码是一个N位的正整数(首位不能是0).此外,由于防伪需要,一个N位正整 ...

  3. poj 3735 Training little cats(矩阵快速幂,模版更权威,这题数据很坑)

    题目 矩阵快速幂,这里的模版就是计算A^n的,A为矩阵. 之前的矩阵快速幂貌似还是个更通用一些. 下面的题目解释来自 我只想做一个努力的人 @@@请注意 ,单位矩阵最初构造 行和列都要是(猫咪数+1) ...

  4. 【矩阵快速幂】bzoj1297 [SCOI2009]迷路

    1297: [SCOI2009]迷路 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1407  Solved: 1007[Submit][Status ...

  5. hdu 5607 BestCoder Round #68 (矩阵快速幂)

    graph  Accepts: 9 Submissions: 61  Time Limit: 8000/4000 MS (Java/Others)  Memory Limit: 65536/65536 ...

  6. 【矩阵快速幂】【杭电OJ1757】

    http://acm.hdu.edu.cn/showproblem.php?pid=1757 A Simple Math Problem Time Limit: 3000/1000 MS (Java/ ...

  7. 2016"百度之星" - 初赛(Astar Round2A) A.All X 矩阵快速幂

    All X  Time Limit: 2000/1000 MS (Java/Others)  Memory Limit: 65536/65536 K (Java/Others) Problem Des ...

  8. HDU 5318——The Goddess Of The Moon——————【矩阵快速幂】

    The Goddess Of The Moon Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/ ...

  9. hihoCoder #1151 : 骨牌覆盖问题·二 (矩阵快速幂,DP)

    题意:给一个3*n的矩阵,要求用1*2的骨牌来填满,有多少种方案? 思路: 官网题解用的仍然是矩阵快速幂的方式.复杂度O(logn*83). 这样做需要构造一个23*23的矩阵,这个矩阵自乘n-1次, ...

随机推荐

  1. linux下python解释器的sys.path路径如何添加

    一. 使用pycharm时, pycharm会自动把我们新建的每个项目都加入到sys.path路径中, 我们在使用过程中根本不涉及 项目路径的处理, 但是当项目部署到linux上时, 问题就来了, l ...

  2. chrome 模拟发送请求的方法

    chrome f12 看到了web页面的请求,有时候想修改一下参数重新执行一下怎么办? 如果是get方法.参数不多可以直接在浏览器中打开.否则post方法参数多时很多人会复制到postman中执行,但 ...

  3. 2019CCPC网络预选赛 八道签到题题解

    目录 2019中国大学生程序设计竞赛(CCPC) - 网络选拔赛 6702 & 6703 array 6704 K-th occurrence 6705 path 6706 huntian o ...

  4. 第02组 Beta冲刺(2/4)

    队名:十一个憨批 组长博客 作业博客 组长黄智 过去两天完成的任务:了解整个游戏的流程 GitHub签入记录 接下来的计划:继续完成游戏 还剩下哪些任务:完成游戏 燃尽图 遇到的困难:没有美术比较好的 ...

  5. Linux性能优化实战学习笔记:第四十六讲

    一.上节回顾 不知不觉,我们已经学完了整个专栏的四大基础模块,即 CPU.内存.文件系统和磁盘 I/O.以及网络的性能分析和优化.相信你已经掌握了这些基础模块的基本分析.定位思路,并熟悉了相关的优化方 ...

  6. [LeetCode] 794. Valid Tic-Tac-Toe State 验证井字棋状态

    A Tic-Tac-Toe board is given as a string array board. Return True if and only if it is possible to r ...

  7. [LeetCode] 337. House Robber III 打家劫舍之三

    The thief has found himself a new place for his thievery again. There is only one entrance to this a ...

  8. Visual Studio 调试系列9 调试器提示和技巧

    系列目录     [已更新最新开发文章,点击查看详细] 01 固定数据提示 如果你在调试时,经常将鼠标悬停在数据提示上,就可能想固定变量的数据提示,方便自己随时查看. 即使在重新启动后,固定的变量也能 ...

  9. Java中HashMap和TreeMap的区别

    什么是Map集合在数组中我们是通过数组下标来对其内容索引的,而在Map中我们通过对象来对对象进行索引,用来索引的对象叫做key,其对应的对象叫做value.这就是我们平时说的键值对. HashMap ...

  10. Python处理数据集-2

    原数据集的数据格式: 每行为:(test_User, test_Item) negativeItem1 negativeItem2 negativeItem3 …… negativeItem99 即每 ...