zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    3. docker-compose实战--ghost app
    3. nacos服务发现
    1. nacos初识, 和eureka的比较, 在docker上安装nacos
    2.nacos服务配置中心
    如何将PHP对象数组转换成普通数组
    php 通过变量 来调用函数
    linux svn
    Sublime text 3安装svn插件
    php 字符串 定界符 json_last_error()
    centos7 rm -rf 删除文件的找回
  • 原文地址:https://www.cnblogs.com/zsben991126/p/10475254.html
Copyright © 2011-2022 走看看