ABCD

题目背景

SOURCE:NOIP2016-AHSDFZ T2

题目描述

有 4 个长度为 N 的数组 a,b,c,d 。现在需要你选择 N 个数构成数组e ,数组e 满足 a[i]≤e[i]≤b[i] 以及

这里写图片描述
并且使得

这里写图片描述
最大。

输入格式

输入文件共 N+1 行。

第 1 行包含 1 个正整数 N 。

第 i+1 行包含 4 个整数 a[i],b[i],c[i],d[i] 。

输出格式

输出共 1 行,包含 1 个整数,表示所给出公式的最大值。输入数据保证一定有解。

样例数据 1

输入

5

-1 1 2 5

-2 2 1 2

0 1 1 3

-2 -1 3 10

-2 2 3 9

输出

2

样例数据 2

输入

10

1 10 1 7

-10 10 2 0

-10 10 2 2

-10 10 2 0

1 10 1 0

-10 10 2 0

10 10 2 0

1 10 1 0

-10 10 2 0

1 10 1 0

输出

90

样例数据 3

输入

10

1 10 1 0

-10 10 2 2

-10 10 2 2

-10 10 2 2

1 10 1 0

-10 10 2 2

-10 10 2 2

1 10 1 0

-10 10 2 2

1 10 1 0

输出

-4

备注

【数据规模与约定】

对于 20% 的数据,N≤10;-2≤a[i]< b[i]≤2;

对于 60% 的数据,N≤50;-20≤a[i]< b[i]≤20;

对于 100% 的数据,N≤200;-25≤a[i]< b[i]≤25;1≤c[i]≤20;0≤d[i] ≤100000。

好吧我承认这道题我又zz" role="presentation" style="position: relative;">zzzz了,考试时竟然爆0" role="presentation" style="position: relative;">00,唉下来之后发现就是个简单dp" role="presentation" style="position: relative;">dpdp。

我们对原来的限制条件变形,让0≤num[i]≤a[i]−b[i]" role="presentation" style="position: relative;">0≤num[i]≤a[i]−b[i]0≤num[i]≤a[i]−b[i],然后令num[i]=e[i]−a[i]" role="presentation" style="position: relative;">num[i]=e[i]−a[i]num[i]=e[i]−a[i],代入原来的式子运算,会发现这是一道背包。b[i]−a[i]" role="presentation" style="position: relative;">b[i]−a[i]b[i]−a[i]是物品的数量限制,num[i]" role="presentation" style="position: relative;">num[i]num[i]是物品i" role="presentation" style="position: relative;">ii的选取数量限制,c[i]" role="presentation" style="position: relative;">c[i]c[i]则是物品的大小,然后就是背包了。

然而我们发现,这样子只有60" role="presentation" style="position: relative;">6060分。因此需要用一个叫做单调队列的东西进行优化。代码如下:

#include<bits/stdc++.h>
#define N 210
#define M 100010
using namespace std;
int n,m,a[N],b[N],c[N],d[N],dp[M],ans,q[M],f[M],head,tail;
int main(){
    scanf("%d",&n),ans=m=0;
    for(int i=1;i<=n;++i){
        scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
        b[i]-=a[i];
        m-=a[i]*c[i];
        ans+=a[i]*d[i];
    }
    memset(dp,128,sizeof(dp));
    dp[0]=0;
    for(int i=1;i<=n;++i)
        for(int j=0;j<c[i];++j){
            head=1,tail=0;
            for(int k=j;k<=m;k+=c[i]){
                if(head<=tail&&k-q[head]==(b[i]+1)*c[i])++head;
                while(head<=tail&&f[tail]+(k-q[tail])/c[i]*d[i]<=dp[k])--tail;
                q[++tail]=k,f[tail]=dp[k];
                dp[k]=f[head]+(k-q[head])/c[i]*d[i];
            }

        }
    printf("%d",ans+dp[m]);
    return 0;
}

最新文章

  1. [.net core]简介(转)
  2. 逻辑运算符&amp;&amp;和&amp;的区别 ||和|的区别
  3. c#如何使输入数据类型限制,C#如何添加限制
  4. 10秒钟sublime text 3安装SVN插件
  5. 前端Html和Css面试题
  6. Spring基本概念
  7. mySQL CRUD操作(数据库的增删改查)
  8. JAVA赋值运算符
  9. Android实现数据存储技术
  10. android 电容屏(三):驱动调试之驱动程序分析篇
  11. TCP/IP协议原理与应用笔记16:交换机和路由器区别
  12. 搭建OA平台
  13. jQuery的css
  14. arguments对象
  15. 安卓开发笔记(二十):利用夜神模拟器调试运行Android Studio的apk
  16. promise源码解析
  17. Linux下不同文件不同颜色的意义
  18. [机器学习]正则化方法 -- Regularization
  19. 【转载】奇异值分解(SVD)计算过程示例
  20. springboot2系列目录

热门文章

  1. 1.Log4j入门
  2. Win10 C盘根目录权限
  3. 前台框架vue.js中怎样嵌入 Echarts 组件?
  4. 基于OpenGL编写一个简易的2D渲染框架-01 创建窗口
  5. Simple2D-16(音乐播放器)ImGui 库介绍
  6. vue深入了解组件——动态组件&amp;异步组件
  7. vc 读xml文件 宏
  8. break、continue、pass介绍
  9. mesos无执行器启动docker
  10. R及Rstuio下载及配置,及基本使用介绍