// 整数的拆分.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();
}
else
break;
}
}
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;
else
dp[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)
没想明白为什么分为盘子 都不空 和 有一个空 两种情况???