动态规划过程详解--传递信息求组合题目
Posted C_YCBX Py_YYDS
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态规划过程详解--传递信息求组合题目相关的知识,希望对你有一定的参考价值。
题目
普通bfs或dfs暴力解法
此题在LeetCode上的难度显示是简单题,原因不言而喻,因为可以通过暴力解法通过。。。当然这种暴力解法一般只适用于问题规模30以下。。如果比赛中碰到大概率是1000以上复杂度。。。所以还是老老实实dp吧!
此题只要通过map把关系图建好,则就能通过暴力解法搜索
解题代码:
class Solution {
public:
int numWays(int n, vector<vector<int>>& relation, int k) {
unordered_map<int,vector<int>>check;
//建表
for(const auto t:relation){
check[t[0]].emplace_back(t[1]);
}
queue<int>Q; Q.push(0);
int step = 1;
int res = 0;
//bfs搜索
while(!Q.empty()){
for(int i = Q.size();i>0;i--){
const int t = Q.front();Q.pop();
if(check.count(t)){
vector<int>&q=check[t];
for(const int pp:q){
if(step==k&&pp==n-1)
res++;
Q.push(pp);
}
}
}
step++;
if(step>k)
break;
}
return res;
}
};
dp过程详解
动态规划的过程一般模块化的分为以下几步:
- 读题找出相关联的状态,并根据状态得出具体的dp数组实例。
- 通过dp数组状态间的联系建立dp数组的状态转移方程。
- 通过完成基本案例的填写,base case填好后,根据状态转移方程确定遍历方向。
下面就对上述过程进行实践:
- 找出相关联的状态:传递的次数 和 到达的编号,列出
dp[i][j]
:表示传递了i次后到达j的方案数。 - 根据dp数组含义建立动态转移方程:
dp[i][j] = dp[i-1][k1..kn](其中k1到kn表示能传到j的上一次编号)
- 填写
base case:dp[0][0] = 1
其余初始值均为0。则遍历方向可以是自由横向方向
(毕竟只依赖上一行数据,而第0行都已经确定了答案)。
不优化的二维dp数组解法:
class Solution {
public:
int numWays(int n, vector<vector<int>>& relation, int k) {
int dp[k+1][n];memset(dp,0,sizeof(dp));
dp[0][0] = 1;
for(int i = 1;i<=k;i++){
for(const auto t:relation){
dp[i][t[1]] += dp[i-1][t[0]];
}
}
return dp[k][n-1];
}
};
优化为一维数组:
由于每次的答案只和上一行的结果相关,由于横向遍历无法控制方向,所以直接建立临时数组保存下一行的答案,然后再与dp不断替换来实现一维数组优化。
class Solution {
public:
int numWays(int n, vector<vector<int>>& relation, int k) {
int*dp = (int*)malloc(sizeof(int)*n);
memset(dp,0,n*sizeof(int));
dp[0] = 1;
for(int i = 1;i<=k;i++){
//申请动态数组记录一行的结果
int*tmp = (int*)malloc(sizeof(int)*n);
memset(tmp,0,n*sizeof(int));
for(const auto t:relation){
tmp[t[1]] += dp[t[0]];
}
free(dp);
dp = tmp;
}
return dp[n-1];
}
};
以上是关于动态规划过程详解--传递信息求组合题目的主要内容,如果未能解决你的问题,请参考以下文章