您的位置:首页 > 其它

Ural 1017

2010-11-22 21:05 330 查看
题意:N个砖块按照严格递增到顺序建造楼梯,且楼梯阶数至少为2,求有多少种方法

WA:根本就想不到状态转移方程。。。

方法:这是我们戒dota生涯的第一个题目,也彻底证明了咱到DP水平是何其之低。。。刚刚拿过来到时候没有任何思路,如果只是记录i个方块对应的方法数的话,是无法由i-1推至i的,因为这样无法限定条件。后来学习了大牛们到思想,才AC了。。

最朴素的思路是n^3的,令f[i][j]表示i个砖块高度为j可形成到方法数,则可以知道 f[i][j] = Σf[i-j][k] 其中(0 <= j <=i, 0 <= k < j )

代码: 注意都要用longl long 最后的 ans忘了long long 在第六组WA了

#include <iostream>
#include <cstring>
using namespace std;
#define MAX 505
long long f[MAX][MAX];
int main() {
int n;
while (cin >> n) {
for(int i = 0; i <MAX; i++)
memset(f[i],0,sizeof(f[i]));
f[0][0] = 1;
for(int i = 1; i <= n; i++)
{
for(int j = 0; j <= i; j++)
{
for(int k = 0; k < j;k++)
f[i][j] += f[i-j][k];
}
}
long long ans = 0;
for(int j = 0; j < n; j++)
ans += f
[j];
cout << ans << endl;
}
}


然后发现大牛们有一种n^2的算法,关键在于f[[i][j] 表示到是i个砖块最大高度为j的方法数,这样状态转移方程即是

f[i][j] = f[i][j-1] + f[i-j][j-1] 边界为f[0][0] 为1,其余为0,可参见http://blog.csdn.net/zxddavy/archive/2010/11/22/6027883.aspx

注意不用滚动数组到时候要考虑 当 i < j到时候 方程就变了,是 f[i][j] = f[i][j-1] (i < j)

观察这个方程可知,j只与j-1有关,于是我们可以用滚动数组,但是j作为列就不好滚动了,很简单,把i和j交换即可,这样不仅省了空间,而且省去了i < j的那个方程到复制时间

代码:

#include <iostream>
#include <cstring>
using namespace std;
#define MAX 505
long long f[MAX];
int main() {
int n;
while (cin >> n) {
memset(f,0,sizeof(f));
f[0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = n; j >= i; j--) {
f[j] = f[j] + f[j - i];
}
}
cout << f
- 1 << endl;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: