标签:
我第一时间想到的方案是化归而不是规划,毕竟之前的问题类似,所以就有了这个版本:
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
if (obstacleGrid.empty()){
return 0;
}
const int begin = obstacleGrid.front().front();
if (begin == 1){
return 0;
}
const size_t m = obstacleGrid.size();
const size_t n = obstacleGrid.front().size();
vector<vector<int>> record((m), vector<int>(n));
function<int(size_t, size_t)> getPathsNum;
getPathsNum = [&](int a, int b)
{
if (obstacleGrid[a][b] == 1){
return 0;
}
if (a == 0 && b == 0){
return 1;
}
int&& result = 0;
if (a == 0){
result = getPathsNum(0, b - 1);
record[a][b] = result;
return result;
}
if (b == 0){
result = getPathsNum(a - 1, 0);
record[a][b] = result;
return result;
}
const int paths_num = record[a][b];
if (paths_num != 0){
return paths_num;
}
result = getPathsNum(a - 1, b) + getPathsNum(a, b - 1);
record[a][b] = result;
return result;
};
return getPathsNum(m - 1, n - 1);
}
感觉:嗯嗯,可以可以。一测时间, 92 ms。尼玛用 ruby 的都比我速度快,这玩毛。
后来发现我又陷入 DP 就是递归的思维定势里了,f(m, n) = f(m - 1, n) + f(m, n -1) 这个式子固然可以反着推,但正着填充不是更好?这才发现上面的版本根本不是用的动态规划的思想。
真正 DP 的思想是填充。当然填充也很简单大概意思就是 result[m, n] = result[m - 1, n] + result[m, n - 1]。这才是动规的思想好不拉!
能更省空间吗?我发现其实每一行的结果只依赖上一行,再往上的对它并没有直接影响。那还存储它们作甚?所以只需要一行数据的空间,然后逐行扫描。
int uniquePathsWithObstacles(vector<vector<int> > &obstacleGrid) {
if (obstacleGrid.empty() || obstacleGrid[0][0] == 1 ||
obstacleGrid.back().back() == 1){
return 0;
}
const size_t row_length = obstacleGrid[0].size();
vector<int> row(row_length);
auto const& first_row = obstacleGrid[0];
bool is_blocked = false;
for (size_t i = 0; i != row_length; ++i){
if (is_blocked || first_row[i] == 1){
row[i] = 0;
is_blocked = true;
}else{
row[i] = 1;
}
}
for (size_t i = 1; i != obstacleGrid.size(); ++i){
for (size_t j = 0; j != row_length; ++j){
if (obstacleGrid[i][j] == 1){
row[j] = 0;
}
else if (j > 0){
row[j] = row[j] + row[j - 1];
}
}
}
return row.back();
}
标签:
原文地址:http://www.cnblogs.com/wuOverflow/p/5045756.html