经典 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; }
在一个谎言的国度,沉默就是英雄