整数划分问题(动态规划)

题目描述:给你一个整数n,比如是4,输出可以将4划分的总数目。

可以划分为

4

3 1

2 2     2 1 1 

1 1 1 1 

这样总共有五种情况。


书上写的是递归实现的方法,很耗费时间,输入100之后还需要5s+的样子才能运行出来。


可以直接使用动态规划。 a[n][m]表示总和为n,其中最大的数字是m的总类数。我们所需要求得答案便是a[n][n].


(1)a[n][n]=a[n][n-1]+1

(2)a[n][m]=a[n][m-1]+a[n-m][m]  (m<n&&n-m>=m)    n-m是因为要使得这一行最大数字必须为m

(3)a[n][m]=a[n][m-1]+a[n-m][n-m]  (m<n&&n-m<m)



代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long a[1002][1002];

int fun(int n,int m)   //递归实现太耗费时间
{
    if(n<1||m<1) return 0;
    else if(n==1||m==1) return 1;
    else if(n<m) return fun(n,n);
    else if(n==m) return 1+fun(n,n-1);
    else return fun(n,m-1)+fun(n-m,m);
}

int main()
{
    int n,i,j;
    memset(a,0,sizeof(a));
    for(i=1;i<=1000;i++)
        a[i][1]=a[1][i]=1;
    for(i=2;i<=1000;i++)
    {
        for(j=2;j<i;j++)
        {
            if(i-j>=j) a[i][j]=a[i][j-1]+a[i-j][j];
            else a[i][j]=a[i][j-1]+a[i-j][i-j];
        }
        a[i][i]=a[i][i-1]+1;
    }

    while(cin>>n)
    {
        //cout<<fun(n,n)<<endl;
        cout<<a[n][n]<<endl;
    }
    return 0;
}



你可能感兴趣的:(思维)