《算法设计与分析》第五周作业
标签(空格分隔): 课堂作业
姓名:李**
学号:16340114
题目:Unique Paths(https://leetcode.com/problems/unique-paths/description/)
前言
俗话说得好,有作业的假期就不能叫假期,要写算法博客的国庆还能叫国庆吗?
国庆要回家,回家前先把博客给写(shui)了吧
题目概要
给定一个m*n的矩阵,一个机器人在左上角,目的地在右下角(点题目链接看图),机器人每次只能往下走或者往右走,问机器人走到终点有多少条独特的路径。
思路
其实这个很简单啊,机器人必须要向右走m-1次,向下走n-1次,进行简单的排列组合就可以得到答案的。总共要走(m + n - 2)次,在这(m + n - 2)次中,选择(m - 1)次向右走就可以,所以答案就是
C
m
+
n
−
2
m
−
2
C^{m-2}_{m+n-2}
Cm+n−2m−2
你以为这就结束了吗?这可是国庆特别版欸。我这么简单明了的算法肯定是可以打败100%的人啦。抱着好奇的心理去discussion里看了别人的答案,看完之后我的表情是这样的:
(图片来自网络)
很多版本的答案都使用了递归,从目的地开始递归,计算当前的路径个数,一直用向左或者向上的走法进行bfs,递归回到起点,得到答案。不得不说这样的做法确实是很慢很麻烦(相比于我发现的偷鸡解法),但这不能否定这个思想是一个很重要的思想,可以在不能投机取巧的时候作为通用一个解题思路去解题。
具体实现
真做起来的时候发现 C m + n − 2 m − 2 C^{m-2}_{m+n-2} Cm+n−2m−2还真是不好算,先算分子吧,会overflow;乘一个分子再除一个分母吧,又会发生精度误差(long double都救不回来)。还好这题的分子不大,直接算分子再算分母,最后相除就阔以了。
心得
学到老活到老。
一门好课程应该在放假的时候把作业取消掉。
源码:
class Solution {
public:
int uniquePaths(int m, int n)
{
if (m < n)
return uniquePaths(n, m);
long double result = 1;
int x = m - 1;
int y = n - 1;
int bound = y;
int z = x + y;
for (int i = 0; i < bound; i++)
{
result *= (long double)z;
z--;
}
for (int i = 0; i < bound; i++)
{
result /= (long double)y;
y--;
}
return (int)result;
}
};