HDU 5366 The mook jong

题目链接:

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
Submit  Status  Practice  HDU 5366
Appoint description:  System Crawler  (2016-03-25)

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

 方法二:

  数位dp。

  可以把题意理解为求满足下面两个条件的长度为n的01串总数

  条件1、不能全为0

  条件2、任意两个1之间必须有两个及以上的0相隔

  dp[i][0]表示第i位为0时长度为i的所有的合法串;

  dp[i][1]表示第i位为1时长度为i的所哟的合法串。

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 const int maxn = 66;
 7 typedef long long LL;
 8 
 9 LL dp[maxn][2];
10 
11 int n;
12 
13 void pre() {
14     memset(dp, 0, sizeof(dp));
15     dp[1][0] = dp[1][1] = 1;
16     for (int i = 2; i < maxn; i++) {
17         if (i > 3) dp[i][1] = dp[i - 3][0] + dp[i - 3][1];
18         //当i==2时只有01合法,当i==3时只有001合法。
19         else dp[i][1]=1;
20         dp[i][0] = dp[i - 1][0] + dp[i - 1][1];
21     }
22 }
23 
24 int main() {
25     pre();
26     while (scanf("%d", &n) == 1) {
27         printf("%lld\n", dp[n][0] + dp[n][1] - 1);
28     }
29     return 0;
30 }
View Code

 

你可能感兴趣的:(HDU 5366 The mook jong)