给定一个m*n的地图,其中加入了一些障碍。每次只能向下或者向右走,问从左上角走到右下角有多少不同的路径?
分别用0和1代表空区域和障碍
例如
下图表示有一个障碍在3*3的图中央。
[
[0,0,0],
[0,1,0],
[0,0,0]
] 有2条不同的路径 备注:m和n不超过100.
class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int> > &a) {
int i, j, m = a.size(), n = a[0].size();
vector<vector<int> > dp(m, vector<int>(n, 0)); // 初始化成0
// 第一个格点的值与障碍数相反
dp[0][0] = 1 - a[0][0];
// 依次计算
for(i = 0; i < m; ++i) {
for(j = 0; j < n; ++j) {
// 只有没有障碍才有通路
if(a[i][j] == 0) {
if(i == 0 && j != 0) dp[0][j] = dp[0][j - 1]; // 左
else if(i != 0 && j == 0) dp[i][0] = dp[i - 1][0]; // 上
else if(i != 0 && j != 0) dp[i][j] += dp[i - 1][j] + dp[i][j - 1]; // 左+上
}
}
}
return dp[m - 1][n - 1];
}
};
public class Solution {
//初始化两个for循环赋值可以免去,空间复杂度可以降到一维
//个人觉得直接修改输入数据应该不是很合适的做法
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int rowLen = obstacleGrid.length;
int colLen = obstacleGrid[0].length;
int[] res = new int[colLen + 1];
res[1] = 1;
for (int i = 1; i <= rowLen; i++) {
for (int j = 1; j <= colLen; j++) {
if (obstacleGrid[i - 1][j - 1] == 0) {
//res[i]保存的是上一行的值,当前值直接用左边的值加上上一行的值
res[j] += res[j - 1];
} else {
res[j] = 0;
}
}
}
return res[colLen];
}
}
class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int> > &obstacleGrid) {
if(obstacleGrid.empty()){
return 0;
}
int m = obstacleGrid.size();
int n = obstacleGrid[0].size();
vector<vector<int>> F(m, vector<int>(n, 0));
for(int i = 0; i < m; ++i){
if(obstacleGrid[i][0] == 1){
break;
}
F[i][0] = 1;
}
for(int j = 0; j < n; ++j){
if(obstacleGrid[0][j] == 1){
break;
}
F[0][j] = 1;
}
for(int i = 1; i < m; ++i){
for(int j = 1; j < n; ++j){
if(obstacleGrid[i][j] == 1){
F[i][j] = 0;
}
else{
F[i][j] = F[i - 1][j] + F[i][j - 1];
}
}
}
return F[m - 1][n -1];
}
}; /*
* 目的:找路径,找路径的拓展
* 方法:动态规划
*/
//方法一:使用二维dp,时间复杂度为O(n^2),空间复杂度为O(n^2)
int uniquePathsWithObstacles(vector<vector<int> > &obstacleGrid) {
int row = obstacleGrid.size();
if (row==0) return 0;
int col = obstacleGrid[0].size();
vector<vector<int>>dp(row,vector<int>(col,1));
for (int i = 0; i < row;++i){
if (obstacleGrid[i][0] == 1){
dp[i][0]=0;
}
else{
dp[i][0] = i==0?1:dp[i-1][0];
}
}
for (int j = 0; j <col;++j){
if (obstacleGrid[0][j] == 1){
dp[0][j] = 0;
}
else{
dp[0][j] = j==0?1:dp[0][j-1];
}
}
for (int i = 1; i < row;++i){
for (int j = 1; j<col;++j){
if (obstacleGrid[i][j] == 1){
dp[i][j] = 0;
}
else{
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
}
return dp[row-1][col-1];
}
//方法二:使用一维dp,时间复杂度O(n^2),空间复杂度O(n)
int uniquePathsWithObstacles(vector<vector<int> > &obstacleGrid) {
int m = obstacleGrid.size(),n = obstacleGrid[0].size();
vector<int>dp(n,0);
dp[0] = 1;
for (int i = 0; i < m; ++i){
for (int j =0; j < n; ++j){
if (obstacleGrid[i][j]==1)
dp[j]=0;
else if (j>0){
dp[j] = dp[j]+dp[j-1];
}
}
}
return dp[n-1];
}
public class Solution {
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int m = obstacleGrid.length;
int n = obstacleGrid[0].length;
int [][] dp = new int[m][n];
dp[0][0] = 1-obstacleGrid[0][0];//初始化
for(int i=0;i<m;i++)
for(int j=0;j<n;j++ ){
//该句可以避免无用功,如果是阻碍点直接丢弃,进入下一个点,同时dp[i][j]=0不影响
if(obstacleGrid[i][j]==0){
if(i==0 && j!=0)
dp[0][j] = dp[0][j-1];//右赋值
else if(i!=0 && j==0)
dp[i][0] = dp[i-1][0];//左赋值
else if(i!=0 && j!=0)
dp[i][j]=dp[i-1][j]+dp[i][j-1];//左+上赋值
else
continue;
}
}
return dp[m-1][n-1];
}
}
空间换时间,重新搭建一个矩阵 ,将不能通过的地方为0,边界上的点通过后一个点根据前一个点进行 计算,其他的点则通过上,左进行计算
class Solution {
public static int uniquePathsWithObstacles(int[][] obstacleGrid) {
int m=obstacleGrid.length,n=obstacleGrid[0].length;
int dp[][] = new int[m][n];
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(obstacleGrid[i][j]==1){
dp[i][j]=0;
continue;
}
//初始化dp[0][0]
if(i==0&&j==0){
dp[i][j]=1;
continue;
}
//第一行
if(i==0){
dp[i][j]=dp[i][j-1];
continue;
}
//第一列
if(j==0){
dp[i][j]=dp[i-1][j];
continue;
}
//上述情况之外
dp[i][j]=dp[i-1][j]+dp[i][j-1];
}
}
return dp[m-1][n-1];
}
}
int uniquePathsWithObstacles(vector<vector<int> > &obstacleGrid) {
int m=obstacleGrid.size();
int n=obstacleGrid[0].size();
vector<vector<int>> dp(m,vector<int>(n,0));
for(int i=0;i<m;i++){
if(obstacleGrid[i][0]!=1)
dp[i][0]=1;
else
break;
}
for(int j=0;j<n;j++){
if(obstacleGrid[0][j]!=1)
dp[0][j]=1;
else
break;
}
for(int i=1;i<m;i++){
for(int j=1;j<n;j++){
if(obstacleGrid[i][j]==1)
dp[i][j]=0;
else
dp[i][j]=dp[i-1][j]+dp[i][j-1];
}
}
return dp[m-1][n-1];
}
class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int> > &obstacleGrid) {
int n = obstacleGrid.size();
int m = obstacleGrid[0].size();
if(n==0 || m==0)
return 0;
vector<int> dp(m,0);
dp[0] = 1;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
if(obstacleGrid[i][j] == 1)
dp[j] = 0;
else if(j != 0)
dp[j] += dp[j-1];
}
return dp[m-1];
}
}; class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int> > &obstacleGrid)
{
/*
int m=obstacleGrid.size(),n=obstacleGrid[0].size();
if(obstacleGrid.empty())
return 0;
int dp[m][n];
fill_n(&dp[0][0],m*n,0);
dp[0][0] = obstacleGrid[0][0]==1? 0 : 1;
for(int i=1;i<m;i++)
dp[i][0] = obstacleGrid[i][0]==1 ? 0 : dp[i-1][0];
for(int j=1;j<n;j++)
dp[0][j] = obstacleGrid[0][j]==1 ? 0 : dp[0][j-1];
for(int i=1;i<m;i++)
{
for(int j=1;j<n;j++)
{
dp[i][j] = obstacleGrid[i][j]==1 ? 0 : dp[i-1][j] + dp[i][j-1];
}
}
return dp[m-1][n-1];
}
*/
/// 使用O(n)空间的方案
int m=obstacleGrid.size(),n=obstacleGrid[0].size();
if(m==0 || n==0)
return 0;
vector<int> res(n,0);
res[0] = 1;
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
if(obstacleGrid[i][j]==1)
res[j] = 0;
else if(j>0)
res[j] = res[j]+res[j-1];
}
}
return res[n-1];
}
};
package suda.alex.leetcode;
public class UniquePathsWithObstacles {
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int m = obstacleGrid.length;
int n = obstacleGrid[0].length;
int[][] dp = new int[m][n];
for (int i = 0; i < m && obstacleGrid[i][0] != 1; i++) {
dp[i][0] = 1;
}
for (int j = 0; j < n && obstacleGrid[0][j] != 1; j++) {
dp[0][j] = 1;
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
if(obstacleGrid[i][j] == 1){
dp[i][j] = 0;
}
else{
dp[i][j] = dp[i][j - 1] + dp[i - 1][j];
}
}
}
return dp[m - 1][n - 1];
}
}
public class Solution {
public int uniquePathsWithObstacles(int[][] grid) {
if(grid.length < 1 || grid[0].length < 1 || grid[0][0] == 1){
return 0;
}
int dp[] = new int[grid[0].length];
dp[0] = 1;
for(int i = 1; i < grid[0].length; i++) {
dp[i] = grid[0][i] == 0 ? dp[i-1] : 0;
}
for(int i = 1; i < grid.length; i++){
dp[0] = grid[i][0] != 1 ? dp[0] : 0;
for(int j = 1; j < grid[0].length; j++) {
dp[j] = grid[i][j] != 1 ? dp[j-1] + dp[j] : 0;
}
}
return dp[grid[0].length - 1];
}
}
class Solution
{
public:
int uniquePathsWithObstacles(vector<vector<int> > &obstacleGrid)
{
if(obstacleGrid[0][0]==1)return 0;
int a=obstacleGrid.size(),b=obstacleGrid[0].size();
for(int i=0;i<a;++i)
{
if(obstacleGrid[i][0]==1)
{
for(;i<a;++i)
obstacleGrid[i][0]=0;
}
else obstacleGrid[i][0]=1;
}
for(int i=1;i<b;++i)
if(obstacleGrid[0][i]==1)
{
for(;i<b;++i)
obstacleGrid[0][i]=0;
}
else obstacleGrid[0][i]=1;
for(int i=1;i<a;++i)
for(int j=1;j<b;++j)
{
if(obstacleGrid[i][j]==1)obstacleGrid[i][j]=0;
else
obstacleGrid[i][j]=obstacleGrid[i-1][j]+obstacleGrid[i][j-1];
}
return obstacleGrid[a-1][b-1];
}
};
public class Solution {
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
if(obstacleGrid.length==0)
return 0;
if(obstacleGrid[0][0]==1)
return 0;
obstacleGrid[0][0] = 1;
for(int j = 1;j<obstacleGrid[0].length;j++){
obstacleGrid[0][j] = obstacleGrid[0][j]==1?0:obstacleGrid[0][j-1];
}
for(int i = 1;i<obstacleGrid.length;i++){
for(int j = 0;j<obstacleGrid[i].length;j++){
if(obstacleGrid[i][j]==1)
obstacleGrid[i][j] = 0;
else
obstacleGrid[i][j] = (j-1>=0?obstacleGrid[i][j-1]:0)+obstacleGrid[i-1][j];
}
}
return obstacleGrid[obstacleGrid.length-1][obstacleGrid[0].length-1];
}
}
public class Solution {
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int[][] dp = new int[obstacleGrid.length][obstacleGrid[0].length];
for (int i = 0; i < dp.length; i ++ ) {
if(obstacleGrid[i][0] == 1) break;
dp[i][0] = 1;
}
for (int i = 0; i < dp[0].length; i ++ ) {
if(obstacleGrid[0][i] == 1) break;
dp[0][i] = 1;
}
for (int i = 1; i < dp.length; i ++ ) {
for (int j = 1; j < dp[0].length; j ++ ) {
if(obstacleGrid[i][j] == 1) dp[i][j] = 0;
else dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
return dp[dp.length - 1][dp[0].length - 1];
}
}
class Solution {
public:
/**
*
* @param obstacleGrid int整型vector<vector<>>
* @return int整型
*/
int uniquePathsWithObstacles(vector<vector<int> >& g) {
if(g.size()==0 || g[0].size()==0) return 0;
// write code here
int n = g.size(),m = g[0].size();
vector<vector<int> >dp(n,vector<int>(m));
for(int i=0;i<n;++i) {
for(int j=0;j<m;++j) {
if(i==0&& j==0) {
dp[i][j] = g[i][j]==0;
}else if(i==0) {
if(g[i][j]==0) dp[i][j] += dp[i][j-1];
}else if(j==0) {
if(g[i][j]==0)
dp[i][j] +=dp[i-1][j];
}else {
if(g[i][j]==0) {
dp[i][j] += (dp[i-1][j]+dp[i][j-1]);
}
}
}
}
return dp[n-1][m-1];
}
}; int uniquePathsWithObstacles(vector<vector<int> >& obstacleGrid) {
// write code here
int m = obstacleGrid.size(), n = obstacleGrid[0].size();
int i, j;
vector<vector<int>> graph(m, vector<int> (n,0));
for (i = 0; i < m; i++)//对行列进行处理
{
if (obstacleGrid[i][0] != 1)
graph[i][0] = 1;
else
break;
}
for (i = 0; i < n; i++)
{
if (obstacleGrid[0][i] != 1)
graph[0][i] = 1;
else
break;
}
for (i = 1; i < m; i++)
{//从[1][1]开始统计更新
for (j = 1; j < n; j++)
{
graph[i][j] = graph[i - 1][j] + graph[i][j - 1];
if (obstacleGrid[i][j] == 1)
{
graph[i][j] = 0;
}
}
}
return graph[m - 1][n - 1];
}
设dp[i][j]表示前i行和前j列最短路径数,状态方程如下:
i >= 2 && j >= 2时,obstacle[i-2][j-1] != 1, dp[i][j] += dp[i-1][j] obstacle[i-1][j-2] != 1, dp[i][j] += dp[i][j-1] dp[1][k] = obstacle[0][k-1] != 1 && dp[1][k-1]!=0 ? 1 : 0 dp[k][1] = obstacle[k-1][0] != 1 && dp[k-1][1]!=0 ? 1 : 0 解释如下:
左侧非阻塞节点的最短路径数+上侧非阻塞节点的最短路径数 代码如下:
//
// Created by jt on 2020/8/30.
//
#include <vector>
using namespace std;
class Solution {
public:
/**
*
* @param obstacleGrid int整型vector<vector<>>
* @return int整型
*/
int uniquePathsWithObstacles(vector<vector<int> >& obstacleGrid) {
// write code here
if (obstacleGrid.size() < 1 || obstacleGrid[0].size() < 1) return 0;
vector<vector<int> > dp(obstacleGrid.size() + 1, vector<int>(obstacleGrid[0].size() + 1, 0));
if (obstacleGrid[0][0] == 0) dp[1][1] = 1;
for (int i = 2; i <= obstacleGrid.size(); ++i) { dp[i][1] = dp[i-1][1]!=0 && obstacleGrid[i-1][0]!=1 ? 1 : 0; }
for (int i = 2; i <= obstacleGrid[0].size(); ++i) { dp[1][i] = dp[1][i-1]!=0 && obstacleGrid[0][i-1]!=1 ? 1 : 0; }
for (int i = 2; i <= obstacleGrid.size(); ++i) {
for (int j = 2; j <= obstacleGrid[0].size(); ++j) {
dp[i][j] += obstacleGrid[i-2][j-1] == 0 ? dp[i-1][j] : 0;
dp[i][j] += obstacleGrid[i-1][j-2] == 0 ? dp[i][j-1] : 0;
}
}
return dp[obstacleGrid.size()][obstacleGrid[0].size()];
}
};