整数的拆分问题

来源:互联网 发布:手机淘宝账号在哪里 编辑:程序博客网 时间:2024/05/17 21:51
// 整数的拆分.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <iostream>#include <vector>using namespace std;int q(int n , int m){if(n < 1 || m < 1)return 0;if(n == 1 || m == 1)return 1;if(n < m)return q(n , n);if(n == m)return q(n , m - 1) + 1;return q(n , m - 1) + q(n - m , m);}void dfs(int sum , vector<int>& vec , int curnum , int id){int i;if(curnum == sum){static int inum = 1 ;cout<<"方案 "<<inum++<<": ";for(i = 0; i < vec.size() ; ++i)cout<<vec[i]<<" ";cout<<endl;return;}for(i = id ; i <= sum; ++i){if(curnum + i <= sum){vec.push_back(i);dfs(sum , vec , curnum + i , i);vec.pop_back();}elsebreak;}}int main(void){int n,i,j,dp[121][121];for(i = 1 ; i < 121 ; ++i){for(j = 1 ; j < 121 ; ++j){if(i == 1 ||  j == 1)dp[i][j] = 1;else if(i > j)dp[i][j] = dp[i][j-1] + dp[i-j][j];else if(i == j)dp[i][j] = dp[i][j-1] + 1;elsedp[i][j] = dp[i][i];}}while(scanf("%d",&n)!=EOF){cout<<dp[n][n]<<endl;cout<<q(n,n)<<endl;vector<int> vec;dfs(n , vec , 0 , 1);cout<<endl;}system("pause");return 0;}
如,对于正整数n=6,可以拆分为:
6
5+1
4+2, 4+1+1
3+3, 3+2+1, 3+1+1+1
2+2+2, 2+2+1+1, 2+1+1+1+1
1+1+1+1+1+1+1
现在的问题是,对于给定的正整数n,程序输出该整数的拆分种类数(HDOJ  1028)。

DP思路:
n = n1 + n2 + n3 + n4 + .... + nk
状态表示:将n划分为k个数相加的组合方案数记为 q(n,k)。(相当于将n个苹果放入k个盘子)
状态转移:
(1)若k>n,则盘子数大于苹果数,至少有k-n个空盘子,可以将其拿掉,对组合方案数无影响。
q(n,k) = q(n,n)
(2)若k<=n,则盘子数小于等于苹果数,则分为两种情况
1.至少有一个盘子空着:q(n,k) = q(n,k-1)
2.所有盘子都不空:q(n,k) = q(n-k,k)

q(n,k) = q(n,k-1) + q(n-k,k)

没想明白为什么分为盘子 都不空 和 有一个空 两种情况???