[Project Euler] 来做欧拉项目练习题吧: 题目015

                                       [Project Euler] 来做欧拉项目练习题吧: 题目015

                                                    周银辉

 

问题描述

Starting in the top left corner of a 2×2 grid, there are 6 routes (without backtracking) to the bottom right corner.

How many routes are there through a 20×20 grid? 

 

问题分析

这个题需要一点点观察能力:

观察2*2的方格,以左上角为起点,右下角为终点,形成的所有路径刚好可以构成一棵二叉树。

(不走回头路,并且以经过的方格上的节点为树节点,其中方格左上角为根节点,叶子节点始终是方格右下角)。

而路径条数也就是树的叶子节点个数。

用Count[A]表示树A的叶子节点个数,Left,Right表示左右子树.那么Count[A] = Count[Left] + Count[Right]

OK,问题就变得很简单了,一个递归算法就可以解决。

此后的问题,就是优化递归算法(创建一个缓冲区),减少重复运算,否则速度是不可接受的。

#include <stdio.h>
#define SZ    21        //20*20, index from 0 to 20, so size is 21 
#define END (SZ-1)
long long grid[SZ][SZ];
long long test(int i, int j)
{
int record = grid[i][j];
if(record!=0)
{
return record;
}
if(i==END && j==END)
{
return 1;
}
long long left=0, right=0, total=0;
int  ni=i+1, nj=j+1; //ni: next i
if(ni<SZ)
{
left = test(ni, j);
grid[ni][j] = left;
}
if(nj<SZ)
{
right = test(i, nj);
grid[i][nj] = right;
}
total = left+right;
grid[i][j] = total;
return total;
}
int main()
{
printf("path count: %lld\n", test(0,0));
return 0;
}

速度挺快的:

real    0m0.004s

user    0m0.001s

sys     0m0.003s 

 

posted @ 2011-02-24 00:56 周银辉 阅读(1486) 评论(6) 编辑 收藏

 回复 引用 查看   
#1楼 2011-02-24 08:27 万仓一黍      
这个不需要用递归。直接分析即可。
通过分析,可以看出这个和“杨辉三角形”的值是一样的。
而“杨辉三角形”是和组合数是一致的。
因此,通过分析,有下面的公式
假设有n行,m列(n≥1,m≥1)。则题目的解为
C(n,n+m)。有关组合数的计算公式这里不介绍了。

如文章里提到的2行2列,则解为
C(2,4)=6

文章里提到的20行20列,则解为
C(20,40)=137846528820

 回复 引用 查看   
#2楼[楼主] 2011-02-24 09:16 周银辉      
@万仓一黍
哈哈,thanks

 回复 引用 查看   
#3楼 2011-02-24 10:59 devil0153      
我做这题的时候方法更笨,做出来后才发现C(n,2n)根本不用写程序就可以算出来,我的笨方法基本就是观察法加递推法
    class Program
    {
        static List<List<long>> list = new List<List<long>>() { new List<long>() { 1 } };

        static void Main(string[] args)
        {
            for (int n = 1; n < 20; n++)
            {
                var preList = list[n - 1];
                var sum = 0L;
                List<long> cells = new List<long>();
                for (int i = 0; i < preList.Count; i++)
                {
                    cells.Add(sum += preList[i]);
                }
                cells.Add(preList.Sum() * 2);
                list.Add(cells);
            }
            Console.WriteLine(list.Last().Sum() * 2);
            Console.ReadKey();
        }
    }

 回复 引用 查看   
#4楼[楼主] 2011-02-24 13:40 周银辉      
@devil0153
呵呵呵,也挺好的

 回复 引用 查看   
#5楼 2011-03-04 16:10 玫瑰季节      
呵呵, 直接使用非递归的加法: 对角线扫描法即可

P(i,j) = P(i-1,j) + P(i,j-1);

 回复 引用 查看   
#6楼 2011-03-21 13:15 Viaxl      
@万仓一黍
不用牵扯到杨辉三角形..
n*n的矩形, 就是走2n步 选出n步朝右 剩下的朝下
也就是C(n,2n)..

发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 1963358 ri4wWyivvBE=