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次, ...
随机推荐
- ASP.NET CoreMVC 中的控制器
Controller in ASP.NET Core MVC 在本节中,我们将讨论 Controller 是什么以及它在 ASP.NET Core MVC 中的作用. Fiddler 需要大家提前装一 ...
- C语言I作业12—学期总结
一.我学到的内容 二我的收获 作业 收获 C语言博客作业1 刚开始初步了解C语言方面的知识 学会Markdown基本语法 C语言博客作业2 学会了应该如何提问 PTA系统常见问题解答 学会了MinGW ...
- java8 HashTable 原理
HashTable原理 Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现.Hashtable中的方法是同步的,而HashMap方法(在 ...
- Vue2 实践揭秘 错误列表
京东上的购买地址 作者是土生土长的聪明中国人 https://item.jd.com/12176536.html 64页 const bookID = this.$router.params.id 搞 ...
- i2c的读写时序图
根据实际示波器的波形画的时序图,时序图不好画,小小一幅图,画了两个小时,分享之:
- python实现ldap接入
需要提前安装python-ldap模块 python接入ldap其实分了几个步骤: 1.使用一个管理员账户登陆到ldap 2.使用一个字段值是唯一的字段,去搜索到要验证用户的DN值(ldap搜索到的单 ...
- Caused by: java.lang.ClassCastException: org.springframework.web.SpringServletContainerInitializer cannot be cast to javax.servlet.ServletContainerInitializer。。。。。检查一下servlet-api是否冲突了?
原因:jar包发生冲突.在我的pom.xml文件中 <dependency> <groupId>javax.servlet</groupId> ...
- python正确使用异常处理机制
一.不要过度使用异常 不可否认,Python 的异常机制确实方便,但滥用异常机制也会带来一些负面影响.过度使用异常主要表现在两个方面: 把异常和普通错误混淆在一起,不再编写任何错误处理代码,而是以简单 ...
- Java中如何获取一个类中泛型的实际类型
本文链接:https://blog.csdn.net/kuuumo/article/details/83021158 _______________________________________ ...
- ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2(转载)
ASP.NET Core 2.2 has been out for a while now and with it come some significant improvements to the ...