• 【单峰计数DP】Problem F – Fabricating Sculptures


    【单峰计数DP】Problem F – Fabricating Sculptures

    image

    题意:

    你拥有m块正方体积木,在最底层铺上s块正方体积木,且在这个基础上,将其余m-s块积木铺好,且不能出现“凹”字的形状。

    求问有多少种拼法?

    设f[i,j]为最底层铺上i块,在其上方再铺j块的方案数。

    (f[i,j]=1 imes f[i,j-i] + 2 imes f[i-1,j-(i-1)] +3 imes f[i-2,j-(i-2)]+....+i imes f[1,j-1])

    前面的系数代表可以摆放的位置数目。

    单纯记忆化搜索的话,对于每一对i,j,也需要提取一大堆信息。

    不妨写下dp数组

    令i=1

    dp[1][0]=1

    dp[1][1]=1

    dp[1][2]=1

    dp[1][3]=1

    .......

    令i=2

    dp[2][0]=1

    dp[2][1]=2*dp[1][0]

    dp[2][2]=2*dp[1][1]+dp[2][0]

    dp[2][3]=2*dp[1][2]+dp[2][1]

    .......

    令i=3

    dp[3][0]=1

    dp[3][1]=3*dp[1][0]

    dp[3][2]=3*dp[1][1]+2*dp[2][0]

    dp[3][3]=3*dp[1][2]+2*dp[2][1]+dp[3][0]

    ....

    我们可以发现对于每一dp[i][j]dp[i][j-i](如果有的话)、各种方块数为j的模型的最右端放置到新开辟的第i块的方案数和放在前i-i块的方案数的三种类型之和。

    #include <bits/stdc++.h>
    #define MEM(a,x) memset(a,x,sizeof(a))
    #define W(a) while(a)
    #define gcd(a,b) __gcd(a,b)
    #define pi acos(-1.0)
    #define PII pair<int,int>
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define ll long long
    #define ull unsigned long long
    #define rep(i,x,n) for(int i=x;i<n;i++)
    #define repd(i,x,n) for(int i=x;i<=n;i++)
    #define MAX 1000005
    #define MOD 1000000007
    #define INF 0x3f3f3f3f
    #define lowbit(x) (x&-x)
    using namespace std;
    ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
    ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
    inline int read()
    {
        int x=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9')
        {
            if(ch=='-')
                f=-1;
            ch=getchar();
        }
        while(ch>='0' && ch<='9')
            x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    const int N = 5E3+100;
    int dp[N][N],sum[2*N],pre[2*N],n,m;
    int main()
    {
    	n=read(),m=read();
    	m-=n;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=0;j<=m;j++)
    		{
    			pre[j]=(pre[j]+sum[j])%MOD;
    			if(j==0) dp[i][0]=1;
    			else dp[i][j]=(dp[i][j]+pre[j])%MOD;
    			sum[i+j]=(sum[i+j]+dp[i][j])%MOD;
    		}
    	}
    	cout<<dp[n][m];
        return 0;
    }
    
    
  • 相关阅读:
    Java后端面试题大汇总,冲刺金三银四
    面试官:小伙子,Mybatis的本质和原理说一下
    面试官问:大量的 TIME_WAIT 状态 TCP 连接,对业务有什么影响?怎么处理?
    便捷搭建 Zookeeper 服务器的方法,好用,收藏~
    10 个冷门但又非常实用的 Docker 使用技巧
    mitmproxy 抓包工具(1)
    基于alpine创建Scrapy镜像
    强大的输入框-应用快速启动uTools
    Interceptor、Filter、Servlet的区别
    利用三层判断sql数据库中编码是否已经存在(个人拙作,不喜勿喷)
  • 原文地址:https://www.cnblogs.com/BeautifulWater/p/15477383.html
Copyright © 2020-2023  润新知