576. Out of Boundary Paths(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 109 + 7.

Example 1:
Input:m = 2, n = 2, N = 2, i = 0, j = 0
Output: 6
Explanation:

1

Example 2:
Input:m = 1, n = 3, N = 3, i = 0, j = 1
Output: 12
Explanation:

2
Note:
1.Once you move the ball out of boundary, you cannot move it back.
2.The length and height of the grid is in range [1,50].
3.N is in range [0,50].

题目大意如下:
  给定一个m行n列的一个表格和一个球,球的初始坐标按(i,j)的形式给出,你可以每次向四个方向(上下左右)移动这个球一步,但是最多只能移动N步。要求找到所有把球移出这个表格(出界)的方法的次数。答案特别大所以要mod109 + 7再返回。

解题思路:

  设p[i][j][k]:做第i次移动的时候,横坐标为j,纵坐标为k的位置上“有球”。
  
  过程:
  
  ①初始p[0][x][y]=1(我把初始坐标(i,j)变更为(x,y)防止混淆),表示(x,y)这个位置有球,对于每一个p[i][j][k],考虑p[i-1][j][k](对所有j和所有k),如果p[i-1][j][k]不为0,即上一步(i,j)这个位置“有球”。
  
  ②对于每一个“有球”的位置,考虑四个方向的移动——i+1,i-1,j+1,j-1,如果移动后坐标合法,即没有被移除边界则p[i][new_i][new_k]+=p[i-1][j][k],这是一个优化,因为可能多次移动到同一个地方,反之,如果被移除了边界count+=p[i-1][j][k],这两个公式就是状态转移的过程;
  
  ③最后我们需要的答案就是count。

代码如下:

class Solution {
public:
    int findPaths(int m, int n, int N, int x, int y) {
        int p[N+1][m][n] ;
        int count = 0 ;
        int mod = (int)(1e9+7) ;
        memset(p, 0 , sizeof(p)) ;
        p[0][x][y] = 1 ;
        for(int i = 1 ; i <= N ; ++i){
             for(int j = 0 ; j < m ; ++j){
                for(int k = 0 ; k < n ; ++k){
                    if(p[i-1][j][k] != 0){
                        //cout << "检查到: " <<"p["<<i-1<<"]["<<j<<"]["<<k<<"]="<< p[i-1][j][k] <<endl;

                        if(j+1 < 0 || j+1 >= m) {
                            count +=p[i-1][j][k] ;
                            count %=mod ;
                            //cout <<"p["<<i<<"]["<<j+1<<"]["<<k<<"]"<<" 不合法"<<endl;
                        }
                        else {
                            //cout << "位置: " <<"p["<<i<<"]["<<j+1<<"]["<<k<<"]"<<" 加一"<<endl;
                            p[i][j+1][k]+=p[i-1][j][k] ;
                            p[i][j+1][k]%=mod ;
                        }
                        if(j-1 < 0 || j-1 >= m) {
                            count +=p[i-1][j][k] ;
                            count %=mod ;
                            //cout <<"p["<<i<<"]["<<j-1<<"]["<<k<<"]"<<" 不合法"<<endl;
                        }
                        else {
                            //cout << "位置: " <<"p["<<i<<"]["<<j-1<<"]["<<k<<"]"<<" 加一"<<endl;
                            p[i][j-1][k]+=p[i-1][j][k] ;
                            p[i][j-1][k]%=mod ;
                        }
                        if(k+1 < 0 || k+1 >= n) {
                            count +=p[i-1][j][k] ;
                            count %=mod ;
                            //cout <<"p["<<i<<"]["<<j<<"]["<<k+1<<"]"<<" 不合法"<<endl;
                        }
                        else {
                            //cout << "位置:  " <<"p["<<i<<"]["<<j<<"]["<<k+1<<"]"<<" 加一"<<endl;
                            p[i][j][k+1]+=p[i-1][j][k] ;
                            p[i][j][k+1]%=mod ;
                        }
                        if(k-1 < 0 || k-1 >= n) {
                            count +=p[i-1][j][k] ;
                            count %=mod ;
                            //cout <<"p["<<i<<"]["<<j<<"]["<<k-1<<"]"<<" 不合法"<<endl;
                        }
                        else {
                            //cout << "位置: " <<"p["<<i<<"]["<<j<<"]["<<k-1<<"]"<<" 加一"<<endl;
                            p[i][j][k-1]+=p[i-1][j][k] ;
                            p[i][j][k-1]%=mod ;
                        }
                    }

                }
             }
        }
        return count%mod ;
    }
};

算法分析:
  三个循环,相当于填补一个三维的矩阵,所以复杂度显然为O(n³)。

### 关于 `self.draw_boundary` 方法 对于 `self.draw_boundary` 的具体实现细节,在标准库或者广泛认可的第三方库中并没有直接提及此名称的方法。然而,从上下文中推测这可能是某个特定应用程序或自定义类中的成员函数。 如果假设这是一个用于图形界面绘制边界的自定义方法,则通常此类功能会涉及到定义边界范围并将其渲染到屏幕上。为了更好地理解这个过程,可以参考类似的绘图操作案例,比如使用Pillow库处理图像时创建边界框的操作[^2]: ```python from PIL import ImageDraw, Image def draw_boundary(image, boundary_coords): """ 在给定图片上画出指定坐标的矩形边界线。 参数: image (Image): 背景图片对象 boundary_coords (tuple): 边界坐标元组(x0,y0,x1,y1),表示左上角和右下角位置 返回: 绘制好边界的新的Image实例 """ draw = ImageDraw.Draw(image) draw.rectangle(boundary_coords, outline="red", width=3) return image ``` 上述代码展示了如何在一个已有的图像基础上添加红色线条作为边界标记。虽然这不是确切的 `self.draw_boundary` 实现方式,但是提供了相似逻辑下的编程思路。 另外一种可能性是该方法属于 CAD 或者其他工程设计软件 API 中的一部分,类似于 NX 二次开发里的 `UF_DRAW_define_view_boundary` 函数[^3],它用来设定视图内的显示区域界限。这类应用往往更加专业化,并且依赖具体的平台文档来获取详细的参数列表与调用指南。 由于缺乏更精确的信息来源,以上解释基于现有资料进行了合理的推断。建议查阅项目本身的官方手册或是询问开发者团队以获得最权威的帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值