题目链接:

hdu:http://acm.hdu.edu.cn/showproblem.php?pid=5366

bestcoder:http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=613&pid=1003

C - The mook jong
Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u
Appoint description: 

Description

![](../../data/images/C613-1001-1.jpg) 

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;
}
View Code

相关文章: