字节跳动面试题.小兔棋盘 「卡特兰数、动态规划」

1.题目描述

小兔的叔叔从外面旅游回来给她带来了一个礼物,小兔高兴地跑回自己的房间,拆开一看是一个棋盘。小兔有所失望。

只是没过几天发现了棋盘的好玩之处。从起点(0,0)走到终点(n,n)的最短路径数是C(2n,n),如今小兔又想假设不穿越对角线(但可接触对角线上的格点),这种路径数有多少?

小兔想了非常长时间都没想出来,如今想请你帮助小兔解决问题,对于你来说应该不难吧!

 

Input

每次输入一个数n(1<=n<=35),当n等于-1时结束输入。

 

Output

对于每一个输入数据输出路径数。详细格式看Sample。

 

Sample Input

1

3

12

-1

Sample Output

1 1 2

2 3 10

3 12 416024

2.解题思路

方法一:卡特兰数

这道题的规律是经典的卡特兰数。其实对于每一个递进的数字来说,比如5,思考之后可以分为1和4,2和3,3和2,4和1,还有两种直达的,把经过1格的方法乘以经过4格的方法总数,2格的方法总数乘以3格的方法总数……依次类推,就不难发现出规律,卡特兰数*2便是最后的结果,参考:https://blog.csdn.net/zhuge2017302307/article/details/79247532

这是卡特兰数的推倒公式:

来自百度百科,链接:点击打开链接

注意:此题只能用最上面的递推式推导,其他的都会溢出。

参考:https://blog.csdn.net/wyg1997/article/details/51731607

方法二:动态规划

走格点的迷宫,因为不能穿越对角线,所以到达终点只能向上或者向右走。画出图来可以得出,第一行只能由左边走来,而且对角线上的点只能由下面走来,到达其他点各有两种走法。所以我们事先把第一行所有点的值设为1,进行遍历,到达对角线时i==j, map[i][j]=map[i][j-1],只能接受从下面的点传递过来的走法。i!=j时,map[i][j]=map[i-1][j]+map[i][j-1],可以接受两边传递过来的走法。输出的是2*map[n][n]参考:https://blog.csdn.net/blue_skyrim/article/details/49201335

3.代码实现

方法一:卡特兰数

#include <cstdio>
int main()
{
	__int64 Catalan[40] = {0};
	Catalan[0] = 1;
	Catalan[1] = 1;
	for (int i = 2 ; i <= 35 ; i++)
		for (int j = 0 ; j <= i - 1 ; j++)
			Catalan[i] += Catalan[j] * Catalan[i - 1 - j];
	int num = 1;
	int n;
	while (~scanf ("%d",&n) && n != -1)
		printf ("%d %d %I64d\n",num++,n,Catalan[n] * 2);
	return 0;
}

方法二:动态规划

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int n;
long long map[40][40];
int main()
{
    int i,j,cnt=1;;
    while(cin>>n&&n!=-1)
    {
        memset(map,0,sizeof(map));
        for(i=0;i<=n;++i)
            map[0][i]=1;
        for(i=1;i<=n;++i)
            for(j=0;j<=i;++j)
        {
            if(i==j)
                map[i][j]=map[i][j-1];
            else
                map[i][j]=map[i-1][j]+map[i][j-1];
        }
        printf("%d %d %I64d\n",cnt++,n,2*map[n][n]);
    }
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值