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. Win8 Metro(C#)数字图像处理--2.71Sigma平滑滤波器

    原文:Win8 Metro(C#)数字图像处理--2.71Sigma平滑滤波器  [算法说明]   Sigma平滑滤波器是构造一个模板,比如3*3大小的模板,计算这个模板对应的像素的标准差d,然后 ...

  2. 微信小程序把玩(四十一)canvas API

    原文:微信小程序把玩(四十一)canvas API 绘图是每个移动应用必备的技术,基本上和Android,IOS,等移动开发都是相同的,创建个上下文,给你个画布再上画,官网给的小例子都比较全了自己去看 ...

  3. 传入字典的模型项的类型为“System.Boolean”,但此字典需要类型“InternalCRM.EntityIACrm.Template”的模型项。

    “/”应用程序中的服务器错误. 传入字典的模型项的类型为“System.Boolean”,但此字典需要类型“InternalCRM.EntityIACrm.Template”的模型项. 说明: 执行当 ...

  4. 企业级架构 MVVM 模式指南 (WPF 和 Silverlight 实现) 译(2)

    本书包含的章节内容 第一章:表现模式,以一个例子呈献给读者表现模式的发展历程,我们会用包括MVC和MVP在内的各种方式实现一个收费项目的例子.沿此方向,我们会发现每一种模式的问题所在,这也是触发设计模 ...

  5. nyoj7——街区最短问题

    描述 一个街区有很多住户,街区的街道只能为东西.南北两种方向. 住户只可以沿着街道行走. 各个街道之间的间隔相等. 用(x,y)来表示住户坐在的街区. 例如(4,20),表示用户在东西方向第4个街道, ...

  6. Qt 跨UI线程的数据交换和信号-槽调用实现方案汇总

    一.目录 转载1: http://my.oschina.NET/fanhuazi/blog/737224?ref=myread 点击打开链接 转载2: http://www.qtcn.org/bbs/ ...

  7. WebRequest请求错误(服务器提交了协议冲突. Section=ResponseHeader Detail=CR 后面必须是 LF)

    WebRequest请求错误(服务器提交了协议冲突. Section=ResponseHeader Detail=CR 后面必须是 LF)解决办法,天津config文件,增加一个配置如下 <?x ...

  8. cmake常用工程示例大集合

    1 简单的可执行文件生成工程 1.1 源文件   main.cpp #include <stdio.h> int main(int argc, char *argv[]) { printf ...

  9. Qt Style Sheet实践(二):组合框QComboBox的定制(24K纯开源)——非常漂亮

    组合框是一个重要且应用广泛的组件,一般由两个子组件组成:文本下拉单部分和按钮部分.在许多既需要用户选择.又需要用户手动输入的应用场景下,组合框能够很好的满足我们的需求.如我们经常使用的聊天软件QQ登录 ...

  10. 减少Qt编译时间暨简单Qt裁剪

    本站所有文章由本站和原作者保留一切权力,仅在保留本版权信息.原文链接.原文作者的情况下允许转载,转载请勿删改原文内容, 并不得用于商业用途. 谢谢合作.原文链接:减少Qt编译时间暨简单Qt裁剪 编译一 ...