每日刷题(六十六)
ALGO-122、未名湖的烦恼
这个题也是个很经典的动归题目,值得细品
递归法:
在极端情况下,排队的都是还鞋的或者都是租鞋的,那么就是一种方法。如果还鞋的比租鞋的人多,那么则随便这次先排哪一类人,
即方案总数为return f(x - 1, y) +f(x, y - 1)
如果已经还鞋的人的总数m - x等于已经租鞋的人的总数n - y则只能让还鞋人先排队,即return f(x - 1, y)
当然最后记得在主函数里加上判断语句if(m < n)就是还鞋人数少于租鞋人数,那就与题意(可以避免出现体育组没有冰鞋可租的尴尬场面)不符,所以输出0,表示不是办法。。。
详细C代码如下:
#include<stdio.h>
int m, n;
int f(int x, int y) //本次排列中某一个位置的人是还鞋还是租鞋
{
if(x == 0 || y == 0)
return 1;
else if(m - x > n - y)
return f(x - 1, y) + f(x, y - 1);
else if(m - x == n - y)
return f(x - 1, y);
}
int main()
{
scanf("%d %d", &m, &n);
if(m < n)
{
printf("0\n");
return 0;
}
int sum = f(m, n);
printf("%d\n", sum);
return 0;
}
递推法:
递推法特点是自底而上,比递归复杂性低,但是规律很难想到,一般依靠循环
#include<stdio.h>
int main()
{
int m, n;
scanf("%d %d", &m, &n);
int dp[20][20] = {0};
if(m < n)
{
printf("0\n");
return 0;
}
else
{
int i, j;
int tmp = m - n;
for(i = 0; i <= m; i++)
dp[i][0] = 1;
for(i = 0; i <= n; i++)
dp[0][i] = 1;
for(i = 1; i <= m; i++)
{
for(j = 1; j <= n; j++)
{
if(i - j < tmp)
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
else
dp[i][j] = dp[i - 1][j];
}
}
}
printf("%d\n", dp[m][n]);
return 0;
}
这个题目我是参看了一下隔壁一位大佬的文章https://blog.csdn.net/jaster_wisdom/article/details/79639539