• 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
    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
    ", ans[n]);
        }
        return 0;
    }
    View Code

     方法二:

      可以把题意理解为求满足下面两个条件的长度为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
    ", dp[n][0] + dp[n][1] - 1);
    28     }
    29     return 0;
    30 }
    View Code
  • 相关阅读:
    PHP 面试踩过的坑(三)
    明天准备离职了,面对照顾自己的领导,要这样说
    别怕!MySQL引起的CPU消耗过大,我有办法
    值得收藏:一份非常完整的 MySQL 规范(一)
    emacs 快捷键设置 基础知识篇
    Ruby快速入门(三):控制语句
    Ruby快速入门(一):安装、运行、类和对象
    Ruby快速入门(二):变量、数字、数组和运算符
    Ruby快速入门(四):类和模块
    emacs安装autocomplete插件
  • 原文地址:https://www.cnblogs.com/fenice/p/5321679.html
Copyright © 2020-2023  润新知