问题描述
每年冬天,北大未名湖上都是滑冰的好地方。北大体育组准备了许多冰鞋,可是人太多了,每天下午收工后,常常一双冰鞋都不剩。
每天早上,租鞋窗口都会排起长龙,假设有还鞋的m个,有需要租鞋的n个。现在的问题是,这些人有多少种排法,可以避免出现体育组没有冰鞋可租的尴尬场面。(两个同样需求的人(比如都是租鞋或都是还鞋)交换位置是同一种排法)
输入格式
两个整数,表示m和n
输出格式
一个整数,表示队伍的排法的方案数。
样例输入
3 2
样例输出
5
数据规模和约定
m,n∈[0,18]
问题分析
思路:动态规划 。
1.将原问题分解为子问题
令dp[i][j]表示:i个还鞋,j个借鞋总方案数。
总共i+j个人,那么最后一个人 可能是 还鞋,也可能是借鞋。
如果最后一个人 可能是 还鞋,那么问题及就变成了:总共i+j-1人,i-1人还鞋,j人借鞋总方案数。即dp[i-1][j]
如果最后一个人 可能是 借鞋,那么问题及就变成了:总共i+j-1人,i人还鞋,j-1人借鞋总方案数。即dp[i][j-1]
则有dp[i][j]=dp[i-1][j]+dp[i][j-1]
2.确定状态
令dp[i][j]表示:i个还鞋,j个借鞋总方案数。
3.确定一些初始状态(边界状态)的值
有
dp[0][0]=0
dp[i][0]=1 (i=1~…)
dp[0][i]=0
4.确定状态转移方程
当i 小于 j时,一定找不到方案,所以dp[i][j]=0
当i==j时,那么最后一个一定是 借鞋,所以dp[i][j]=dp[i][j-1]
当i>j时,最后一个 借鞋,还鞋都可以,所以 dp[i][j]=dp[i-1][j]+dp[i][j-1]
参考资料:http://blog.csdn.net/liuke19950717/article/details/50895142
#include<stdio.h>
int main()
{
int m=0,n=0;
int i=0,j=0;
scanf("%d%d",&m,&n);
int dp[m+1][n+1];
//边界状态的值
dp[0][0]=0;
for(i=1;i<=m;i++)
{
dp[i][0]=1;
}
for(j=1;j<=n;j++)
{
dp[0][j]=0;
}
//其他状态的值
for(i=1;i<=m;i++)
{
for(j=1;j<=n;j++)
{
if(i<j)//i<j
{
dp[i][j]=0;
}
else
{
if(i==j)//i==j
{
dp[i][j]=dp[i][j-1];
}
else//i>j
{
dp[i][j]=dp[i-1][j]+dp[i][j-1];
}
}
}
}
printf("%d",dp[m][n]);
return 0;
}