Description
一个实验室有N个放化学品的试管,排列在一条直线上。如果连续M个试管中放入药品,则会发生爆炸,于是,在某些试管中可能不放药品。
任务:对于给定的N和M,求不发生爆炸的放置药品的方案总数
Input
第一行是一个正整数L,代表输入数据的组数
接下来L行,每行有两个正整数N,M( 1<N<32,2≤M≤5)
Output
输出L行,每行只有一个正整数S,表示对应输入数据的方案总数。
Sample Input
2
4 3
3 2
Sample Output
13
5
个人思路:
通过递归来计算可行的方案数。若N=M,则总方案数为2^N-1。 若N<M,则总方案数为2^N。难处理的就是N>M的时候,这时候可以通过N-1的方案数和N-M-1的方案数推出N的方案数。由N-1变成N可以在N-1个试管后放一个试管, 因为试管有放药品和不放药品两个选择,所以是2*N-1的方案数,若是试管装药品可能会爆炸,需要将错误的方案数剔除,而不合题意只能是第N个试管的前面M-1个试管都放药品,第前M个不放药品。所以不合要求的为N-M-1试管放药品合题意的方案数。
参考代码:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int f(int n, int m, int t[33][6])
{
if(t[n][m])
return t[n][m];
if(n<m)
{
t[n][m]=pow(2,n);
return t[n][m];
}
if(n==m)
{
t[n][m]=pow(2,n)-1;
return t[n][m];
}
t[n][m]=f(n-1,m,t)+f(n-1,m,t)-f(n-1-m,m,t);
return t[n][m];
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif // ONLINE_JUDGE
int t,n,m;
scanf("%d", &t);
while(t--)
{
int t[33][6]= {0};
scanf("%d %d", &n, &m);
printf("%d\n", f(n, m, t));
}
return 0;
}