第十二周:( LeetCode576) Out of Boundary Paths(c++)

这是一道新题,难度为Hard,类型为动态规划。

原题:There is an m by n grid with a ball. Given the start coordinate (i,j) of the ball, you can move the ball to adjacent cell or cross the grid boundary in four directions (up, down, left, right). However, you can at most move N times. Find out the number of paths to move the ball out of grid boundary. The answer may be very large, return it after mod 10^9 + 7.

思路:
动态规划最关键的就是找到动态转移方程,如果不考虑grid边界、不考虑int是否溢出等问题,本题的动态转移方程为:grid[x][y]=pre_grid[x-1][y]+pre_grid[x+1][y]+pre_grid[x][y-1]+pre_grid[x][y+1]。其中,用grid[x][y]保存第t步的结果,pre_grid[x][y]保存第t-1步的结果。为了减少繁琐的是否溢出grid边界的判断,在grid[x][y]上下左右各加两行(列),最外一行(列)任何时刻的值都为0(这样不会对结果产生影响),主要是为了保证grid[x][y]=pre_grid[x-1][y]+pre_grid[x+1][y]+pre_grid[x][y-1]+pre_grid[x][y+1]的表达式在任何情况下都不发生数组越界;再往里的一行(列)保存每一步中足球跳出grid的情况(由于足球跳出之后不会再跳回,因此这一行(列)的值在每一步结果算出来之后都要更新为0)。为此,需要做个简单的映射,把原来在位置[i,j]的球映射到[i+2,j+2]。另外,本题的结果很可能超出int范围,按照题目的提示要及时mod 10^9 + 7。时间复杂度为O(N*m*n)。

代码:

#define MOD 1000000007

class Solution {
public:
    int findPaths(int m, int n, int N, int i, int j) {
        int grid[m+4][n+4],pre_grid[m+4][n+4];
        int ans=0;
        //映射
        i=i+2;
        j=j+2;
        //初始化
        memset(grid,0,sizeof(grid));
        memset(pre_grid,0,sizeof(pre_grid));
        pre_grid[i][j]=1;
        for(int t=0;t<N;t++){
            for(int x=1;x<=(m+2);x++){
                for(int y=1;y<=(n+2);y++){
                    grid[x][y]=((pre_grid[x-1][y]+pre_grid[x+1][y])%MOD+(pre_grid[x][y-1]+pre_grid[x][y+1])%MOD)%MOD;
                    //这种情况为足球跳出的情况,即我们所要求的结果
                    if((x==1)||(y==1)||(x==(m+2))||(y==(n+2))){
                        ans=(ans+grid[x][y])%MOD;
                        grid[x][y]=0;
                    }
                }
            }
            //每一步的情况只与上一步有关,更新pre_grid[x][y]
            for(int x=1;x<=(m+2);x++)
                for(int y=1;y<=(n+2);y++)
                    pre_grid[x][y]=grid[x][y];
        }
        return ans%MOD;
    }
};

代码还算比较高效!
Result

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值