经典 dp 数分解

经典dp

题意将数分解,输出分解的数量

//6 = 5 + 1
//6 = 4 + 2
//6 = 4 + 1 +1
//6 = 3 + 3
//6 = 3 + 2 +1
//6 = 2 + 2 + 2
//6 = 2 + 2 + 1 + 1
//6 = 2 + 1 + 1 + 1 + 1
//6 = 1 + 1 + 1 + 1 + 1 

发现6分解后的第一个数都比前一个数小,则定义dp[r][x]

dp[r][x]表示 x分解,第一数为r的情况 ,且r<x  (r=x为临界条件,存在dp[2][4]=dp[2][2],所以我们定义dp[r][r]=1)

dp[5][6]表示将6分解,一个分解数是5的情况

状态转移方程

dp[r][x] = £dp[k][x-r](1<=k<=r)
/*界限条件
dp[1][*]=1
dp[x][x]=1*/

时间复杂度 O(n^3)

空间复杂度O(n^2)

刚开始以为数据很大,用dp,后来仔细看了ppt,额>..<

//programming dp 数分解
//6 = 5 + 1
//6 = 4 + 2
//6 = 4 + 1 +1
//6 = 3 + 3
//6 = 3 + 2 +1
//6 = 2 + 2 + 2
//6 = 2 + 2 + 1 + 1
//6 = 2 + 1 + 1 + 1 + 1
//6 = 1 + 1 + 1 + 1 + 1 

/*界限条件
dp[1][*]=1
dp[x][x]=1*/
 
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>

using namespace std;
const int MAXN = 1e2+10;
int dp[MAXN][MAXN];

int main()
    for(int i=1;i<MAXN;i++){
        for(int j=1;j<MAXN;j++)
            if(i==j||i==1)    
                dp[i][j] = 1;
    }
    for(int i=2;i<MAXN;i++){
        for(int j=i+1;j<MAXN;j++){
            for(int k=1;k<=i;k++)
                dp[i][j]+= dp[k][j-i];
        }
    }
    int n,sum;
    while(cin>>n){
        sum = 0;
        for(int i=1;i<n;i++)
            sum+= dp[i][n];
        cout<<sum<<endl;
    }
    //cin>>i;
    return 0;
}
View Code
在一个谎言的国度,沉默就是英雄
原文地址:https://www.cnblogs.com/EdsonLin/p/5355409.html