描述
一农夫挖了n个坑,准备种萝卜,n个坑排成一条直线,农夫认为如果连续m个坑都放入萝卜种子,那么就会影响萝卜的生长,所以某些坑中就不能放萝卜种子。
本题的任务是:对于给定的n和m,求不影响生长的种法的总数。
输入一行两个正整数n和m,之间用空格隔开
0≤n≤64 , 0≤m≤5输出一行一个正整数,表示正确种法的总数
样例输入
4 3
样例输出
13
提示
找呗0个坑只有不种一种情况;1个坑要看m的情况
解题思路
很显然这道题要使用递推的方法来做。这道题的递推式算是比较难想到的,我认为在做这种递推时要分好情况。例如说这道种萝卜的题目分为三种情况如下:
1.n<m
当坑数小于影响萝卜生长连续坑数时,想一想是不是随便怎样种都行?那如何推出此时的种法数和之前的种法数的关系呢?OK,由于现在n<m的,所以有n-1<m。那当坑数为n-1,影响萝卜生长连续坑数为m时,是不是更加是随便种都行?设此时的种法为f(n-1)(m),好,现在求递推式的关键来了,看一下下面的图你就懂了
当坑数为n-1,影响萝卜生长连续坑数为m时,合理的种法为f(n-1)(m);当坑数为n,影响萝卜生长连续坑数为m时,是不是就是在坑数为n-1加了一个第n个坑?第n个坑的情况为种与不种2种情况,那是不是
f(n)(m)=2* f(n-1)(m)呢?
2.m=n
n=m时,也就是说坑数和影响萝卜生长连续坑数相等时,是不是就是把n个坑全中满这一种情况不行呀?此时我们的递推公式是不是在所有种法的基础上减去1就好了,即f(n)(m)=2* f(n-1)(m)-1;
3.n>m
n>m时,也就是说坑数大于影响萝卜生长连续坑数时,这时的情况比较复杂。看一下下面的图和文字。
假设现在有n个坑,而且为合理种法,那其种法为2*f(n-1)(m);假设当增加1个坑之后,如果这个第n+1个坑要种,后面刚好成了m个连续的坑,就成了不合理的种法。那这种不合理的种法应该有多少种呢?那是不是现在确定了m-1个连续的坑都要种萝卜,而前面n-m-1个坑肯定是为合理种法,有f(n-m-1)(m)种,所以此时不合理的种法应f(n-m-1)(m)种。那此时的合理种法应该为所有的种法减去不合理的种法f(n-m-1)(m),即f(n)(m)= 2*f(n-1)(m)- f(n-m-1)(m)。
参考程序
#include<iostream>
using namespace std;
long long a[66][6];//数组要定义成long long型,要不然到最后会爆
int main()
{
int n,m;
cin>>n>>m;
for(int i=0;i<=n;i++)
for(int j=0;j<=m;j++)
if(i==0)a[i][j]=1;//0个坑只有不种一种情况
else if(i<j)a[i][j]=2*a[i-1][j];//n<m:f(n)(m)=2* f(n-1)(m);
else if(i==j)a[i][j]=2*a[i-1][j]-1;//n=m:f(n)(m)=2* f(n-1)(m)-1
else if(i>j)a[i][j]=2*a[i-1][j]-a[i-1-j][j];//n>m:f(n)(m)= 2*f(n-1)(m)- f(n-m-1)(m)
cout<<a[n][m];
return 0;
}