井字格不重复最多走法

题目:

  • 从起点(0,0)沿着边走到终点(m,n),走的路不重复,求有多少种不同的走法?
    在这里插入图片描述

算法设计

  • 方法一:利用递归思想,从终点(m,n)来看,能走到终点的走法有多少种,假设paths(m,n)表示从起点走到(m,n)的走法数量,那么有表达式:paths(m,n)=paths(m,n-1)+paths(m-1,n)。含义是,到达(m,n)点的走法等于到达(m,n-1)的走法加上到达(m-1,n)的走法,只有这两个途径可以到达(m,n)。
  • 方法二:动态规划,待补充

算法实现

  • 方法一:递归算法
public class WellPath {

    public static long count = 0;

    /**
     * 递归算法
     * paths(m,n)=paths(m-1,n)+paths(m,n-1)
     * 特殊点m=n=0,m<0,n<0
     */
    public static long paths(int m, int n) {
        if (m == 0 && n == 0) {
            return 1;
        }
        if (m < 0 || n < 0) {
            return 0;
        }

        count++;

        return paths(m - 1, n) + paths(m, n - 1);
    }

    public static void main(String[] args) {
        long start = System.nanoTime();
        long result = WellPath.paths(14, 14);
        long end = System.nanoTime();
        System.out.printf("paths: %s,recurse count:%d,time:%d (microsecond)", result, count, (end - start) / 1000);

    }
}

输出结果:

paths: 40116600,recurse count:115000919,time:445815 (microsecond)

import datetime


class WellPath:
    count = 0

    def paths(self, m, n):
        if m == 0 and n == 0:
            return 1
        if m < 0 or n < 0:
            return 0
        self.count += 1
        return self.paths(m - 1, n) + self.paths(m, n - 1)


if __name__ == '__main__':
    well_path = WellPath()
    start = datetime.datetime.now()
    result = well_path.paths(14, 14)
    end = datetime.datetime.now()
    delta = end - start
    print(f'paths: {result},recurse count:{well_path.count},time:{delta.seconds}.{delta.microseconds} s')

输出结果:

paths: 40116600,recurse count:115000919,time:62.990346 s

  • 优点:递归算法简单易懂,实现起来也快

  • 缺点:样例数据过大,会导致递归调用次数过多,性能低

  • 改进:由于在计算paths(m-1,n)时用了paths(m-2,n)+paths(m-1,n-1),计算paths(m,n-1)时用了paths(m-1,n-1)+paths(m,n-2),可以观察出,paths(m-1,n-1)被使用了两次,在计算paths(m-1,n-1)是重复进行了递归计算,这里将之前计算好的paths(m-1,n-1)缓存起来,下次计算需要使用时,就从缓存取,这样减少递归次数。

  • 方法一改进版:引入缓存

public class WellPath {

    public static long count = 0;
    public static long[][] cache = new long[100][100];

    /**
     * 递归算法
     * paths(m,n)=paths(m-1,n)+paths(m,n-1)
     * 特殊点m=n=0,m<0,n<0
     */
    public static long paths(int m, int n) {
        if (m == 0 && n == 0) {
            return 1;
        }
        if (m < 0 || n < 0) {
            return 0;
        }

        count++;

        if (cache[m][n] > 0) {
            return cache[m][n];
        }
        long result = paths(m - 1, n) + paths(m, n - 1);
        cache[m][n] = result;
        return result;
    }

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        long result = WellPath.paths(14, 14);
        long end = System.currentTimeMillis();
        System.out.printf("paths: %s,recurse count:%d,time:%d", result, count, (end - start));

    }
}

输出结果:

paths: 40116600,recurse count:419,time:43 (microsecond)


import datetime


class WellPath:
    count = 0
    cache = [[0 for i in range(100)] for j in range(100)]

    def paths(self, m, n):
        if m == 0 and n == 0:
            return 1
        if m < 0 or n < 0:
            return 0
        self.count += 1
        if self.cache[m][n] > 0:
            return self.cache[m][n]

        temp = self.paths(m - 1, n) + self.paths(m, n - 1)
        self.cache[m][n] = temp
        return temp


if __name__ == '__main__':
    well_path = WellPath()
    start = datetime.datetime.now()
    result = well_path.paths(14, 14)
    end = datetime.datetime.now()
    delta = end - start
    print(f'paths: {result},recurse count:{well_path.count},time:{delta.seconds}.{delta.microseconds} s')

输出结果:

paths: 40116600,recurse count:419,time:0.998 s

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiyubaby.17

您的鼓励是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值