Ignatius and the Princess III HDU - 1028的题解(两种解题)

递归函数的声明为int split(int n, int m),其中n为要划分的正整数,m是划分中最大的正整数。
4 = 4;
4 = 3 + 1;
4 = 2 + 2;
4 = 2 + 1 + 1;
4 = 1 + 1 + 1 + 1;
5=5;
5=4+1;
5=3+2;
5=3+1+1;
5=2+2+1;
5=2+1+1+1;
5=1+1+1+1+1;
算法的基本思想如下:
将计算过的值存储在备忘录(数组)中,下次使用时直接调用,不再重复计算;
当n=0或者m=0时,存储0并返回;(因为没有存在划分的整数或最大划分值为0)
当n=1或者m=1时,存储1并返回;(因为如果划分的整数或最大划分值是1,那么只有一种情况,要么只有一个1不用划分,要么就是用1来划分整数就是n个1只有一种情况)
当m>n时,存储split(n,n)并返回;(因为需要划分整数的最大正整数不能超过n)
当m==n时,只有n自身包含m,存储split(n,m-1)+1并返回;(如果两个值相等,那么就是把自身等于自身的情况去掉算一种+1)
当m<n时,分为分解包含m和不包含m两种情况,存储split(n,m-1)+split(n-m,m)并返回。(这个就是把从前面的递归是递归例子的(<m)下面的情况,后面的递归是递归上面的数量)

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std; 
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int a[125][125];
int dp(int n,int m){
 if (a[n][m] >0){
  return a[n][m];
 }
 else if(m==0||n==0){
  return a[n][m]=0;
 }
 else if(n==1||m==1){
  return a[n][m]=1;
 }
 else if(n==m){
  return a[n][m]=dp(n,m-1)+1;
 }
 else if(n<m){
  return a[n][m]=dp(n,n);
 }
 else if(n>m){
  return  a[n][m]=dp(n,m-1)+dp(n-m,m);
 }
}
int main(int argc, char** argv) {
 int n;
 while(cin>>n){
  memset(a,0,sizeof(a));
  cout<<dp(n,n)<<endl; 
 }
 return 0;
}

这种方法我就有个疑问为什么要加一个if (a[n][m] > 0){return a[n][m];}不加还过不去。我更倾向于第二种的数组解决的方法
先计算出所有子问题的解,然后查找即可。这种算法的AC代码如下:(其实我感觉这个跟上面的一样只是用数组代替了dp()更加简洁,比较容易想明白)

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std; 
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int a[125][125];
int main(int argc, char** argv) {
 int n;
 memset(a,0,sizeof(a));
 for(int i=0;i<=120;i++){
  a[0][i]=0;
  a[i][0]=0;
 }
 for(int j=1;j<=120;j++){
  a[1][j]=1;
  a[j][1]=1;
 }
 for(int i=2;i<=120;i++){
  for(int j=2;j<=120;j++){
   if(i==j){
    a[i][j]=a[i][j-1]+1;
   }
   else if(i<j){
    a[i][j]=a[i][i];
   }else {
    a[i][j]=a[i][j-1]+a[i-j][j];
   }
  }
 }
 while(cin>>n){
  cout<<a[n][n]<<endl; 
 }
 return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值