ACM: HDU 1028 Ignatius and the Princess III-DP

 HDU 1028 Ignatius and the Princess III
Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u

Description

"Well, it seems the first problem is too easy. I will let you know how foolish you are later." feng5166 says. 

"The second problem is, given an positive integer N, we define an equation like this: 
  N=a[1]+a[2]+a[3]+...+a[m]; 
  a[i]>0,1<=m<=N; 
My question is how many different equations you can find for a given N. 
For example, assume N is 4, we can find: 
  4 = 4; 
  4 = 3 + 1; 
  4 = 2 + 2; 
  4 = 2 + 1 + 1; 
  4 = 1 + 1 + 1 + 1; 
so the result is 5 when N is 4. Note that "4 = 3 + 1" and "4 = 1 + 3" is the same in this problem. Now, you do it!" 

Insilput

The input contains several test cases. Each test case contains a positive integer N(1<=N<=120) which is mentioned above. The input is terminated by the end of file. 

Output

For each test case, you have to output a line contains an integer P which indicate the different equations you have found. 

Sample Input

4
10
20

Sample Output5

42
627

/*/
思路有点像模拟,先从小的开始排序,用样例1来说

4的位置可以只放1 {1,1,1,1};①

4的位置也可以放一个2 {2,1,1};这时候剩下2个位置,这状态可以做为一个往2个位置里面再去放东西来看

    2的位置可以只放1 {1,1};  对应的4个位置为 {2,1,1};②

    2的位置也可以放一个2 {2}; 对应的4个位置为 {2,2};③

4的位置可以放一个3 {3,1}; ④

4的位置可以只放一个4 {4}; ⑤

这就是整个过程.【现在放图】



实现过程:

对于这个过程,如果一开始就是前面往后面去推的话,很容意发现,前面的插小空的状态是可以保存的,用dp保存每一个从x个填满y长度的方法个数。 如果y==x,那就说明已经填满了,最大的填放方法已经放完了。 又因为如果y>x的话,不可能放下去,就直接复制前面的种类次数就是的了,也就是:dp[x][y]=dp[x][x];//不可能往小位置里塞入大的数 直接结果就是dp[n][n]; AC代码: /
*/
#include"map"
#include"cmath"
#include"string"
#include"cstdio"
#include"vector"
#include"cstring"
#include"iostream"
#include"algorithm"
using namespace std;
typedef long long LL;
const int MX=202;
#define memset(x,y) memset(x,y,sizeof(x))
#define FK(x) cout<<"【"<<x<<"】"<<endl
int n,dp[MX][MX];

int main() {
	memset(dp,0);
	for(int i=1; i<MX; i++) { //把x,y=1的情况都标出来,为1。
		dp[i][1]=dp[1][i]=1;
	}
	for(int x=2; x<MX; x++) {
		for(int y=2; y<MX; y++) {
			if(x<y) dp[x][y]=dp[x][x];//不可能往小位置里塞入大的数
			if(x==y)dp[x][y]=dp[x][y-1]+1;    //加上放入最大的数的一次。
			if(x>y) dp[x][y]=dp[x][y-1]+dp[x-y][y];/* dp[x-y][y] 往x-y大小里面插入y的可能的次数*/
		}/* dp[x][y-1] 前面的次数*/
	}
	while(~scanf("%d",&n))
		printf("%d
",dp[n][n]);
	return 0;
}

  

原文地址:https://www.cnblogs.com/HDMaxfun/p/5731519.html