Little Sub and Piggybank (杭师大第十二届校赛G题) DP

Little Sub and Piggybank (杭师大第十二届校赛G题) DP题目传送门题意 每天能往存钱罐加任意实数的钱 每天不能多于起那一天放的钱数 如果某一天的钱数恰好等于那天的特价商品 则可以买 求最后的最大快乐值 思路 先来一段来自出题人的题解 显然的贪心 如果第 i 天买完 准备在第 j 天买 那么显然最优是在 i 1 到 j 天放 wi j i 的钱 于是假定选择的物品是 k1 k2 k3 那么必须满足 a ki

题目传送门

题意:每天能往存钱罐加任意实数的钱,每天不能多于起那一天放的钱数。如果某一天的钱数恰好等于那天的特价商品,则可以买,求最后的最大快乐值。

思路:先来一段来自出题人的题解:

  显然的贪心:如果第$i$天买完,准备在第$j$天买,那么显然最优是在$i+1$到j天放$wi/(j-i)$的钱。 于是假定选择的物品是$k1,k2,k3… $那么必须满足:

  $a[ki]/(ki-ki-1)<=a[ki-1]/(ki-1-ki-2)$

   令$f[i][j]$表示最后购买的两个物品为i和j,则$f[i][j]=max(f[j][k]+v[i])$ (j->k->i合法) 观察到上述条件可以把k分离,即$k>=j-(i-j)*a[j]/a[i]$,因此可以维护前缀和来使得时间复杂度变为$O(n2)$。

  这是来自zju的cjb学长的题解,接下来是我对这道题的一些理解。

  $f[i][j]$最后一次买的是第i个物品,前一次是第j个物品的最大收益,那么我们就有$f[i][j]=max(f[j][k]+v[i])$并且i,j,k要合法,合法的条件就是$a[i]/(i-j)<=a[j]/(j-k)$,那么我们把这个式子移一下项,就得到了合法条件是$k>=j-(i-j)*a[j]/a[i]$,然后我们用$g[j][k]$表示,以k为起点,所有买了j物品的最大的f[j][k],即$g[j][k]=max(f[j][k])$,然后同时维护$f$和$g$两个结构就可以了。

Little Sub and Piggybank (杭师大第十二届校赛G题) DP Little Sub and Piggybank (杭师大第十二届校赛G题) DP

#include
      
    
      
      
      
      
      

       
     
       
       
       
       
       #define clr(a,b) memset(a,b,sizeof(a))
       
     
       
       
       
       
        typedef 
       
     
       
       
       
       
       long 
       
     
       
       
       
       
       long
       
     
       
       
       
       
        ll; 
       
     
       
       
       
       
       using 
       
     
       
       
       
       
       namespace
       
     
       
       
       
       
        std; 
       
     
       
       
       
       
       const 
       
     
       
       
       
       
       int maxn=
       
     
       
       
       
       
       2010
       
     
       
       
       
       
       ; 
       
     
       
       
       
       
       int
       
     
       
       
       
       
        n,f[maxn][maxn],g[maxn][maxn],ans,a[maxn],v[maxn],k; 
       
     
       
       
       
       
       int
       
     
       
       
       
       
        main(){ 
       
     
       
       
       
       
       while(cin>>
       
     
       
       
       
       
       n) { 
       
     
       
       
       
       
       for(
       
     
       
       
       
       
       int i=
       
     
       
       
       
       
       1;i<=n;i++
       
     
       
       
       
       
       ) { cin>>
       
     
       
       
       
       
       a[i]; } 
       
     
       
       
       
       
       for(
       
     
       
       
       
       
       int i=
       
     
       
       
       
       
       1;i<=n;i++
       
     
       
       
       
       
       ) { cin>>
       
     
       
       
       
       
       v[i]; } clr(f,
       
     
       
       
       
       
       0),clr(g,
       
     
       
       
       
       
       0
       
     
       
       
       
       
       ); 
       
     
       
       
       
       
       for(
       
     
       
       
       
       
       int i=
       
     
       
       
       
       
       1;i<=n;i++
       
     
       
       
       
       
       ) { f[i][
       
     
       
       
       
       
       0]=
       
     
       
       
       
       
       v[i]; 
       
     
       
       
       
       
       for(
       
     
       
       
       
       
       int j=
       
     
       
       
       
       
       1;j
       
     
       
       
       
       
       
         ) { 
        if(!a[i])k= 
        0 
        ;  
        else k=max(ceil(j- 
        1.0*a[j]/a[i]*(i-j)), 
        0.0 
        );  
        if(j>=k&& 
        g[j][k]) f[i][j]=max(f[i][j],g[j][k]+ 
        v[i]); }  
        for( 
        int j=i- 
        1;j>= 
        0;j-- 
        ) { g[i][j]=max(g[i][j+ 
        1 
        ],f[i][j]); } } ans= 
        0 
        ; rep(i, 
        1,n)ans=max(ans,g[i][ 
        0 
        ]); printf( 
        " 
        %d\n 
        " 
        ,ans); }  
        return 
        0 
        ; } 
       
      
    
      
      
      
      
      

View Code

 

转载于:https://www.cnblogs.com/mountaink/p/10561532.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/211478.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 下午10:20
下一篇 2026年3月18日 下午10:20


相关推荐

  • mavlink无人机控制程序_无人机协同作战

    mavlink无人机控制程序_无人机协同作战1.MAVLink简介MAVLink(MicroAirVehicleLink,微型空中飞行器链路通讯协议)是无人飞行器与地面站(GroundControlStation,GCS)之间通讯,以及无人飞行器之间通讯最常用的协议。它已经在PX4、APM、PIXHAWK和ParrotAR.Drone飞控平台上进行了大量测试。2.发明者LorenzMeier简介MAVLink的…

    2022年8月15日
    12
  • oracle查询一定行数,oracle查看所有表及各表行数

    oracle查询一定行数,oracle查看所有表及各表行数在 Oracle 数据库中 查看所有表及对应个表的行数 只用一个 select 语句查询 table name 和 num rows 两个字段即可 table name 是表名 num rows 代表表的行数 具体如下 1 查询数据库所有的表 sql selectt table name t num rowsfromall tablest sql 执行后的输出结果如下图 2 查询当前用户表 sql selectt

    2026年3月17日
    2
  • mac系统安装win10双系统「建议收藏」

    mac系统安装win10双系统「建议收藏」一个月前,为了在家里学习单片机,在macbookair系统基础上,安装了win10,搞了一个双系统。在安装之前,看了很多资料,基本上提到两点,一个是准备win10镜像,一个是准备win10安装启动程序,而且至少需要一个U盘,有的也说需要两个,一个用来装win10镜像,一个用来装win10启动程序。最后动手安装的时候,一个U盘也没有使用,直接把win10镜像下载到mac系统中,然后启动mac上的磁盘管理工具,按照提示,傻瓜式的进行下一步。有两个地方需要我们手动设…

    2026年4月15日
    8
  • MYSQL IFNULL使用功能

    MYSQL IFNULL使用功能

    2022年1月2日
    80
  • 爆火的Manus、ChatGPT Agent,竟藏着198个信息“黑洞”?

    爆火的Manus、ChatGPT Agent,竟藏着198个信息“黑洞”?

    2026年3月16日
    2
  • Python在线编程环境

    Python在线编程环境除了安装Python的IDE之外,也可以使用在网页中随时随地编写Python程序。Python官网:https://www.python.org/shellPython123:https://py

    2022年7月5日
    32

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号