Ignatius and the Princess III (递推)

来源:互联网 发布:apache php显示源代码 编辑:程序博客网 时间:2024/06/04 17:58

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

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 125int 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);}}


原创粉丝点击