HLOJ1361 Walking on the Grid II 矩阵快速幂
题目分析:
就当是一次记录吧,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 矩阵快速幂的更多相关文章
- 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 ...
- #1560 : H国的身份证号码II(dp+矩阵快速幂)
#1560 : H国的身份证号码II 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 H国的身份证号码是一个N位的正整数(首位不能是0).此外,由于防伪需要,一个N位正整 ...
- poj 3735 Training little cats(矩阵快速幂,模版更权威,这题数据很坑)
题目 矩阵快速幂,这里的模版就是计算A^n的,A为矩阵. 之前的矩阵快速幂貌似还是个更通用一些. 下面的题目解释来自 我只想做一个努力的人 @@@请注意 ,单位矩阵最初构造 行和列都要是(猫咪数+1) ...
- 【矩阵快速幂】bzoj1297 [SCOI2009]迷路
1297: [SCOI2009]迷路 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1407 Solved: 1007[Submit][Status ...
- hdu 5607 BestCoder Round #68 (矩阵快速幂)
graph Accepts: 9 Submissions: 61 Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 ...
- 【矩阵快速幂】【杭电OJ1757】
http://acm.hdu.edu.cn/showproblem.php?pid=1757 A Simple Math Problem Time Limit: 3000/1000 MS (Java/ ...
- 2016"百度之星" - 初赛(Astar Round2A) A.All X 矩阵快速幂
All X Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Problem Des ...
- 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/ ...
- hihoCoder #1151 : 骨牌覆盖问题·二 (矩阵快速幂,DP)
题意:给一个3*n的矩阵,要求用1*2的骨牌来填满,有多少种方案? 思路: 官网题解用的仍然是矩阵快速幂的方式.复杂度O(logn*83). 这样做需要构造一个23*23的矩阵,这个矩阵自乘n-1次, ...
随机推荐
- [Taro] 解决 使用 Taro UI 小程序下 Iconfont 图标 不显示问题
Taro UI 配置 第三方 的 文档 配置即可解决 https://taro-ui.jd.com/#/docs/icon 解决问题: 之前 只有在H5下 才显示 Iconfont 图标 后来按照此文 ...
- TCP三次握手及四次断开,TCP有限状态机
TCP 的连接建立 上图画出了 TCP 建立连接的过程.假定主机 A 是 TCP 客户端,B是服务端.最初两端的 TCP 进程都处于 CLOSED 状态.图中在主机下面的是 TCP进程所处的状态.A ...
- vue图片放大、缩小、旋转等
用于图片浏览的Vue组件,支持旋转.缩放.翻转等操作,基于viewer.js. 效果: 安装 使用npm命令安装 npm install v-viewer 使用 引入v-viewer及必需的css样式 ...
- 基于Django的Rest Framework框架的RESTful规范研究
一.什么是RESTful规范 总的来说:RESTful规范就是一个非技术,人为约定的一个面向资源的架构理念. REST与技术无关,代表的是一种软件架构风格,REST是Representational ...
- MySQL基础指令和安装
数据库概念 那Mysql能干嘛呢?它就是一款软件,安装在任何一台计算机或者服务器上的时候,只要我告诉它创建一个文件,新增一个数据,删除一个数据它就能帮我去做想要的操作 那我们暂且能不能理解为mysql ...
- App启动时间分析
iOS应用的启动可分为pre-main阶段和main()阶段. 1.pre-main阶段 可以通过配置Scheme,设置DYLD_PRINT_STATISTICS为1,来打印pre-main阶段的时间 ...
- pandas的使用(4)
pandas的使用(4)--文件读取和保存
- 【Oracle】重做undo表空间
重做undo表空间 场景: alert日志,报了如下错误: [oraprod@arpinfo bdump]$ tail -f alert_PROD.log Errors in file /ora115 ...
- 【MySQL】Mariadb安装
Mariadb安装 1.解压 [root@oradb bin]# tar zxvf mariadb-10.3.18-linux-x86_64.tar.gz [root@oradb bin]# mv m ...
- scala的应用--UDF:用户自定义函数
在window10下安装了hadoop,用ida创建maven项目. <properties> <spark.version>2.2.0</spark.version&g ...