ural1017
2014-09-04 12:36
211 查看
题意
这道题目要求计算给定数目的砖块可以组成多少种不同的楼梯。楼梯由不同高度的阶梯组成,不允许有两个阶梯有相同的高度。每个楼梯至少包含两个阶梯,每个阶梯至少包含一个砖块。Input
Number NOutput
Number QSample
input | output |
---|---|
212 | 995645335 |
[i]表示n各block 最后一列的长度为i的个数
但是状态转移方程不会。。。。。。囧。。。
后来听了大神的解释只关心最后一列的长度 后面的和前面的没有关系
就像 1 2 5
2 3 5
1 4 5
我们只关心最后一列。但状态转移方程还是不会。。。囧 o(╯□╰)o
但是从这组数中发现了一个问题 ,这个序列是单调递增的,而且和是n.那么我们可以想办法把n拆成多个序列,递增的序列,而且不允许数相等
这就转化成了数的划分问题。查找了资料,真的阔以酱紫做。
参考了一位大神的博客 http://www.cnblogs.com/skyivben/archive/2009/03/02/1401728.html
其实这个讲解的过程也是忽略了很多东西的,因为当人们真的了解了一个问题之后,思维转换的速度非常快,因此懂得的人觉得讲得很清楚了 ,但是听的人还是很不懂。因为懂得人不懂得不懂的人哪里不懂,不懂的人不知道懂的人哪里懂。噗噗噗。。有点像绕口令了。。。跑远了。。首先,我不了解为什么要那么d[k]
表示最小划分元素》=k的个数,可能是因为我没有看原著的原因,这里我就先酱紫忍了。
d[k]
表示最小换分元素的值>=k的划分个数 设最小的是m吧
当m>k时,d[k]
=d[k+1]
当m=k的时候 d[k]
=d[k+1][n-k]就是将所有序列加上k就得到了n-k+k,并且此时的k1>k
d[k]
=0 if(k>n)
d[k]
=1 if(k==n)
d[k]
=d[k+1]
+d[k+1][n-k] else
所以代码就阔以辣,另外有幸的是在上面博客里还有对dp方法的很好的解释。所以用dp的话就是
d
[i]表示n各block有i个台阶(也可以说是有i行)的个数。
首先第一行最少i个,那么第二层i个或者i-1
//还以为可以二项式解决 但好像不能 因为有限制条件 // #include<cstdio> #include<cstring> #include<iostream> using namespace std; long long d[555][555];//d [i]表示n方块中最后一行的是 i .可是状态转移还是不太清楚 long long v[555]; long long fun(int n,int k) //计算C(n,k) http://jarg.iteye.com/blog/859391 { long long v[505]; for(int i=0;i<=n;i++) { v[i]=1; for(int j=i-1;j>0;j--) v[i]=v[j]+v[j-1]; } return v[k]; } int main() { int n,i,j; long long res=0; scanf("%d",&n); /* memset(d,0,sizeof(d)); d[1][1]=1; for(i=2;i<=n;i++) { for(j=1;j*(j+1)/2<=i;j++) { // if(j==1 || j==i) d[i][j]=1; d[i][j]=d[i-j][j-1]+d[i-j][j];//这个过程不知道啊。。。。 } } for(j=1;j*(j+1)/2<=n;j++)res+=d [j]; cout<<res-1<<endl;//因为加了d[1][1]所以要减去 */ /*正确分析: f(n, k)=f(n-k, k)+f(n-k, k-1) 其中n表示砖块的数目,k表示台阶的数目。f(n, k)表示n块砖搭成k阶的方法个数。 那么最下层肯定有k块砖,除去最下层的k块砖,有两种情况,即k-1阶或者k阶。所以可以得到该递推式。 同样可以使用动态规划求解,最终,要求的总方法数为Σf(n, k),其中k=2,…,n。 */ /* memset(v,0,sizeof(v)); v[2]=1; v[3]=3; for(i=4;i<=n;i++) v[i]=v[i-1]+i-2; cout<<v <<endl; //错的 看来找规律要慎重啊。。。 /* 1 0 2 1 3 3 4 5 5 8 6 12 7 17 8 23 */ //最后一种解法 数的划分 http://www.cnblogs.com/skyivben/archive/2009/03/02/1401728.html //d[k] 表示将n划分的最小元素是k // =k时 d[][]=d[k][n-k] // >k 时 d[][]=d[k+1] memset(d,0,sizeof(d)); for(i=1;i<=n;i++)d[i][i]=1; for(i=2;i<=n;i++) { for(j=i-1;j>=1;j--) d[j][i]=d[j+1][i]+d[j+1][i-j]; } cout<<d[1] -1<<endl; }
经历了种种苦难,觉得dp的状态方程还真是不好推啊。。。。
相关文章推荐
- ural1017 Staircases (动态规划)
- URAL 1017 Staircases
- ural 1017 Staircases
- Ural 1017
- 面相对象的topSort和递推【ural1022/ural1017】
- ural 1017. The Staircases
- ural 1017
- Ural 1017 楼梯问题/整数拆分(01背包/dp/母函数)
- ural 1017. Staircases(dp)
- Ural 1017 The Staircases
- URAL 1017 Staircases dp练习
- Ural 1017
- ural 1017. Staircases DP
- URAL 1017 Staircases 记忆化搜索
- ural 1017. Staircases(dp)
- Ural_1017. Staircases(DP)
- URAL 1017|Staircases|动态规划
- ural 1017. Staircases
- URAL 1017. Staircases
- ural 1017 Staircases