您的位置:首页 > 大数据 > 人工智能

ural 1017. Staircases(dp数的划分)

2014-10-20 10:53 281 查看
题意:

n块砖块,按照从小到大的顺序(可以不连续)排成一堆堆,计算有多少种排列方法

分析:(待补。。。)

     dp[k]
表示将数n划分成若干个不相等的数,并且划分的数都大于等于k,

由推导可知:

划分成最小大于k的:

    dp[k+1]

划分成最小等于k的:

    dp[k+1][n-k]

所以状态转移方程:dp[i][j]=dp[i+1][j]+dp[i+1][j-i];

注意!最后结果是dp[1]
表示将n划分成若干不等且大于等于1的

但是题目要求阶梯大于等于2个,所以最后要减去只有一个阶梯的情况

就是n划分成一块:n划分为n所以减一

    ans=dp[1]
-1;

/*******************************************************************************************************************/

转自:http://www.cnblogs.com/skyivben/archive/2009/03/02/1401728.html

数学背景

这道题目涉及到数的分划,属于组合数学数论的研究领域。

1、数 n 的分划(partition)是将 n 表示成任意多个正整数之和的形式。例如,数 5 的分划如下:

5
4 + 1
3 + 2
3 + 1 + 1
2 + 2 + 1
2 + 1 + 1 + 1
1 + 1 + 1 + 1 + 1
用 p(n) 来记 n 的分划的个数,这样就有 p(5) = 7。

为了求解 p(n),我们引入一个中间函数 p(k, n),表示数 n 的最小被加数不小于 k 的分划的个数。对于给定的 k 值,p(k, n) 正好分为以下两类:

最小被加数等于 k

最小被加数大于 k
满足第一个条件的分划的个数是 p(k, n − k)。 这是因为,让我们想象数
n − k 的最小被加数不小于 k 的分划,然后将 "+ k" 附加每一个分划后面,就得到数 n 的最小被加数等于 k 的分划。以 n = 5, k = 1 为例,数 4 的最小被加数不小于 1 的分划是43 + 12 + 22 + 1 + 11 + 1 + 1 + 1,即
p(k, n − k) =p(1, 4) = 5。然后,将 "+ 1"
附加在这 5 个分划后面,就得到数 5 的最小被加数等于 1 的分划:4 + 13 + 1 + 12 + 2 + 12 + 1 + 1 + 11 + 1 + 1 + 1 + 1

满足第二个条件的分划的个数是 p(k + 1, n) 。以 n = 5, k = 1 为例,数 5 的最小被加数大于 1 的分划是5
3 + 2,即 p(k + 1, n) =p(2, 5) = 2。

也就是说,p(1, 5) = p(2, 5) + p(1, 4)。因此:

p(k, n) = 0  如果 k > n
p(k, n) = 1  如果 k = n
p(k, n) = p(k+1, n) +
p(k, n-k)  其它情况
这样,就可以递归地求解 p(k, n),其部分值见下表:

 k
12345678910
n11000000000
22100000000
33110000000
45211000000
57211100000
611421110000
715421111000
822732111100
930842111110
10421253211111
最后,p(n) = p(1, n)

 

2、现在,让我们的来考虑 将 n 分成不相等的正整数之和的分划。例如,数 8 的分划如下:

8
7 + 1
6 + 2
5 + 3
5 + 2 + 1
4 + 3 + 1
用 q(n) 来记 n 的分划的个数,这样就有 q(8) = 6。

为了求解 q(n),我们引入一个中间函数 q(k, n),表示数 n 的最小被加数不小于 k 的分划的个数。对于给定的 k 值,q(k, n) 正好分为以下两类:

最小被加数等于 k

最小被加数大于 k
满足第一个条件的分划的个数是 q(k + 1, n − k)。 这是因为,让我们想象数n −
k 的最小被加数大于 k 的分划,然后将 "+ k" 附加每一个分划后面,就得到数 n 的最小被加数等于 k 的分划。以 n = 8, k = 1 为例,数 7 的最小被加数大于 1 的分划是75 + 2
4 + 3,即 q(k + 1,n − k) = q(2, 7) = 3。然后,将 "+ 1"
附加在这 3 个分划后面,就得到数 8 的最小被加数等于 1 的分划:7 + 15 + 2 + 14 + 3 + 1

满足第二个条件的分划的个数是 q(k + 1, n) 。以 n = 8, k = 1 为例,数 8 的最小被加数大于 1 的分划是86 + 2
5 + 3,即 q(k + 1,n) = q(2, 8) = 3。

也就是说,q(1, 8) = q(2, 8) + q(2, 7)。因此:

q(k, n) = 0  如果 k > n
q(k, n) = 1  如果 k = n
q(k, n) = q(k+1, n) +
q(k + 1, n-k)  其它情况
这样,就可以递归地求解 q(k, n),其部分值见下表:

 

 k
12345678910
n11000000000
21100000000
32110000000
42111000000
53211100000
64211110000
75321111000
86321111100
98532111110
1010532111111
 

最后,q(n) = q(1, n)

 

 

#include  <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;

ll dp[1003][1003];

int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
dp[i][i]=1;
for(int i=n-1;i>=1;i--)
{
for(int j=i+1;j<=n;j++)
dp[i][j]=dp[i+1][j]+dp[i+1][j-i];
}
printf("%I64d\n",dp[1]
-1);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: