leetcode_935. Knight Dialer_动态规划_矩阵快速幂
https://leetcode.com/problems/knight-dialer/
在如下图的拨号键盘上,初始在键盘中任意位置,按照国际象棋中骑士(中国象棋中马)的走法走N-1步,能拨出多少种不同的号码。
解法一:动态规划,逆向搜索
class Solution
{
public:
vector<vector<int> > gra{{,},{,},{,},{,},{,,},
{},{,,},{,},{,},{,}};
const int mod=1e9+;
int knightDialer(int N)
{
int res=;
for(int i=; i<=; i++)
{
vector<vector<int>> dp(N+,vector<int>(,-));
dp[][i]=;
for(int j=;j<=;j++)
res = (res+dfs(N-,j,dp))%mod;
}
return res;
}
int dfs(int step,int num,vector<vector<int>>& dp)
{
if(dp[step][num]>=)
return dp[step][num];
if(step==)
return dp[step][num]=;
int ret=;
for(int i=;i<gra[num].size();i++)
ret = (ret + dfs(step-, gra[num][i], dp))%mod;
return dp[step][num]=ret;
}
};
解法二:动态规划,正向递推
class Solution
{
public:
vector<vector<int> > gra{{,},{,},{,},{,},{,,},
{},{,,},{,},{,},{,}};
const int mod=1e9+;
int knightDialer(int N)
{
int res=;
for(int i=; i<=; i++)
{
vector<vector<int>> dp(N+,vector<int>(,));
dp[][i]=;
for(int j=; j<=N-; j++)
for(int k=; k<=; k++)
for(int l=; l<gra[k].size(); l++)
dp[j][k] = (dp[j][k]+dp[j-][gra[k][l]])%mod;
for(int j=; j<=; j++)
res = (res+dp[N-][j])%mod;
}
return res;
}
};
问题一:要构造10次二维的vector,很耗时,dp[N][10]空间也有很大浪费。
改进:
将dp[j][k] = (dp[j][k]+dp[j-1][gra[k][l]])%mod;(当前状态由前一时刻状态推得)
改为dp[j+1][gra[k][l]] = (dp[j+1][gra[k][l]]+dp[j][k])%mod;(由当前时刻状态推下一时刻状态)
改进过后可以省去9次构造二维vector的开销,除此之外,递推更加高效(相比之下少了一层for)。
class Solution
{
public:
vector<vector<int> > gra{{,},{,},{,},{,},{,,},
{},{,,},{,},{,},{,}};
const int mod=1e9+;
int knightDialer(int N)
{
int res=;
int dp[][];
//vector<vector<int>> dp(N,vector<int>(10,0));
memset(dp,,sizeof(dp));
for(int i=; i<=; i++)
dp[][i]=;
for(int j=; j<=N-; j++)
for(int k=; k<=; k++)
for(int l=; l<gra[k].size(); l++)
dp[j+][gra[k][l]] = (dp[j+][gra[k][l]]+dp[j][k])%mod;
for(int j=; j<=; j++)
res = (res+dp[N-][j])%mod;
return res;
}
};
空间复杂度还没有还没优化,但是可以发现,递推关系只需要两个状态(当前状态和下一步状态),而不需要N个状态。
解法三:动态规划,矩阵快速幂
进一步使用矩阵运算来优化状态的递推关系,同时还可以使用快速幂,使最终时间复杂度优化到O(logN),空间复杂度优化到常数量级。但是C++自己实现矩阵稍微有点麻烦。使用python的numpy非常方便。
class Matrix
{
public:
Matrix(int row, int col);
Matrix(vector<vector<int>>& v);
Matrix operator * (const Matrix& rh)const;
Matrix& operator = (const Matrix& rh);
int GetRow(){return row_;}
int GetCol(){return col_;}int SumOfAllElements();
~Matrix();
private:
int row_,col_;
long long **matrix_;
};
Matrix::Matrix(int row, int col)
{
row_ = row;
col_ = col;
matrix_ = new long long* [row_];
for(int i=; i<row_; i++)
matrix_[i] = new long long[col_];
for(int i=; i<row_; i++)
for(int j=; j<col_; j++)
matrix_[i][j] = (i==j?:);
} Matrix::Matrix(vector<vector<int>>& v)
{
row_ = v.size();
col_ = v[].size();
matrix_ = new long long* [row_];
for(int i=; i<row_; i++)
matrix_[i] = new long long[col_];
for(int i=; i<row_; i++)
for(int j=; j<col_; j++)
matrix_[i][j] = v[i][j];
} Matrix Matrix::operator * (const Matrix& rh)const
{
Matrix result(row_,col_);
for(int i=; i<row_; i++)
for(int j=; j<col_; j++)
{
long long temp=;
for(int k=; k<col_; k++)
{
temp += matrix_[i][k]*rh.matrix_[k][j];
temp %= (int)1e9+;
}
result.matrix_[i][j] = temp;
}
return result;
} Matrix& Matrix::operator = (const Matrix& rh)
{
if(this==&rh)
return (*this);
for(int i=; i<col_; i++)
delete [] matrix_[i];
delete [] matrix_;
row_ = rh.row_;
col_ = rh.col_;
matrix_ = new long long* [row_];
for(int i=; i<row_; i++)
matrix_[i] = new long long[col_];
for(int i=; i<row_; i++)
for(int j=; j<col_; j++)
matrix_[i][j] = rh.matrix_[i][j];
return (*this);
} int Matrix::SumOfAllElements()
{
long long result=;
for(int i=; i<row_; i++)
for(int j=; j<col_; j++)
{
result += matrix_[i][j];
result %= (int)1e9+;
}
return result;
}
Matrix::~Matrix()
{
for(int i=; i<col_; i++)
delete [] matrix_[i];
delete [] matrix_;
}
//以上为矩阵类的实现,仅能满足此题方阵乘法,其他的功能性质没有考虑 class Solution
{
public: const int mod=1e9+;
int knightDialer(int N)
{
vector<vector<int> > matrix
{
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
};
Matrix matrix1(matrix);
Matrix result(matrix1.GetRow(), matrix1.GetCol());
int step = N-;
while(step>)
{
if(step&)
result = result * matrix1;
step >>= ;
matrix1 = matrix1 * matrix1;
}
return result.SumOfAllElements();
}
};
leetcode_935. Knight Dialer_动态规划_矩阵快速幂的更多相关文章
- 【CF1151F】Sonya and Informatics(动态规划,矩阵快速幂)
[CF1151F]Sonya and Informatics(动态规划,矩阵快速幂) 题面 CF 题解 考虑一个暴力\(dp\).假设有\(m\)个\(0\),\(n-m\)个\(1\).设\(f[i ...
- 【BZOJ5298】[CQOI2018]交错序列(动态规划,矩阵快速幂)
[BZOJ5298][CQOI2018]交错序列(动态规划,矩阵快速幂) 题面 BZOJ 洛谷 题解 考虑由\(x\)个\(1\)和\(y\)个\(0\)组成的合法串的个数. 显然就是把\(1\)当做 ...
- 【BZOJ4870】组合数问题(动态规划,矩阵快速幂)
[BZOJ4870]组合数问题(动态规划,矩阵快速幂) 题面 BZOJ 洛谷 题解 显然直接算是没法做的.但是要求的东西的和就是从\(nk\)个物品中选出模\(k\)意义下恰好\(r\)个物品的方案数 ...
- 【BZOJ1494】【NOI2007】生成树计数(动态规划,矩阵快速幂)
[BZOJ1494][NOI2007]生成树计数(动态规划,矩阵快速幂) 题面 Description 最近,小栋在无向连通图的生成树个数计算方面有了惊人的进展,他发现: ·n个结点的环的生成树个数为 ...
- CF954F Runner's Problem(动态规划,矩阵快速幂)
CF954F Runner's Problem(动态规划,矩阵快速幂) 题面 CodeForces 翻译: 有一个\(3\times M\)的田野 一开始你在\((1,2)\)位置 如果你在\((i, ...
- nyoj_148_fibonacci数列(二)_矩阵快速幂
fibonacci数列(二) 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 In the Fibonacci integer sequence, F0 = 0, F ...
- fibonacci数列(二)_矩阵快速幂
描述 In the Fibonacci integer sequence, F0 = 0, F1 = 1, and Fn = Fn − 1 + Fn − 2 for n ≥ 2. For exampl ...
- 【BZOJ2004】公交线路(动态规划,状态压缩,矩阵快速幂)
[BZOJ2004]公交线路(动态规划,状态压缩,矩阵快速幂) 题面 BZOJ 题解 看到\(k,p\)这么小 不难想到状态压缩 看到\(n\)这么大,不难想到矩阵快速幂 那么,我们来考虑朴素的\(d ...
- 【BZOJ1009】GT考试(KMP算法,矩阵快速幂,动态规划)
[BZOJ1009]GT考试(KMP算法,矩阵快速幂,动态规划) 题面 BZOJ 题解 看到这个题目 化简一下题意 长度为\(n\)的,由\(0-9\)组成的字符串中 不含串\(s\)的串的数量有几个 ...
随机推荐
- BZOJ_4383_[POI2015]Pustynia_线段树优化建图+拓扑排序
BZOJ_4383_[POI2015]Pustynia_线段树优化建图+拓扑排序 Description 给定一个长度为n的正整数序列a,每个数都在1到10^9范围内,告诉你其中s个数,并给出m条信息 ...
- 两行代码搞定网站gzip压缩
网站使用gzip压缩的好处就不用多说了吧,自行脑补,来说一下如何使用nodejs实现gzip压缩,只需要两行代码,so ease. 通过nodejs实现gzip 需要用到的模块 compression ...
- 一个表的两个字段具有相同的类型。如何仅用SQL语句交换这两列的数据?
--假设为A B两个字段--查询Select A As B, B As A From TableName --更新Update TableName Set A = B, B = A
- hdoj2859【DP基础】
/* 看题解A的. 总结:小矩阵--> 大矩阵 dp[i][j]=min(t,dp[i-1][j+1]+1); */ #include <iostream> #include < ...
- IEnumerable<T> 的时候一个主意事项p
IEnumerator IEnumerable.GetEnumerator() { return _vtDataView.GetEnumerator(); } public IEnumerator&l ...
- C#递归拷贝文件夹下文件以及文件夹
public bool CopyOldLabFilesToNewLab(string sourcePath, string savePath) { if (!Directory.Exists(save ...
- Spring事务引发dubbo服务注册问题
文章清单 1. 问题 2. 查找bug过程 3. 解决方案 使用spring boot+dubbo写项目,一个服务,之前是正常的,后来调用方出现空指针异常,第一反应提供方出了问题. 1. 看控制台,服 ...
- Python %s和%r的区别
%s 用str()方法处理对象 %r 用rper()方法处理对象,打印时能够重现它所代表的对象(rper() unambiguously recreate the object it represen ...
- loj125 除数函数求和 2
https://loj.ac/problem/125 $原式=2\sum_{i=1}^n(i^2*{\lfloor}{\frac{n}{i}}{\rfloor})+3\sum_{i=1}^n(i*{\ ...
- [在读]Nodejs实战
书到手的时候其实就已经过时,Express更新太快,因而书中的例子实践起来会有很多阻碍. 目前搁置状态.