cf478d 线性dp好题

/*
给定r个红块,g个绿块,按要求堆放
问当堆放成最大高度时,有多少种可能的堆放方式 
排列要求:1.第i行放i块
          2.每行同色 

首先当然要确定能够放置几行
设红块有r个,绿块有g个,那么放置h行需要(h+1)h/2个
那么r+g>=(h+1)h/2 => 2(r+g)>=(h+1)h => 2(r+g)>h*h
那么有 h=sqrt(2r+2g),然后再找符合条件的h 

然后确定状态:dp[i][j]表示前i行用了j个红块的排列方案
转移方程:外层循环枚举i表示第i层,内层循环枚举j表示红块使用数 
    dp[i][j]=dp[i-1][j]+dp[i-1][j-i],即该行不用红块和用红块的两种决策 
决策合法性:当j<i时这层只能用绿块
            同时第i层红块至少用max(i(i+1)/2-g,0)个 
初始状态,dp=0,r>0,dp[1][1]=1,g>0,dp[1][0]=1 
用滚动数组优化 
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll ans,h,dp[200005],r,g;
#define mod 1000000007 
int main(){
    cin>>r>>g;
    h=sqrt(2*r+2*g);
    while(h*(h+1)/2>(r+g))h--; 
    if(r>0)dp[1]=1;
    if(g>0)dp[0]=1;
    for(int i=2;i<=h;i++){
        int l=max((ll)0,(i+1)*i/2-g);
        for(int j=r;j>=l;j--){
            if(j>=i)dp[j]=(dp[j]+dp[j-i])%mod;
            else dp[j]=dp[j];//只能用绿块 
        }
    }
    int l=max((ll)0,(h+1)*h/2-g);
    for(int i=r;i>=l;i--) 
        ans=(ans+dp[i])%mod;
    cout<<ans<<endl;
}

 

转载于:https://www.cnblogs.com/zsben991126/p/10475254.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值