• diagrams(哈尔滨工程大学ACM预热赛 A)(高精度 dp)


    链接:https://ac.nowcoder.com/acm/contest/554/A
    来源:牛客网
     

    时间限制:C/C++ 1秒,其他语言2秒
    空间限制:C/C++ 32768K,其他语言65536K
    64bit IO Format: %lld

    题目描述

    小虎刚刚上了幼儿园,老师让他做一个家庭作业:首先画3个格子,第二行有2个格子,第三行有1个格子。每行的格子从左到右可以放棋子,但要求除第一行外,每行放的棋子数不能超过上一行的棋子。玩了一会儿,小虎问大哥大虎:这个作业有很多种摆放法,我想都找到,但我不知道有多少中方案,你能帮助我么?
    大虎是学校信息学集训队的,立刻想到用计算机来解决这个问题,并很快有了解答:13。第二天他把问题拿到了学校,并说如果第一行有N个格子,第二行有N-1个格子,…,第N行有1个格子,怎么办?现在请你一块来帮助他解决这个难题。
    数据范围
    30%数据:1≤N≤12
    50%数据:1≤N≤30
    100%数据:1≤N≤100

    输入描述:

    仅一行,一个正整数N。

    输出描述:

    一行,方案总数。

    示例1

    输入

    复制

    2

    输出

    复制

    4

    说明

    样例1说明N=2时,有如下4中摆放棋子法(*表示棋子,_表示空格):
    方案法    1    2    3    4
    摆放法    *_    **    *_    **
    摆放法    _    _    *    *

    示例2

    输入

    复制

    3

    输出

    复制

    13

    简单好想的dp

    唯一的坑点就是需要用大数

    这里我使用了递归的dp算法 直接把返回值设置为大数类型

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    long long ans=0;
    struct bigintiger
    {
        int num[100];
        int digit;
        int flag;
    }unit;
    bigintiger add(bigintiger a,bigintiger b)
    {
        bigintiger tmp;
        memset(tmp.num,0,sizeof(tmp.num));
        tmp.digit=max(a.digit,b.digit);
        for(int i=1;i<=tmp.digit;i++)
        {
            tmp.num[i]=a.num[i]+b.num[i];
        }
        for(int i=1;i<=tmp.digit;i++)
        {
            if(tmp.num[i]>=10)
            {
                tmp.num[i+1]++;
                tmp.num[i]%=10;
            }
        }
        if(tmp.num[tmp.digit+1]!=0)
        {
            tmp.digit++;
        }
        tmp.flag=1;
        return tmp;
    }
    bigintiger dp[105][105];//使用101记录数位
    void print(bigintiger x)
    {
        for(int i=x.digit;i>=1;i--)
            printf("%d",x.num[i]);
        cout<<endl;
    }
    int n;
    bigintiger dfs(int x,int lim)
    {
        //printf("%d %d
    ",x,lim);
        bigintiger ans;
        memset(ans.num,0,sizeof(ans.num));
        ans.flag=0;
        ans.digit=0;
        if(x!=n&&(lim==0||x==0)) {return unit;}
        else if(x==n&&(lim==0||x==0)) {return ans;};
        if(dp[x][lim].flag!=0) return dp[x][lim];
        for(int i=min(x-1,lim);i>=0;i--)
        {
            ans=add(ans,dfs(x-1,i));
        }
        dp[x][lim]=ans;
        //printf("x=%d lim=%d
    ",x,lim);
        //print(dp[x][lim]);
        return ans;
    }
    int main()
    {
        memset(unit.num,0,sizeof(unit.num));
        unit.flag=1;
        unit.digit=1;
        unit.num[1]=1;
        scanf("%d",&n);
        dfs(n+1,n);
        print(dp[n+1][n]);
    }
    
  • 相关阅读:
    下面我使用vector容器为基础来构成一棵树
    COM编程
    vc买书指导
    [转帖] 职场学习=贼学技术
    创业者应具备的基本商业知识
    比尔盖茨的10大优秀员工准则(看你符合几条)
    损害个人魅力的26条错(转帖)
    流行:时尚健康美女10大标准
    人生要做的30件事(转帖)
    最伟大的管理原则
  • 原文地址:https://www.cnblogs.com/caowenbo/p/11852293.html
Copyright © 2020-2023  润新知