1229: [USACO2008 Nov]toy 玩具

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 338  Solved: 136
[Submit][Status][Discuss]

Description

玩具 [Chen Hu, 2006] Bessie的生日快到了, 她希望用D (1 <= D <= 100,000; 70%的测试数据都满足 1 <= D <= 500)天来庆祝. 奶牛们的注意力不会太集中, 因此Bessie想通过提供玩具的方式来使它们高兴. 她已经计算出了第i天需要的玩具数T_i (1 <= T_i <= 50). Bessie的幼儿园提供了许多服务给它们的奶牛程序员们, 包括一个每天以Tc (1 <= Tc <= 60)美元卖出商品的玩具店. Bessie想尽可能的节省钱, 但是Farmer John担心没有经过消毒的玩具会带来传染病(玩具店卖出的玩具是经过消毒的). 有两种消毒的方式. 第1种方式需要收费C1美元, 需要N1个晚上的时间; 第2种方式需要收费 C2美元, 需要N2个晚上的时间(1 <= N1 <= D; 1 <= N2 <= D; 1 <= C1 <= 60; 1 <= C2 <= 60). Bessie在party结束之后把她的玩具带去消毒. 如果消毒只需要一天, 那么第二天就可以拿到; 如果还需要一天, 那么第三天才可以拿到. 作为一个受过教育的奶牛, Bessie已经了解到节约的意义. 帮助她找到提供玩具的最便宜的方法.

Input

* 第 1 行: 六个用空格隔开的整数 D, N1, N2, C1, C2, Tc

* 第 2..D+1 行: 第 i+1 行包含一个整数: T_i

Output

第 1 行: 提供玩具所需要的最小费用.

Sample Input

4 1 2 2 1 3
8
2
1
6

输入解释:
Bessie想开4天的party, 第1天需要8个玩具, 第2天需要2个玩具, 第3天需要1个玩具,
第4天需要6个玩具. 第一种方式需要$2, 用时1天; 第二种方式需要$1, 用时2天. 买
一个玩具需要$3.

Sample Output

35
输出解释:
第 1 天 买8个玩具, 花去$24; 送2个玩具去快洗, 6个慢洗.
第 2 天 取回2个快洗的玩具, 花去$4. 送1个玩具去慢洗.
第 3 天 取回6个慢洗的玩具, 花去$6.
第 4 天 取回所有的玩具(与现有的加在一起正好6个), 花去$1. 这样就用了最少的钱.
 
  好久没刷不是考试的题了……
  liu_runda表示他看不下去我们现在刷的和考的题了,也不知道是不是他搞出来这一波奇奇怪怪的题……
  这道题上来我的打法是这样的:
    我每一天如果说买最便宜就光买就好了。
    对于快洗和慢洗分别开了一个类似于“洗衣池”的东西,记录一下有多少衣服可以被快洗/慢洗。然后对于慢洗(我们假定他比慢洗便宜)我们能用就用,然后看是买便宜还是快洗便宜,如果快洗便宜就从最新的可以快洗的快洗。然后,20分……
  好歹打了一个小时,又花了一个小时证出来它不对,留个代码祭奠一下。
 #include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#define N 100005
using namespace std;
int n,va1,va2,t1,t2,bu,t[N];
int sum[],ans,st[N],top;
int main()
{
freopen("toy.in","r",stdin);
freopen("toy.out","w",stdout);
scanf("%d%d%d%d%d%d",&n,&t1,&t2,&va1,&va2,&bu);
for(int i=;i<=n;i++)
{
scanf("%d",&t[i]);
}
if(va1>va2)swap(va1,va2),swap(t1,t2);
//cout<<endl;
int now=;
for(int i=;i<=n;i++)
{
if(i>t1) sum[]+=t[i-t1];
if(i>t2)
{
sum[]+=t[i-t2];
top++;
st[top]=i-t2;
}
if(bu<=va1&&bu<=va2)
{
ans+=bu*t[i];
continue;
}
if(sum[]>=t[i])
{
sum[]-=t[i];
ans+=va1*t[i];
if(t1>=t2)sum[]-=t[i];
}
else
{
ans+=va1*sum[];
if(t1>=t2)
{
sum[]-=sum[];
if(bu<=va2)
{
ans+=bu*(t[i]-sum[]);
}
else
{
if(sum[]>=t[i]-sum[])
{
ans+=va2*(t[i]-sum[]);
sum[]-=(t[i]-sum[]);
int js=;
while(top)
{
if(js+t[st[top]]>=t[i]-sum[])
{
t[st[top]]-=t[i]-sum[]-js;
if(!t[st[top]])top--;
break;
}
js+=t[st[top]];
t[st[top]]=;
top--;
}
}
else
{
ans+=va2*sum[];
while(top)
{
t[st[top]]=;
top--;
}
ans+=bu*(t[i]-sum[]-sum[]);
sum[]=;
}
}
}
else
{
ans+=bu*(t[i]-sum[]);
}
sum[]=;
}
//cout<<ans<<endl;
}
printf("%d\n",ans);
return ;
}

  为什么这么打不对呢?假设我们快洗和买相差无几,但是慢洗要便宜很多,那么我们在较早的时间快洗会导致之后的慢洗无法使用现在的玩具,导致虽然我们在当时省了一点小钱,但最终我们丢了大钱(好有哲理啊)。

  那么我们到底该怎么办呢?

  我们上面这种打法之所以不对,是因为我们把原本应该买新玩具的地方使用了快洗,那么我们为什么不能通过确定我们总共要买多少玩具来避免呢?当然可以,但对于买的玩具的个数我们枚举肯定是不行的,那么二分可以吗?用十二指肠想一想也知道不行,那么我们能否用三分呢?好像是可以的,假设我们免费买,那么我们买的越多花的钱越少,但实际还是要花钱去买的,所以貌似就是一个三分。之前在cgh_Andy的题解中发现了证明,大家想看可以去看一下(据说还有拿导数证的%%%)。

  那么我们既然知道了三分的值,我们就可以按照类似与我之前的方法进行贪心,唯一不一样的是这次我们能买就买。别的还是照常,维护一个双向队列就好了。

 #include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#define N 100005
using namespace std;
int n,va1,va2,t1,t2,bu,t[N],a[N];
int sum,mx,q[N],hea,en;
int check(int x)
{
hea=,en=;
memset(q,,sizeof(q));
memcpy(a,t,sizeof(t));
int ans=x*bu;
for(int i=;i<=n;i++)
{
if(i>t2)
{
en++;
q[en]=i-t2;
}
if(t[i]<=x)
{
x-=t[i];
continue;
}
for(int j=t[i]-x;j;)
{
if(en<hea)return 0x7fffffff;
if(q[hea]<=i-t1)
{
int k=min(a[q[hea]],j);
a[q[hea]]-=k,j-=k;
ans+=va1*k;
if(!a[q[hea]])hea++;
}
else
{
int k=min(a[q[en]],j);
a[q[en]]-=k,j-=k;
ans+=va2*k;
if(!a[q[en]])en--;
}
}
if(x)x=;
}
return ans;
}
int main()
{
scanf("%d%d%d%d%d%d",&n,&t1,&t2,&va1,&va2,&bu);
for(int i=;i<=n;i++)
{
scanf("%d",&t[i]);
sum+=t[i];
mx=max(mx,t[i]);
}
if(va1>va2)swap(va1,va2),swap(t1,t2);
int li=mx,ri=sum;
while(li<ri-)
{
int lmid=(li*+ri)/,rmid=(li+ri*)/;
int ans1=check(lmid),ans2=check(rmid);
if(ans1<ans2)ri=rmid;
else li=lmid;
} int ans=0x7fffffff;
for(int i=li;i<=ri;i++)
{
ans=min(check(i),ans);
}
printf("%d\n",ans);
return ;
}

  Ps:一开始交上去还T了,因为打错了三分,我是不是该找一些三分的题练一下,因为我貌似还没有一次自己打过三分成功的说。

Bzoj 1229: [USACO2008 Nov]toy 玩具 题解 三分+贪心的更多相关文章

  1. BZOJ 1229 [USACO2008 Nov]toy 玩具(三分+贪心)

    [题木链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1229 [题目大意] 每天对玩具都有一定的需求ni,每天可以花f价值每条购买玩具, 当天 ...

  2. BZOJ 1229: [USACO2008 Nov]toy 玩具

    BZOJ 1229: [USACO2008 Nov]toy 玩具 标签(空格分隔): OI-BZOJ OI-三分 OI-双端队列 OI-贪心 Time Limit: 10 Sec Memory Lim ...

  3. BZOJ_1229_[USACO2008 Nov]toy 玩具_三分+贪心

    BZOJ_1229_[USACO2008 Nov]toy 玩具_三分+贪心 Description 玩具 [Chen Hu, 2006] Bessie的生日快到了, 她希望用D (1 <= D ...

  4. BZOJ1229 USACO2008 Nov toy 玩具 【三分+贪心】*

    BZOJ1229 USACO2008 Nov toy 玩具 Description 玩具 [Chen Hu, 2006] Bessie的生日快到了, 她希望用D (1 <= D <= 10 ...

  5. 【BZOJ】1229 [USACO2008 Nov]toy 玩具

    [算法]三分+贪心 [题解] 数据范围小的版本:餐巾计划 这题不是使用最小费用流的下凸函数,因为这题是要满足最大流,那么这题到底在三分什么? 三分的这个函数,其实是总费用随卖出玩具量变化而变化的函数, ...

  6. BZOJ1229 & 洛谷2917:[USACO2008 NOV]toy 玩具 & 洛谷4480:[BJWC2018]餐巾计划问题——题解

    标题很长emmm…… [USACO2008 NOV]toy 玩具 https://www.luogu.org/problemnew/show/P2917 https://www.lydsy.com/J ...

  7. BZOJ 1230: [Usaco2008 Nov]lites 开关灯( 线段树 )

    线段树.. --------------------------------------------------------------------------------- #include< ...

  8. BZOJ 1619: [Usaco2008 Nov]Guarding the Farm 保卫牧场

    题目 1619: [Usaco2008 Nov]Guarding the Farm 保卫牧场 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 491  S ...

  9. BZOJ 1618: [Usaco2008 Nov]Buying Hay 购买干草

    题目 1618: [Usaco2008 Nov]Buying Hay 购买干草 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 679  Solved:  ...

随机推荐

  1. SDP开发平台试用版上线!提供源码!!!!

    SDP开发平台提供试用版!! SDP软件快速开发平台是一套面向对象的应用软件快速开发平台. 1.SDP 设计端--页面设计 通过简单的拖拉控件,或者快速生成控件,可以在几分钟快速制作一个页面:如图 通 ...

  2. C#数字图像处理算法详解大全

    原文:C#数字图像处理算法详解大全 C#数字图像处理算法详解大全 网址http://dongtingyueh.blog.163.com/blog/#m=0 分享一个专业的图像处理网站(微像素),里面有 ...

  3. 分布式文件系统的比较,115网盘用了fastdfs

    分布式文件系统 分布式文件系统,作为网盘的基础,应用底层文件管理.而分布式文件系统之上,用户文件的权限,用户目录管理都是由非分布式文件系统管理. 分布式文件系统需要关心的主要内容: 文件分布/数据分布 ...

  4. Qt 5.9对Mac的图形显示有许多改进

    We have some platform specific improvements as well as support for new platforms and compilers comin ...

  5. shell中select、case的使用

    case和select结构在技术上说并不是循环, 因为它们并不对可执行代码块进行迭代. 但是和循环相似的是, 它们也依靠在代码块顶部或底部的条件判断来决定程序的分支. select   select结 ...

  6. 初涉Delphi Socket编程

    不是第一次接触socket编程了,但以前都是看别人的依葫芦画瓢,也不知道具体的原理. 新的项目,有了新的开始,同时也需要有新的认识. Delphi 中带有两套TCP Socket组件: Indy So ...

  7. jconsole远程监控logstash agent

    在logstash的jvm.options文件末尾添加: -Dcom.sun.management.jmxremote.port=9999   //指定jmx端口-Dcom.sun.managemen ...

  8. C C++ Java C# JS编译、执行过程的原理入门分析

    C.C++是典型的编译型编程语言,编译链接后,点击则可执行. JS,解释型脚本语言,则不需要进行编译,直接解释执行. Java和C#则是所谓的高级语言,编译执行的方式做了很多处理, 尤其是C#,VS编 ...

  9. es6基本语法,vue基本语法

    一.es6基本语法 0.es6参考网站 http://es6.ruanyifeng.com/#README 1.let 和 const (1)const特点: 只在局部作用域起作用 不存在变量提升 不 ...

  10. python发送邮件554DT:SPM已解决

    说明:本例使用163邮箱 一.报错信息 使用SMTP发送邮件遇到以下报错: 554, b'DT:SPM 163 smtp10,DsCowACXeOtmjRRdsY8aCw--.21947S2 1561 ...