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 Core 进程内(InProcess)托管
ASP.NET Core 进程内(InProcess)托管 在 ASP.NET Core 中的进程内(InProcess)托管模型 什么是 Kestrel 服务器 当一个 ASP.NET Core 应 ...
- 洛谷p3384【模板】树链剖分题解
洛谷p3384 [模板]树链剖分错误记录 首先感谢\(lfd\)在课上调了出来\(Orz\) \(1\).以后少写全局变量 \(2\).线段树递归的时候最好把左右区间一起传 \(3\).写\(dfs\ ...
- 【2019.7.25 NOIP模拟赛 T1】变换(change)(思维+大分类讨论)
几个性质 我们通过推式子可以发现: \[B⇒AC⇒AAB⇒AAAC⇒C\] \[C⇒AB⇒AAC⇒AAAB⇒B\] 也就是说: 性质一: \(B,C\)可以相互转换. 则我们再次推式子可以发现: \[ ...
- oracle-DBlink基本操作
01,查询 查询DBLINK信息 select * from dba_db_links; select owner,object_name from dba_objects where object_ ...
- idea maven项目打包并部署到tomcat
打包 打开Maven管理器,邮寄package,执行Run Maven Build,执行成功后将war包生成到target目录下. 部署 1.将war包复制到tomcat安装目录下的webapps目录 ...
- Nacos集成Spring Cloud Gateway 基础使用
项目结构 项目 端口 描述 nacos-provider 8000 服务 nacos-getway 8001 网关 nacos-provider项目依赖 <dependencies> &l ...
- 2018-2019-2 20162329 《网络对抗技术》Exp8: Web基础
目录 Exp8: Web基础 一. 基础问题回答 1. 什么是表单 2. 浏览器可以解析运行什么语言. 3. WebServer支持哪些动态语言 二. 实验过程 1. Web前端HTML 2..Web ...
- Spring事务调用类自己方法失效解决办法和原因
问题 正常情况下,我们都是在controller里调用service里的方法,这个方法如果需要加事务,就在方法上加上@Transactional,这样是没问题的,事务会生效. 可是如果像下面这样,绕以 ...
- Hbase Filter之PrefixFilter
PrefixFilter PrefixFilter是将rowkey前缀为指定字符串的数据全部过滤出来并返回给用户.例如: Scan scan = new Scan(); scan.setFilter( ...
- idea中maven项目打jar包
从Eclipse换成Idea的小伙伴们可能会找不到Eclipse中Maven项目打jar包的方法,因为eclipse只需要在工程上点击右键,右键菜单中就有Maven打包的相关选项. 然而Idea的右键 ...