题目链接:
hdu:http://acm.hdu.edu.cn/showproblem.php?pid=5366
bestcoder:http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=613&pid=1003
Appoint description:
Description

ZJiaQ want to become a strong man, so he decided to play the mook jong。ZJiaQ want to put some mook jongs in his backyard. His backyard consist of n bricks that is 1*1,so it is 1*n。ZJiaQ want to put a mook jong in a brick. because of the hands of the mook jong, the distance of two mook jongs should be equal or more than 2 bricks. Now ZJiaQ want to know how many ways can ZJiaQ put mook jongs legally(at least one mook jong).
ZJiaQ want to become a strong man, so he decided to play the mook jong。ZJiaQ want to put some mook jongs in his backyard. His backyard consist of n bricks that is 1*1,so it is 1*n。ZJiaQ want to put a mook jong in a brick. because of the hands of the mook jong, the distance of two mook jongs should be equal or more than 2 bricks. Now ZJiaQ want to know how many ways can ZJiaQ put mook jongs legally(at least one mook jong).
Input
There ar multiply cases. For each case, there is a single integer n( 1 < = n < = 60)
Output
Print the ways in a single line for each case.
Sample Input
1
2
3
4
5
6
Sample Output
1
2
3
5
8
12
题解:
方法一:
区间dp。
dp[i][j]表示前i个地砖放j个木人桩(其中第i个地砖肯定有放东西,要不然就不会是dp[i][j],而是dp[k][j](k<i) )
则易得转移方程 dp[i][j]=sum(dp[k][j-1]),其中k<i-2;
初始化要注意:dp[i][1]=1,而其他则都清零。
代码:
#include<iostream> #include<cstdio> using namespace std; const int maxn = 66; typedef long long LL; int n; LL dp[maxn][maxn],ans[maxn]; void pre() { memset(dp, 0, sizeof(dp)); for (int i = 1; i < maxn; i++) dp[i][1] = 1; for (int i = 2; i < maxn; i++) { for (int j = 2; j < i; j++) { for (int k = i - 3; k >= j-1; k--) { dp[i][j] += dp[k][j - 1]; } } } memset(ans, 0, sizeof(ans)); for (int i = 1; i <maxn; i++) { for (int j = 1; j <= i; j++) { ans[i] += dp[i][j]; } } for (int i = 2; i < maxn; i++) ans[i] += ans[i - 1]; } int main() { pre(); while (scanf("%d", &n) == 1) { printf("%lld\n", ans[n]); } return 0; }