Ignatius and the Princess III (递推)

整数划分问题是一个经典的递归问题。

dp[n][m]表示 整数n的m划分为 n=x1+x2+x3+...+x;其中xi的最大值小于等于m;

那么我们讨论一下怎么把问题转换为其子问题;

1、当m=1或者n=1 时 显然dp[n][m]=1;

2、当n<m时 问题转换为整数n的n划分 dp[n][m]=dp[n][n];

3、当n=m时 分两种情况考虑 

3.1、当划分的数中包含m时,dp[n][m]=1;

3.2、当划分的数不包含m时,问题转换为整数n的m-1的划分 dp[n][m]=dp[n][m-1];

4、当n>m时 同样分为两种情况

4.1、当划分的数中包含m时,问题转换为整数n-m的m的划分 dp[n][m]=dp[n-m][m];

4.2、当划分的数中不包含m时,问题转换为整数n的m-1的划分 dp[n][m]]=dp[n][m-1];

综上所述:

dp(n, m)=   1;                (n=1 或者 m=1)

                             dp(n, n);                        (n<m)

                             1+dp(n, m-1);                (n=m)

                             dp(n-m,m)+dp(n,m-1);      (n>m)

直接递归会超时,那么我们可以采用记忆化搜索的方式解决或者用递推。

下面是记忆化搜索的代码:

#include <stdio.h>
#include <string.h>
#define maxn 125
int dp[maxn][maxn];
int dfs(int n,int m)
{

	int i,j;
	if(dp[n][m]!=-1)	return dp[n][m];
	if(n==1 || m==1)	return 1;
	if(n<m)	dp[n][m]=dfs(n,n);
	else if(n==m)	dp[n][m]=1+dfs(n,m-1);
	else if(n>m)	dp[n][m]=dfs(n-m,m)+dfs(n,m-1);
	return dp[n][m];
		
}
int main()
{
	int N,sum;
	memset(dp,-1,sizeof(dp));

	while(scanf("%d",&N)==1)
	{
		sum=dfs(N,N);
		printf("%d\n",sum);	
	}	
}



你可能感兴趣的:(Ignatius and the Princess III (递推))